【问题标题】:Managed DirectX: Specifying the Depth (Z-Order) of Sprites containing Texture and Text托管 DirectX:指定包含纹理和文本的 Sprite 的深度(Z 顺序)
【发布时间】:2011-09-12 12:09:45
【问题描述】:

我正在使用托管 DirectX 尝试使用 Sprite 将纹理和一段文本绘制到屏幕上。不幸的是,如果我将文本和纹理放在同一个精灵中,则无论我执行绘制命令的顺序如何,纹理都会覆盖(过度绘制?)文本。

由于我最终想要散布纹理和文本,我如何为这些精灵指定 Z 顺序。每一层都必须在一个单独的精灵中吗?

这是当前代码:

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();

注意:使用 SpriteFlags.SortDepthBackToFront 或 SpriteFlags.SortDepthBackToFront 不会改变行为。

这可能是我的概念上的误解,但如果代码有用,我将不胜感激地接受使用 C++ 或任何语言的非托管 DirectX 中的示例。

提前非常感谢!

【问题讨论】:

  • Draw 方法是否具有采用 layerDepth 参数的重载? XNA 的 SpriteBatch 有,所以我希望托管 DirectX 的精灵也有。
  • 感谢您的评论。 Sprite.Draw 和 Font.DrawText 都没有图层深度参数。 Sprite.Draw 中的第二个 Vector3 确实指定了 3d 位置,但是将 Z 设为负会导致纹理根本不出现,将其设为正不会改变过度绘制行为。

标签: c# directx sprite managed-directx


【解决方案1】:

如果要更改渲染的 Z-Order,则必须在 Draw 命令中设置 Z 值。如果你将 all 设置为 0,你会得到各种奇怪的东西。您更大的问题是 DrawText 不允许您设置 Z-Depth 这是各种垃圾。

因此,您唯一的机会是使用 ID3DXSprite::SetTransform。对于相关的 z 排序位置,您只需要将 Z 坐标向后移动。因此,您可以按如下方式设置转换(假设您使用的是恒等世界矩阵)(C++ 示例)

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 );

然后您继续传递 (0, 0, 0) 的位置进行渲染,文本也将获得正确的 z 排序深度。

希望对您有所帮助。

【讨论】:

  • 谢谢。这足够接近,可以为纹理和文本设置精灵深度。我将很快添加一个提供代码示例的答案。次要点 - 对于变换矩阵,人们想要平移 z-Order 而不是缩放它。我用 Matrix t = Microsoft.DirectX.Matrix.Identity; t.Translate(0, 0, zOrder);
  • @Tom West:对不起,你是完全正确的..那是我的一个愚蠢的错误。我会编辑我的答案:)
【解决方案2】:

这是我(海报)给出的答案:

Goz 提供了解决问题所需的大部分信息。本质上,对于纹理,您可以使用第二个 Verctor3 的第三个参数指定 z 顺序。实验表明 (1) z 顺序从 0.0 到 1.0,其中 0.0 最接近,1.0 最远。超出该范围的任何内容都不会出现。

对于文本,因为没有机会在调用中指定z,所以需要使用Goz建议的变换矩阵。

最后,我使用的代码大致如下。

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();

【讨论】:

    猜你喜欢
    • 2011-06-15
    • 1970-01-01
    • 2013-07-27
    • 1970-01-01
    • 1970-01-01
    • 2014-05-11
    • 2015-02-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多