SOLVED] How to modify the contents of a texture at runtime

Started by
10 comments, last by RobM 14 years, 9 months ago
Hi all I'm trying to modify the contents of a texture dynamically (using DirectX9). It's an 8bit grayscale texture and what I'm currently doing is locking the texture like this:

D3DLOCKED_RECT lockedRect;
globalBlendMapTexture->LockRect(0, &lockedRect, 0, D3DLOCK_DISCARD);
blendMapData = (BYTE*)lockedRect.pBits;
blendMapPitch = lockedRect.Pitch;
...
int stride = blendMapPitch / width;
blendMapData[(y * blendMapPitch) + (x * stride)] = newValue;
globalBlendMapTexture->Unlock(0);



This works fine. I have something almost identical for getting the colour at a particular point and when I set the new colour and do a lookup, it gives me the new colour as expected. The problem I have is that this new colour doesn't show when doing a lookup in my pixel shader, it still uses the old colour. I load the globalBlendMapTexture using this:

HRESULT hr = D3DXCreateTextureFromFileEx( device, L"some bitmap.bmp",
D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT,
D3DUSAGE_DYNAMIC, D3DFMT_UNKNOWN, 
D3DPOOL_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 
0, NULL, NULL, &globalBlendMapTexture);




As per the MS docs, I've created it using D3DUSAGE_DYNAMIC and D3DPOOL_DEFAULT which should allow lockable textures (that bit works anyway by the looks of it). Is there something else I need to do for the pixel shader to pick up the change? I thought this would have been handled by the driver. Thanks [Edited by - RobMaddison on June 24, 2009 2:49:12 PM]
Advertisement
Hi,

There must be an UnlockRect() function at the end of your update work. I couldn't see it. Maybe that's your problem.
There's no "hard", and "the impossible" takes just a little time.
Thanks for the quick response, I do unlock the texture each time,
I just forgot to add that bit to my snippet.

Should this be possible the way I'm doing it or do I need to use surfaces
or something like that?
Quote:do I need to use surfaces

I don't think so.

I'm using D3DXFillTexture(). But if you use a pixel's old color to calculate the new color, it's not useful.
There's no "hard", and "the impossible" takes just a little time.
Quote:Original post by RobMaddison
Thanks for the quick response, I do unlock the texture each time,
I just forgot to add that bit to my snippet.

Should this be possible the way I'm doing it or do I need to use surfaces
or something like that?
Nope, textures are the way to go.

All that looks fine to me though - some things you could try:
1. Are you absolutely positive that you're calling SetTexture() to set the correct texture?
2. Any output from the Debug Runtimes?
3. Have you tried using D3DXSaveTextureToFile to save the texture to a file and check that it contains what you expect?
4. If you don't use a pixel shader, and let the fixed function pipeline take over, does it work then?
Perhaps you need to regenerate the mipmaps?
I'm not sure whether or not it's done automatically when you change the texture by locking it.. though I'm sure someone else can shed some light on this. =)
At first, relock texture rect and check if pixel was changed.
Anyway, if you change texture during rendering i think you should reupload it entirely to the GPU. So you should reset texture in the shader, after the change.
Quote:Original post by Erik Rufelt
Perhaps you need to regenerate the mipmaps?
I'm not sure whether or not it's done automatically when you change the texture by locking it.. though I'm sure someone else can shed some light on this. =)
Actually, that sounds like a likely problem - the texture has a full mipmap chain generated for it when it's loaded, but you only update the top mip level. Either change the 5th parameter to D3DXCreateTextureFromFileEx to 1 instead of D3DX_DEFAULT, or lock and update all surface levels.
Quote:1. Are you absolutely positive that you're calling SetTexture() to set the correct texture?

This texture is a fundamental part of my rendering (blending) process so it is definitely set.

Quote:2. Any output from the Debug Runtimes?

I haven't checked these. Mostly because it looks like it is working from within the code, i.e. when I set a pixel to a different value and then retrieve it again from the texture, I get returned the new pixel value as expected.

Quote:3. Have you tried using D3DXSaveTextureToFile to save the texture to a file and check that it contains what you expect?

I haven't no, that's a good idea, I'll try that a bit later. I have a little test in my pixel shader that indicates whether the relevant pixel has changed colour. So in my code I dynamically change this particular pixel to value 68 and in the shader, I check that pixel to see if it is 68 - if it is, all geometry turns white. If I start the program with 68 in that value in the texture, the relevant geometry is white (so the test works).

Quote:4. If you don't use a pixel shader, and let the fixed function pipeline take over, does it work then?

My pixel shader is relatively complex, how would I let the fixed function pipeline 'take over'?

Thanks
Quote:Original post by RobMaddison
Quote:4. If you don't use a pixel shader, and let the fixed function pipeline take over, does it work then?

My pixel shader is relatively complex, how would I let the fixed function pipeline 'take over'?
Well, you can strip stuff out and render the texture applied to a basic triangle. I know that might be a bit of work to do though...

This topic is closed to new replies.

Advertisement