问题
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!
回答1:
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.
回答2:
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();
来源:https://stackoverflow.com/questions/7387598/managed-directx-specifying-the-depth-z-order-of-sprites-containing-texture-an