PDA

View Full Version : need help to fill my texture



virtual
13-10-2009, 09:09 AM
hi all


got access violation prob when trying to fill the texture , exactly when computing the next scanline .



procedure CopyImageToTexture(pSrc : array of byte; xWidth, yHeight,var _texture :IDirect3DTexture9);
var
d3drc : D3DLOCKED_RECT;
pDest : PDWORD;
nPixel: integer;
r,g,b : BYTE;
nRow : integer;

begin


_texture.LockRect(0, d3drc, NIL, 0);

d3drc.Pitch := d3drc.Pitch shr 2;

for nRow := 0 to yHeight -1 do
begin
// set destination pointer for this row

pDest := DWORD(d3drc.pBits) + nRow * d3drc.Pitch ; // problem here

// copy the row

for nPixel := 0 to xWidth-1 do
begin
// extract pixel data

r := pSrc[nPixel];
g := pSrc[nPixel+1];
b := pSrc[nPixel+2];

// write color word to texture

inc(pDest^, $FF000000 or (r shl 16) or (g shl 8) or b);

end;
end;

_tex.UnlockRect(0);




any solution would be great

thanks

Galfar
13-10-2009, 12:40 PM
Why are you dividing Pitch by 4?


pDest := DWORD(d3drc.pBits) + nRow * d3drc.Pitch ;
Try this instead:

pDest := @PByteArray(d3drc.pBits)[nRow * d3drc.Pitch]; // original pitch, not /4 one


inc(pDest^, $FF000000 or (r shl 16) or (g shl 8) or b);
This is wrong too, you don't increase the address stored in pDest,
just the value it points to.

Did you write this code by converting from C++?

virtual
13-10-2009, 03:09 PM
thnx
yes this is a converting from c++ code
the original code looks like this


bool CopyImageToTexture(UCHAR *pSrc, int xWidth, int yHeight, LPDIRECT3DTEXTURE8 pTex, int xPos, int yPos)
{
D3DLOCKED_RECT d3drc;
UCHAR r, g, b;
UINT *pDest;
int nRow, nPixel;

// lock the texture

if (FAILED(pTex->LockRect(0, &d3drc, NULL, 0)))
return false;

// adjust pitch from bytes to UINTs

d3drc.Pitch >>= 2;

// copy the image

for (nRow = 0; nRow < yHeight; nRow++)
{
// set destination pointer for this row

pDest = (UINT*)d3drc.pBits + (nRow + yPos) * d3drc.Pitch + xPos;

// copy the row

for (nPixel = 0; nPixel < xWidth; nPixel++)
{
// extract pixel data

r = *pSrc++;
g = *pSrc++;
b = *pSrc++;

// write color word to texture

(*pDest++) = 0xFF000000 | (r << 16) | (g << 8) | b;
}
}

// unlock texture

pTex->UnlockRect(0);


// return success

return true;
}


i don't know whats the best replacment for UCHAR *pSrc , i used array of byte

tpascal
13-10-2009, 03:51 PM
another error:



for nPixel := 0 to xWidth-1 do
begin
// extract pixel data

r := pSrc[nPixel];
g := pSrc[nPixel+1];
b := pSrc[nPixel+2];



Note how in the FOR loop Npixel is incremented by 1, when npixel = 0 it works like you think, but note when npixel = 1 then "r" will have the value you placed in "g" in prior interations, and so on. Instead using "npixel" for your array index you need to use a index that is incremented by 3.


Your fill texture rutine works placing pixel by pixel; i guess you do that becouse the source texture is not in the same format as the target; but if for any chance both source and target are the same format and size then i suggest you just copy the whole block memory from source to target, one simple move() pascal procedure will do the job.

NecroDOME
13-10-2009, 04:23 PM
This is how I do it:

D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8:
begin
pb := pbyte(Cardinal(FRect.pBits) + y * Cardinal(FRect.pitch) + x * 4);
pb^ := b;
inc(pb);
pb^ := g;
inc(pb);
pb^ := r;
inc(pb);
pb^ := a;
end;
x and y is the x and the y in the texture. FRect is TD3DLockedRect.

virtual
13-10-2009, 04:39 PM
Note how in the FOR loop Npixel is incremented by 1, when npixel = 0 it works like you think, but note when npixel = 1 then "r" will have the value you placed in "g" in prior interations, and so on. Instead using "npixel" for your array index you need to use a index that is incremented by 3.


thnx , i haven't see this bug :-[

i need to copy the whole block pixel per pixel , in case of a trensparent texture
i've to set alpha channel also while looping .

@NecroDOME , thnx for the code , but didn't work

Galfar
13-10-2009, 04:43 PM
@NecroDOME , thnx for the code , but didn't work

You need to change
pDest : PDWORD;
from your original code to
pDest: PByte

inc(pb) in Necro's code increases address by 1, but if you use inc(pDest) where pDest is PDWORD it increases address by 4.

virtual
13-10-2009, 07:40 PM
yes i change it just like what did

here is the Project http://www.mediafire.com/?dmsxk0nkez2


i am lost

VilleK
14-10-2009, 01:20 PM
You did not include texture.bmp but your code works here if you change it like this:



procedure DxTexture.CopyImageToTexture(pSrc :Pbyte; xWidth, yHeight, xPos, yPos :integer);
var
d3drc : D3DLOCKED_RECT;
pDest : PBYTE;
nPixel: integer;
r,g,b : BYTE;
nRow : integer;
begin
_tex.LockRect(0, d3drc, NIL, 0);
for nRow := 0 to yHeight -1 do
begin
pDest := pbyte(Cardinal(d3drc.pBits) + (nrow+ypos) * d3drc.pitch + xpos*4);
for nPixel := 0 to xWidth-1 do
begin
r := pSrc^; inc(pSrc);
g := pSrc^; inc(pSrc);
b := pSrc^; inc(pSrc);

pDest^ := r; inc(pDest);
pDest^ := g; inc(pDest);
pDest^ := b; inc(pDest);
pDest^ := 0; inc(pDest);
end;
end;
_tex.UnlockRect(0);
end;

virtual
15-10-2009, 04:10 PM
yes it works , thnx for the help

and all the other members