IDirect3DTexture9 and manipulation of single pixels

Started by
3 comments, last by Metzler 20 years, 8 months ago
Hi, I am trying to get direct access to the bitmap-data of the IDirect3DTexture9 data structure, because i want to manipulate (that is paint) single pixels on that bitmap. Actually i havent found any kind of tutorial or documentation for this (google, gamedev or directx sdk). So i would be pleased, if anybody could help me by giving me some advices how to do it or where to search for. Thanks in advance
Advertisement
IDirect3DTexture9::LockRect()

This asks the graphics driver for a pointer to your texture's pixel data.

Please search info on "texture locking", this is frequent question.

[edited by - Nik02 on August 31, 2003 7:13:34 AM]

Niko Suni

It is quite simple!
Although there are a couple niggles.
Just as a note, i''ve done this in dx8.1, but all the interfaces
and functions are the same afaik. (and even if not they''ll tell you where to look).

Basically it goes like this.

Prep work:
You need to make sure that a copy of the texture resides in system memory. D3D won''t let you access texture data on the video card (D3DPOOL_DEFAULT) so what you have to do is modify the texture in system memory and then re-upload the texture to video memory.

Getting the data:
Decide which level you want to modify, this will usually be level 0 (the top image on the mip chain, or the only image if there are no mip-maps).
Frist call IDirect3DTexture::GetLevelDesc() This gives you information about the image, including the texture format, size in bytes, width, and height.
Now we can do one of two things. We can access this texture data directly, or we can access it as an IDirect3DSurface. If you access it directly you use the D3DLEVEL_DESC info to decide how to manipulate the bits, if you access it as a Surface, you can use D3DX functions to convert it to an easy to manipulate surface such as A8R8G8B8 (this is especially useful when dealing with compressed formats).
To access the data directly, use IDirect3DTexture::LockRect().
To access it via a surface call IDirect3DTexture::GetSurfaceLevel(). You can then call LockRect() on the Surface and the process for locking texture or surface is the same. However if you get the surface you can also use the nifty D3DXLoadSurfaceFromSurface() function to convert the surface to (eg.) A8R8G8B8. This function is fairly simple, you just create an IDirect3DSurface with IDirect3DDevice::CreateImageSurface() with the Format you want to convert to, then pass it as the destination to the D3DXLoadSurfaceFromSurface().

Now, where were we...up to LockRect(). You pass in a D3DLOCKED_RECT structure to this function, and when it returns it will contain two useful bits of data. The image pitch, and also a pointer to the actual texture data!!
When manipulating this data you must pay close attention to the pitch. For RGB formats (that is pretty much anything that isn''t a DXT compressed format) the Pitch represents the number of bytes that are used by a single row of image data. This can be a larger number than width*(bytes per pixel), so you must be careful when accessing the image data. For example, when you get to the end of a row, you need to jump (Pitch - width*(bytes per pixel)) bytes to get to the start of the next row of image data!

Now you have manipulated your image data you can UnlockRect() the data. Now you have to re-upload the changed image data to the graphics card.
First though, if you are using mip-maps you may want to use D3DXFilterTexture to regenerate the mipmaps with the modified image data.

Finally, to re-upload the image data is quite simple. A call to IDirect3DDevice::UpdateTexture() specifying your system-memory copy of the texture and video memory copy of the texture will do the trick!

As a final note, if you are planning on changing a texture every frame (or at least very often) you may wish to consider using Dynamic Textures. The main cosmetic difference between normal (static) and Dynamic textures is that you can lock them in video memory, and don''t have to keep a seperate system memory copy of the texture. They also allow special operations when locking similar to dynamic vertex/index buffers. I haven''t used them myself though so i''ll leave my discussion of the topic end now
Hope you find that useful!
CYer, Blitz

PS. Just thought i''d list all the seperate functions seperately so you don''t have to look through all my words
IDirect3DTexture::GetLevelDesc()
IDirect3DTexture::GetSurfaceLevel()
IDirect3DTexture or IDirect3DSurface::LockRect() (and UnlockRect())
IDirect3DDevice::CreateImageSurface()
D3DXLoadSurfaceFromSurface()
D3DXFilterTexture()
IDirect3DDevice::UpdateTexture()
Ok, THX. I was searching for the wrong topic... :-/
Huge THX @ Blitz_Krieg ! This is more than i imagined to !

This topic is closed to new replies.

Advertisement