Skip to main content
GameDev.net gamedev.net
🔒 Locked

IDirect3DTexture9

Started by ryt Sep 4, 2005 at 10:28 AM 13 replies 1.8k views
Original Post
ryt
ryt
for textures i use IDirect3DTexture9. How can i lock the texture and then update its pixels?
Scet
Scet
You have to get a pointer to a texture/render-target/buffer to edit it pixel-by-pixel. Say you created a 32-bit 256x256 colour texture, it would look something like this:

(might not be 100% correct)
LPDIRECT3DTEXTURE8 Txr;D3DLOCKED_RECT Rc;unsigned int* Pntr;D3DXCreateTexture(D3DDevice,256,256,0,0,D3DFMT_A8R8G8B8,D3DPOOL_MANAGED,&Txr)Txr->LockRect(0,&Rc,NULL,D3DLOCK_NOSYSLOCK);Pntr=(unsigned int *)Rc.pBits;Pntr[(10*256)+80]=0xFF00FF00; //plots a full green pixel at 80,10//do more drawingTxr->UnlockRect(0);


This only works for power-of-2 textures as I left of the stuff for padding. Also be aware that if you use a 16-bit format like A1R5G5B5 then you would need an unsigned short pointer instead of unsigned int/long.

Also if you want to create images out of raw pixel data check out D3DXLoadSurfaceFromMemory().

This has been asked alot. Look through the DirectX forum some more and I'm sure you'll see more examples.
ryt
ryt
thx, i hope it works. ill use D3DPOOL_DEFAULT
Agony
Agony
Check to make sure LockRect() returns a successful HRESULT, and also check to make sure that Rc.pBits is not NULL. The LockRect() call might have failed because the lock flags weren't valid for the texture type. Try D3DLOCK_NOSYSLOCK | D3DLOCK_DISCARD for your lock flags, instead of just D3DLOCK_NOSYSLOCK. Or look up LockRect() in the documentation to get more details.

The reason why you would use an unsigned int pointer in this case is because an unsigned int is (almost always) the same size as a D3DMT_A8R8G8B8 pixel, so casting hte Rc.pBits pointer to an unsigned int pointer is basically making it so that it can be used as if it is an array of pixels.
"We should have a great fewer disputes in the world if words were taken for what they are, the signs of our ideas nly, and not for things themselves." - John Locke o
ryt
ryt
it apears theat Rc.pBits is NULL, what should i do?
ryt
ryt
Can somebody give me 100% good code? so i can see whats realy wrong
ryt
ryt
In my version i put D3DPOOL_DEFAULT instead of D3DPOOL_MANAGED. Now it works, but i dont understand it, shouldnt it also work with D3DPOOL_DEFAULT??
Agony
Agony
You'll have to check the documentation for details. Get used to it, because the documentation is a great help for answering many questions more quickly and accurately than the forums often can.

The main idea behind using managed textures and locking is because a managed texture has a local (system memory) copy of the pixels as well as the actual used copy in video memory. So when you lock it, you have access to the system memory copy, and can change it, read from it, etcetera. When you unlock it, the drivers will update the video memory copy when they get a chance. With default pool textures, there isn't any managed local copy, so you have to be careful about specifying usage for the texture, and flags for locking. I use a lot of dynamic usage textures in the default pool, because they are designed for being locked often, so the drivers do things a bit differently, but a normal texture is designed to not be locked and read from or written to regularly, especially not read from. Thus UpdateTexture() and UpdateSurface() are the recommended methods in the documentation. Usually when you do need access to a texture, you only need to write to it, not read from it, since it normally hasn't changed since you last copied it into video memory.
"We should have a great fewer disputes in the world if words were taken for what they are, the signs of our ideas nly, and not for things themselves." - John Locke o
Nik02
Nik02
From SDK:

Quote:
Textures placed in the D3DPOOL_DEFAULT pool cannot be locked unless they are dynamic textures or they are private, four-character code (FOURCC), driver formats. To access unlockable textures, you must use functions such as IDirect3DDevice9::UpdateSurface, IDirect3DDevice9::UpdateTexture, IDirect3DDevice9::GetFrontBufferData, and IDirect3DDevice9::GetRenderTargetData. D3DPOOL_MANAGED is probably a better choice than D3DPOOL_DEFAULT for most applications.
Niko Suni
ryt
ryt
It WORKS :)))))) instead of D3DXCreateTexture() i puted CreateTexture(...,D3DUSAGE_DYNAMIC,...,D3DPOOL_DEFAULT,...) and it works.
ryt
ryt
i wish to control the color by time. Pntr in this case is rapresenting the color and is unsigned int, but my time is float, how can i convert float to unsigned int??
Evil Steve
Evil Steve
That depends on what you want to do. The reason ptr is an unsigned int (32-bit value) is because your pixel data is 32-bit (A8R8G8B8). So, the data at ptr is in the format 0xaarrggbb.
If you want your texture to change from black to red, and your time ranges from 0.0f to 1.0f, then you'd do something like:
float fTime; // your time in the range 0..1Pntr=(unsigned int *)Rc.pBits;// Calculate the colour to useDWORD dwIntensity = ((DWORD)fTime*255.0f);DWORD dwColour = dwIntensity << 16;// Fill the texturefor(int y=0; y<texture_height; ++y){   pRow = Pntr[y*Rc.Pitch]; // Get a pointer to the start of this row of texels   for(int x=0; x<texture_width; ++x)      *pRow++ = dwColour;}


However, if you're doing this every frame, you'd be far better using the texture stages to adjust your triangle colour, since it'll be far more efficient.
ryt
ryt
thx, theats what i meant.

DWORD dwColour = dwIntensity << 16;

what does this mean << 16; ??
Evil Steve
Evil Steve
Quote:
Original post by ryt
thx, theats what i meant.

DWORD dwColour = dwIntensity << 16;

what does this mean << 16; ??

Because the colour is packed as 0xaarrggbb (D3DFMT_A8R8G8B8 means you have the bits in that order, it'll be different for other texture formats), you need to get the dwIntensity value (which is between 0 and 255, which is 0x00 -> 0xff) into the red bits. Because the red bits are 16 bits away from the right, you need to shift left by 16 bits. "<< 16" means "Shift left by 16 bits".
I don't mean to sound patronising, but it's fairly basic C/C++, and you should perhaps consider learning or going back and revising some of the more basic stuff before you move onto DirectX.

Edit: Actually, the D3DCOLOR_ARGB macro would be better to use in this case. Using it, you'd replace the line with:
DWORD dwColour = D3DCOLOR_ARGB(0,dwIntensity,0,0);
Which is much easier to read and understand. Obviously you can put other values (variables or constants) in for alpha, green and blue instead of the zeros.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.