0

I am using managed DirectX to try and draw a texture and a piece of text to the screen using a Sprite. Unfortunately, if I place the text and the texture in the same sprite, the texture overwrites (overdraws?) the text regardless of the order I do the draw commands.

Since I will eventually want to intersperse textures and text, how do I specify a Z-order for these sprites. Does each layer have to be in a separate sprite?

Here is the current code:

m_device.BeginScene();
m_device.Clear(ClearFlags.Target, Color.Black, 1.0f, 0);
m_sprite.Begin(SpriteFlags.SortTexture | SpriteFlags.AlphaBlend);

// Switching the order of following two statements doesn't change the Z-Order!
m_sprite.Draw(m_texture, Vector3.Empty, new Vector3(0, 0, 0), 
              Color.White.ToArgb());
m_d3dFont.DrawText(m_sprite, m_text, x, y, color);

m_sprite.End();
m_device.EndScene();
m_device.Present();

Note: Using the SpriteFlags.SortDepthBackToFront or SpriteFlags.SortDepthBackToFront does not change the behaviour.

This is probably a conceptual misunderstanding on my part, but if code is useful, I'll gratefully accept samples in unmanaged DirectX using C++ or whatever language.

Many thanks in advance!

Tom West
  • 1,759
  • 2
  • 13
  • 20
  • Does the Draw method have an overload that takes a layerDepth argument? XNA's SpriteBatch does, so I expect managed DirectX's sprite would have either. – tafa Sep 12 '11 at 13:03
  • Thanks for the comment. Neither Sprite.Draw nor Font.DrawText have a layer depth argument. The second Vector3 in the Sprite.Draw does specify a 3d position, but making the Z negative causes the texture not to appear at all, and making it positive doesn't change the overdraw behaviour. – Tom West Sep 12 '11 at 15:56

2 Answers2

2

If you want to change the Z-Order of rendering then you have to set the Z value in the Draw command. If you set the all to 0 you will get all sorts of weirdness. Your bigger issue is that DrawText doesn't allow you to set a Z-Depth which is all kinds of rubbish.

Thus your only chance is to use ID3DXSprite::SetTransform. You need to shift only the Z-Coordinate back with it for the relevant z ordering position. So you can set your transforms (assuming you are using identity world matrices) as follows (C++ example)

D3DXMATRIX mat( 1.0f, 0.0f, 0.0f, 0.0f,
                0.0f, 1.0f, 0.0f, 0.0f,
                0.0f, 0.0f, 1.0f, 0.0f,
                0.0f, 0.0f, zOrder, 1.0f );
m_Sprite->SetTransform( &mat );

You then carry on passing a position of (0, 0, 0) for rendering and text will also gain the correct depth for z-ordering.

Hope that helps.

Goz
  • 61,365
  • 24
  • 124
  • 204
  • Thank you. That was close enough to enable to set sprite depth for both textures and text . I will shortly add an answer that provides a code example. Minor point - for the transformation matrix, one wants to translate the z-Order rather than scale it. I did this with Matrix t = Microsoft.DirectX.Matrix.Identity; t.Translate(0, 0, zOrder); – Tom West Sep 12 '11 at 20:17
  • @Tom West: Sorry you are completely right .. that was a stupid mistake of me. I'll edit my answer :) – Goz Sep 12 '11 at 20:28
0

Here is the answer I (the poster) went with:

Goz provided most of the information needed to solve the problem. Essentially, for textures, you can specify the z-order using the third parameter of the second Verctor3. Experimentation has made it clear that (1) z order goes from 0.0 to 1.0, with 0.0 being closest and 1.0 being the the furthest away. Anything out of that range doesn't appear at all.

For text, because there's no opportunity to specify the z in the call, you need to use Goz's suggestion of a transform matrix.

In the end, here's roughly the code I used.

m_device.BeginScene();
m_device.Clear(ClearFlags.Target, Color.Black, 1.0f, 0);
m_sprite.Begin(SpriteFlags.SortDepthFrontToBack | SpriteFlags.SortTexture | SpriteFlags.AlphaBlend);

// The "1.0f" is the z-order of texture1.  This places it at the very back.
m_sprite.Draw(m_texture1, Vector3.Empty, new Vector3(0, 0, 1.0f), 
             Color.White.ToArgb());

// The text1 is placed at z-order 0.8f, in order to place it in front of texture1
Microsoft.DirectX.Matrix t = Microsoft.DirectX.Matrix.Identity;
t.Translate(new Vector3(0, 0, 0.8f));
m_sprite.Transform = t;
m_d3dFont.DrawText(m_sprite, m_text1, 200, 200, color1);
m_sprite.Transform = Microsoft.DirectX.Matrix.Identity;


// The "0.6f" is the z-order of texture2.  This places it at the very back.
m_sprite.Draw(m_texture2, Vector3.Empty, new Vector3(220, 220, 0.6f), 
              Color.White.ToArgb());

// The text2 is placed at z-order 0.4f, in order to place it in front of texture2
t = Microsoft.DirectX.Matrix.Identity;
t.Translate(new Vector3(0, 0, 0.4f));
m_sprite.Transform = t;
m_d3dFont.DrawText(m_sprite, m_text2, 240, 240, color2);
m_sprite.Transform = Microsoft.DirectX.Matrix.Identity;

m_sprite.End();
m_device.EndScene();
m_device.Present();
Tom West
  • 1,759
  • 2
  • 13
  • 20