Not logged in, Join Here! or Log In Below:  
News Articles Search    

 Home / 3D Theory & Graphics / 2D in D3D, a bit of help needed Account Manager
Archive Notice: This thread is old and no longer active. It is here for reference purposes. This thread was created on an older version of the flipcode forums, before the site closed in 2005. Please keep that in mind as you view this thread, as many of the topics and opinions may be outdated.

March 30, 2005, 09:02 AM

I'm new to DirectX 9 (and this forum) and I've been learning with the help of a few tutorials. I'm a retro programmer so my main focus is making 2D graphics. I'm learning DX so I can access cool stuff like alpha, scaling, etc.

So far I can initialise DirectX and draw sprites (ID3DXSprite) easily. I'm looking for a bit more control, though.
I'm looking for a way to be able to:

- Draw an image 'into' any other image (eg, draw onto their buffer)
- Treat the backbuffer as an image, to keep it consistent (so I can use the same blitting functions)
- Get access to an image's pixels directly
- Store an image in either video or system memory

I found out (by accident) about DirectX's IDirect3DSurface9 interface, which at first sounded like it was exactly what I wanted. As far as I can tell, though, it's actually a part of DirectDraw, so hardware acceleration (alpha/scale/storing in v-ram) isn't possible (unless I'm mistaken?).

So my question is, could anyone nudge me in the right direction of a way to achieve this? I don't mind how complicated it is as long as I can find a decent tutorial or reference.

Thanks a bunch,

PS: I've had a look around on Google, and these forums, but they don't really give me the sort of answer I'm looking for.


March 30, 2005, 09:11 AM

> Draw an image 'into' any other image (eg, draw onto their buffer)
> Treat the backbuffer as an image, to keep it consistent (so I can use the same
> blitting functions)

Look for "render to texture".

The backbuffer actually is what is called a "surface" in Direct3D. The render to texture technique selects another surface as render target. There are limitations, however.

> Get access to an image's pixels directly

Bad idea. Most data is stored in video ram, and access to it (especially read access) is terribly slow. What you need to do it is the Lock() and UnLock() methods of an IDirect3DSurface9.

IDirect3DSurface9 isn't a part of DirectDraw. In fact DirectDraw doesn't exist any longer since version 8.
Textures, Backbuffer, Depth buffer, etc. are all IDirect3DSurfaces behind the curtains. Availability of acceleration may depend on the pixel format and storage location of the surface.

> Store an image in either video or system memory

When creating a surface or texture (textures are surfaces, too) there are a load of parameters that control the memory management.

You currently seem to use the D3DX framework around D3D, not plain D3D. Maybe you want to look into vertex buffers (IDirect3DVertexBuffer) for rendering instead of ID3DXSprite.


March 30, 2005, 09:37 AM

Hiya Chris, thanks for the reply. I'll have a look into rendering to a texture. The direct pixel access is mainly for system memory textures, so I don't think speed will be that much of a problem.

Not long before I came here I botched up this bit of code:

  2. IDirect3DSurface9 * backbuffer = 0;
  3. IDirect3DSurface9 * image;
  5. dxw.d3d_device->GetRenderTarget(0,&backbuffer);
  7. result = dxw.d3d_device->CreateOffscreenPlainSurface(128,128,
  8.                                                         dxw.GetDepthFormat(32),
  9.                                                         D3DPOOL_DEFAULT,
  10.                                                         ℑ,
  11.                                                         0);
  13. result = D3DXLoadSurfaceFromFile(image,
  14.                                         0, // palette
  15.                                         0, // dest rect
  16.                                         "image.bmp",
  17.                                         0, // source rect,
  18.                                         D3DX_FILTER_NONE,
  19.                                         0xFFFF00FF, // colour key
  20.                                         0);
  22. // inside main loop:
  24. POINT drawat;
  25. drawat.x = mouse_x;
  26. drawat.y = mouse_y;
  27. dxw.d3d_device->UpdateSurface(image,0,backbuffer,&drawat);

This draws fine if the surface is stored in D3DPOOL_SYSTEMMEM, but does nothing if I use D3DPOOL_DEFAULT. That's what lead me to believe that it uses DirectDraw rather than D3D. Any idea why that's happening? (the first 2 functions succeed both ways, but UpdateSurface fails if I use D3DPOOL_DEFAULT)

Thanks again,


March 30, 2005, 10:21 AM

That's an easy one. You have the documentation of the DirectX 9 SDK ?
Looking into UpdateSurface there yields, amongst others, these restrictions:

  2. Remarks
  4. This method is similar to CopyRects in Microsoft® DirectX® 8.0.
  6. This function has the following restrictions.
  8. The source surface must have been created with D3DPOOL_SYSTEMMEM.
  9. The destination surface must have been created with D3DPOOL_DEFAULT.

If you don't have this doc, it's available as Word DOC and as CHM help file and contained in the DirectX 9 SDK downloads. You can learn loads and loads by browsing through the documentation of the functions in question. It's really written in a very clear and precise way, and can save you from buying the one or other book.


March 30, 2005, 10:44 AM

Whoops. Should've read the whole thing first. Ok, I'll have a look through the documentation. I'm still not really sure what I need to be doing though! (Having a reference is great... if you know what functions you need to actually call). I've tried looking at render targets and they seem to just do nothing at all:

  2.         dxw.d3d_device->GetRenderTarget(0,&backbuffer);
  3.         texture1->GetSurfaceLevel(0,&t1surface);
  5.         dxw.d3d_device->SetRenderTarget(0,t1surface);
  6.         dxw.d3d_device->BeginScene();
  8.         RECT srcrect;
  9.         srcrect.left = 0;
  10. = 0;
  11.         srcrect.bottom = 32;
  12.         srcrect.right = 32;
  14.         dxw.sprite->Draw(texture2,      // texture
  15.                                         &srcrect,       // source rect
  16.                                         0,              // handle point (top left)
  17.                                         &D3DXVECTOR3(0,0,0) ,// dest rect
  18.                                         0xFFFFFFFF); // colour
  20.         dxw.d3d_device->EndScene();
  22.         dxw.d3d_device->SetRenderTarget(0,backbuffer); 


March 30, 2005, 11:44 AM

Damn, sorry! Forgot the Sprite->Begin(0) and Sprite->End(). Works fine now. thanks for the help!

This thread contains 6 messages.
Hosting by Solid Eight Studios, maker of PhotoTangler Collage Maker.