LPDIRECT3DTEXTURE9 get pixel
Hi,
Nice simple question
How do I get the value of a pixel of a loaded texture at a given position in the texture.
Its nice and easy using hlsl...
tex2D(Texture, Pos )
But I can't use hlsl in this case.
Thanks for the help!
C.
You need to LockRect() the texture, then read from it.
Note that locking a texture is a very expensive thing to do, so you'd usually want to lock the entire texture, read a bunch of pixels, then unlock it.
Example code, assuming you just want to read one pixel:
That assumes a 32-bit texture, if it's not then you'll have to adjust the code accordingly.
Note that locking a texture is a very expensive thing to do, so you'd usually want to lock the entire texture, read a bunch of pixels, then unlock it.
Example code, assuming you just want to read one pixel:
D3DCOLOR readPixel(LPDIRECT3DTEXTURE9 pTexture, UINT x, UINT y){ // Lock the texture: D3DLOCKED_RECT rect; HRESULT hResult = pTexture->LockRect(0, &rect, NULL, D3DLOCK_READONLY); if(FAILED(hResult)) { // Failed to lock the texture, error return 0; } // Get the bits as a BYTE* const BYTE* pBits = rect.pBits; // Seek to the correct pixel and read it DWORD nBytesPerPixel = 4; const DWORD* pPixel = (DWORD*)(pBits + y * rect.Pitch + x*nBytesPerPixel); DWORD dwPixel = *pPixel; // Unlock the texture pTexture->UnlockRect(0); // Return the pixel return dwPixel;}
Cheers for the reply
I'm using a 8 bit rgb heightmap. But its a grayscale.
The function seems to be returning really big numbers.
I was expecting a value between 0 and 255.
Any ideas?
Thanks
C.
I'm using a 8 bit rgb heightmap. But its a grayscale.
The function seems to be returning really big numbers.
I was expecting a value between 0 and 255.
Any ideas?
Thanks
C.
Quote:Original post by colinolivantYes, that function assumes a 32-bit texture. For 8-bit you'd want:
Cheers for the reply
I'm using a 8 bit rgb heightmap. But its a grayscale.
The function seems to be returning really big numbers.
I was expecting a value between 0 and 255.
Any ideas?
Thanks
C.
BYTE readPixel(LPDIRECT3DTEXTURE9 pTexture, UINT x, UINT y){ // Lock the texture: D3DLOCKED_RECT rect; HRESULT hResult = pTexture->LockRect(0, &rect, NULL, D3DLOCK_READONLY); if(FAILED(hResult)) { // Failed to lock the texture, error return 0; } // Get the bits as a BYTE* const BYTE* pBits = rect.pBits; // Seek to the correct pixel and read it BYTE byPixel = pBits[y * rect.Pitch + x]; // Unlock the texture pTexture->UnlockRect(0); // Return the pixel return byPixel;}
Hi I know this is problem has been fixed but i've got a another problem related to this...
I now want to write to a texture.
The whole reason i want to do this is because 0-255 isn't enough detail for a heightmap i need somelike like a short which i think is 16-bit i.e. 0 to 32767
The texture is 16-bit heightmap so i guess i should create the texture using D3DFMT_R16F?
Then writing to the texture something like...
But this ain't working....
I think i'm getting confused between 8,16,32 bit textures, any one explain?
Also if i use D3DFMT_R16F will i be able to do this in a pixel shader?
Thanks for any help in advance, and big thanks for Evil Steve!!!
I now want to write to a texture.
The whole reason i want to do this is because 0-255 isn't enough detail for a heightmap i need somelike like a short which i think is 16-bit i.e. 0 to 32767
The texture is 16-bit heightmap so i guess i should create the texture using D3DFMT_R16F?
if ( FAILED( D3DXCreateTexture( DXUTGetD3DDevice(), 4096, 4096, 1, 0, D3DFMT_R16F, D3DPOOL_DEFAULT, &HeigthTexture ) ) ) { exit(-1); }
Then writing to the texture something like...
IDirect3DSurface9 * surface = 0; // get surface of first mip level texture->GetSurfaceLevel(0, &surface); // get description of the surface (width, height etc) D3DSURFACE_DESC desc; texture->GetLevelDesc(0, &desc); D3DLOCKED_RECT locked; // lock whole surface for read-only access surface->LockRect(&locked, 0, D3DUSAGE_WRITEONLY); DWORD* imageData = (DWORD*)locked.pBits; short u = 0; for(int h = 0; h < desc.Height; h++) { for(int j = 0; j < desc.Width; j++) { imageData[h * (locked.Pitch) + j] = u; } } surface->UnlockRect(); surface->Release();}
But this ain't working....
I think i'm getting confused between 8,16,32 bit textures, any one explain?
Also if i use D3DFMT_R16F will i be able to do this in a pixel shader?
tex2D(texture,postion).r
Thanks for any help in advance, and big thanks for Evil Steve!!!
your imageData pointer is a pointer to a DWORD, which is an unsigned long. You probably want a pointer to a short, so that when you advance it or index it, it uses the correct size.
Also, the pitch is provided in bytes, not in shorts or DWORDs. Either use a pointer to byte and advance it by the pitch to get the start of each row, or divide the pitch by the size of a short (I wouldn't recommend this).
Also, R16F means a 16bit floating point value, you're using a 16bit signed integer format, so the data you're writing wouldn't fit the texture type you're creating.
You need to pick the data type you want to store in the texture and keep consistent about using it.
Also, the pitch is provided in bytes, not in shorts or DWORDs. Either use a pointer to byte and advance it by the pitch to get the start of each row, or divide the pitch by the size of a short (I wouldn't recommend this).
Also, R16F means a 16bit floating point value, you're using a 16bit signed integer format, so the data you're writing wouldn't fit the texture type you're creating.
You need to pick the data type you want to store in the texture and keep consistent about using it.
Right I think i'm getting there. The formats look better now but i just dont know how to write to the pixel...
The format is now D3DFMT_D16, this right?
Thanks for the help
IDirect3DSurface9 * surface = 0; // get surface of first mip level texture->GetSurfaceLevel(0, &surface); // get description of the surface (width, height etc) D3DSURFACE_DESC desc; texture->GetLevelDesc(0, &desc); D3DLOCKED_RECT locked; // lock whole surface for read-only access surface->LockRect(&locked, 0, D3DUSAGE_WRITEONLY); short *pData; BYTE* pBits = (BYTE*)locked.pBits; for (int y=0; y<4096; y++) { for (int x=0; x<4096; x++) { //WTF pBits[x] = (short)0; } pBits += locked.Pitch; } // important, clean up! surface->UnlockRect(); surface->Release();
The format is now D3DFMT_D16, this right?
Thanks for the help
Quote:Original post by colinolivantD3DFMT_D16 is a depth buffer format, and it's not directly usable by the application - the driver is free to use those 16 bits however it wants, there's nothing to say what format it's in. It could be a 16-bit floating point number, it could be a short, or it could be some other scale.
Right I think i'm getting there. The formats look better now but i just dont know how to write to the pixel...
*** Source Snippet Removed ***
The format is now D3DFMT_D16, this right?
Thanks for the help
What you want for a 16-bit format is something liek this:
short *pData;BYTE* pRawBits = (BYTE*)locked.pBits;for (int y=0; y<4096; y++){ // Get this scanline as a short* short* pBits = (short*)pRawBits; for (int x=0; x<4096; x++) { // pBits is a short* now, not a BYTE* pBits[x] = (short)0; } // Advance the BYTE* to point to the next scanline pRawBits += locked.Pitch;}
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement