Sign in to follow this  
QuadMV

Getting color data from a loaded texture

Recommended Posts

QuadMV    168
I have a texture loaded from a file using: D3DXCreateTextureFromFile It works fine. However, I want to get the color buffer comprising the texture out of the LPDIRECT3DVERTEXBUFFER9 variable How do I do this? I assume I need some combination of getsurface and getprivatedata? I'm not sure of the exact code. If anyone could provide a snipet of what I need to do I'd appreciate it. Thanks

Share this post


Link to post
Share on other sites
PumpkinPieman    382
First of all you want to get the texture data out of LPDIRECT3DTEXTURE9 not LPDIRECT3DVERTEXBUFFER9, hah.

The method is simple, lock a portion of the texture and it will give you a pointer to the pixel data. If you specify NULL for the selected RECT it will lock the entire texture.


DWORD m_pixelbytes;
DWORD* m_ptr;

bool cTexture::Lock(LPRECT rect, bool ReadOnly)
{
D3DLOCKED_RECT data;

if(FAILED(texture->LockRect(0, &data, rect, 0)))
return false;

m_ptr = (DWORD*)data.pBits;
m_pixelbytes = data.Pitch / sizeof(DWORD);

return true;

};

void cTexture::Unlock()
{
texture->UnlockRect(0);
};

// Basic use
DWORD cTexture::GetPixel(long x, long y)
{
return m_ptr[m_pixelbytes*y+x];
};



Share this post


Link to post
Share on other sites
QuadMV    168
I knew it was texture, not vertex. That was a cut/paste mistake, but thanks for keeping me honest.

I almost got what you showed working, but does the opposite work? If I modify the data can I write the changed data back to the texture? I'm not getting errors doing so, but the texture isn't changing, so I'm sure I'm missing something.

I have the RECT set to NULL which I think means the entire rect, right?

Thanks


Also, the texture I loaded was 320x320, but data.Pitch / sizeof(DWORD); comes back as 128, not 320. Does DirectX auto resize the texture?

Thanks again

Share this post


Link to post
Share on other sites
Drakex    273
Quote:
I almost got what you showed working, but does the opposite work? If I modify the data can I write the changed data back to the texture? I'm not getting errors doing so, but the texture isn't changing, so I'm sure I'm missing something.


What might be happening is that the texture is being modified, but only the base-level mipmap. If you're using mipmaps, and only the base-level mipmap is being modified, the changes won't be apparent unless you're really close to the object. What you can do is use the D3DUSAGE_AUTOGENMIPMAPS flag when creating the texture. For that matter, why don't you post the code that creates the texture? The problem might be there.

Quote:
I have the RECT set to NULL which I think means the entire rect, right?


Yes.

Quote:
Also, the texture I loaded was 320x320, but data.Pitch / sizeof(DWORD); comes back as 128, not 320. Does DirectX auto resize the texture?


Yes. It will be resized to the next-largest power of two, in your case a 512x512 texture.

..Wait a second. Why is it 128? The pitch should be 2048, giving you a image pixel width of 512. Are you using a DXT compressed texture?

Share this post


Link to post
Share on other sites
PumpkinPieman    382
It may also depend on the colour format the texture was created in as well.

Quote:

The pitch for DXTn formats is different from what was returned in Microsoft DirectX 7.0. It now refers to the number of bytes in a row of blocks. For example, if you have a width of 16, then you will have a pitch of 4 blocks (4*8 for DXT1, 4*16 for DXT2-5.)


Try using unsigned short instead of a DWORD and see if it makes any differece.

I'm really not sure otherwise.

Share this post


Link to post
Share on other sites
QuadMV    168
The image is a greyscale, so would I need to use char instead of DWORD or short?

When I sue char I get 2048, wich I think makes sence if the image is 320, you said it rounds it to 512, then I assume it gets converted to an ARGB image, so it's 512*4 or 2048. Is that right?

Therefore, to copy the image with memcpy, would it be 2048*2048?

Thanks

Share this post


Link to post
Share on other sites
QuadMV    168
For what it's worth, I changed it from char to sizeof(D3DCOLOR) and it's giving me 512, and the copy seems to be working ok.

However, when I modify, I'm still not seeing the modified contents.

I'm going to try D3DUSAGE_AUTOGENMIPMAPS and see if it makes a difference

Share this post


Link to post
Share on other sites
QuadMV    168
I changed my code from

//D3DXCreateTextureFromFile(pd3dDevice, map, &mTerrainTexture[97]);

to

D3DXCreateTextureFromFileExW(pd3dDevice, map, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, &mTerrainTexture[97] );

But, I'm not sure how/where to specify D3DUSAGE_AUTOGENMIPMAPS, I tried to put it on MipFilter, but then I found D3DUSAGE_AUTOGENMIPMAPS is unknown/undeclared identifier.

Any suggestions?

Share this post


Link to post
Share on other sites
Drakex    273
Put it in the Usage parameter, the 6th one. The one you have set to 0. And I messed up - it's AUTOGENMIPMAP, no S.

Hey, try this, and tell us what number comes out:


D3DXCreateTextureFromFileExW(pd3dDevice, map, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, D3DUSAGE_AUTOGENMIPMAP, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, &mTerrainTexture[97] );

IDirect3DSurface9* sfc;
mTerrainTexture[97]->GetSurfaceLevel(0,&sfc);
D3DSURFACE_DESC desc;
sfc->GetDesc(&desc);

// output the desc.Format member somehow, with a messagebox or log or whatever you use

sfc->Release();





Share this post


Link to post
Share on other sites
QuadMV    168
I'm getting closer, but not quite there. Here is the output you requested:

desc {Format=D3DFMT_X8R8G8B8 Type=D3DRTYPE_SURFACE Usage=0 ...} _D3DSURFACE_DESC

Format D3DFMT_X8R8G8B8 _D3DFORMAT
Type D3DRTYPE_SURFACE _D3DRESOURCETYPE
Usage 0 unsigned long
Pool D3DPOOL_MANAGED _D3DPOOL
MultiSampleType D3DMULTISAMPLE_NONE _D3DMULTISAMPLE_TYPE
MultiSampleQuality 0 unsigned long
Width 512 unsigned int
Height 512 unsigned int

When I added AUTOGENMIPMAP to the 6th field, everything is compiling now, but my texture is appearing as blank.

I commented out all the code that modifies the data copies it and copy it back, so I'm just rendering with a standard texture, nothing funky. If I create the texture using a zero, it renders perfect, but if I create the texture with AUTOGENMIPMAP, it renders blank.

Is there something else I need to do when there are no mipmaps.

Now that I’ve said that, writing that question above gave me an idea. I changed the code back to using a zero, and I added back the code to modify the data, then I changed the samplerstate and turned off mipmapping. This seems to have done the trick. Can someone just confirm that I’m turning it off just for this object, and that samplerstate isn’t some sort of global setting. I am resetting it when I’m done drawing the one texture I’m playing around with.

Thanks all for your patience. Sorry if this is getting too crazy.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this