Sign in to follow this  

IDirect3DTexture9

This topic is 4505 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

for textures i use IDirect3DTexture9. How can i lock the texture and then update its pixels?

Share this post


Link to post
Share on other sites
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 drawing
Txr->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.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Pntr=(unsigned int *)Rc.pBits; Why (unsigned int *)??
I compile succesfully, bu i get break here: Pntr[(10*256)+80]=0xFF00FF00; Whats wrong??

ryt

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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??

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
It WORKS :)))))) instead of D3DXCreateTexture() i puted CreateTexture(...,D3DUSAGE_DYNAMIC,...,D3DPOOL_DEFAULT,...) and it works.

Share this post


Link to post
Share on other sites
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??

Share this post


Link to post
Share on other sites
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..1
Pntr=(unsigned int *)Rc.pBits;

// Calculate the colour to use
DWORD dwIntensity = ((DWORD)fTime*255.0f);
DWORD dwColour = dwIntensity << 16;

// Fill the texture
for(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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Sign in to follow this