【问题标题】:How to make primitives correctly overlay sprites in DirectX (2D)如何使图元在 DirectX (2D) 中正确覆盖精灵
【发布时间】:2011-07-01 16:43:22
【问题描述】:

我在 Direct3D9 中渲染精灵和图元时遇到了问题。我正在尝试使用精灵制作一个简单的 2D 游戏,但是我发现我还需要原语来绘制简单的正方形、线条等。问题在于叠加。

如果我只使用Device.DrawUserPrimitives() 绘制图元,一切都很好,图元被正确渲染。如果我只使用Sprite.Draw() 绘制精灵,也可以。但是,如果我想同时绘制精灵和图元,所有精灵都会自动覆盖图元或使其变黑。

我尝试过禁用 Z 缓冲区,在渲染精灵时禁用 Z 缓冲区中的写入,等等,但它总是一样的。我设法通过改变它们的 z 位置使图元覆盖精灵,但是所有图元都是黑色的...... :(

请注意,我在绘制精灵之前和之后都尝试过渲染图元。它没有帮助。

我将在此处发布一些绘图精灵和图元的 sn-ps(变量名称已更改,因此即使您对 C# 和 SlimDX 一无所知,您也可以理解我在绘制什么):

mSprite.Begin(SpriteFlags.ObjectSpace | SpriteFlags.DoNotModifyRenderState);
mSprite.Draw(texture, centerVector, positionVector, color); // positionVector = Vector3.Zero in my example
mSprite.Flush();

(...)

device.VertexDeclaration = vertexDecl;
device.DrawUserPrimitives(PrimitiveType.TriangleFan, m_fan1.Length - 2, m_fan1);

...其中 m_fan1 是一个包含 Vector4 positionint color 的结构,vertexDecl 声明了这些顶点元素。

m_fan1[0] = new TransformedColored(new Vector4(100.0f, 100.0f, 1.0f, 1.0f), Color.Green);
m_fan1[1] = new TransformedColored(new Vector4(0.0f, 0.0f, 1.0f, 1.0f), Color.Green);
m_fan1[2] = new TransformedColored(new Vector4(200.0f, 0.0f, 1.0f, 1.0f), Color.Green);
m_fan1[3] = new TransformedColored(new Vector4(200.0f, 200.0f, 1.0f, 1.0f), Color.Green);
m_fan1[4] = new TransformedColored(new Vector4(0.0f, 200.0f, 1.0f, 1.0f), Color.Yellow);
m_fan1[5] = new TransformedColored(new Vector4(0.0f, 0.0f, 1.0f, 1.0f), Color.Green);

顺便说一句:

  1. 如果我将填充模式更改为线框,则可以正确绘制图元的线框。
  2. 如果图元覆盖精灵,图元几乎是黑色的,我绘制的精灵越多,图元越暗。也许它与 alpha 有关?
  3. 所有图元都正确渲染直到我绘制一个精灵。但即使我停止绘制精灵,在我重置应用程序之前,图元也会保持暗/黑色。

如果你需要我源代码的其他sn-ps,请写在这里,我会更新这个。

【问题讨论】:

    标签: c# graphics directx slimdx


    【解决方案1】:

    我使用sprite.Transform();解决了这个问题

    sprite.Transform = Matrix.Scaling(1, 1, 1) * Matrix.Translation(x,y, 0); // works
    

    相比

    sprite.Transform = Matrix.Scaling(1, 1, 1) * Matrix.Translation(x,y, 1); // doesn't work
    

    我希望这对遇到此问题的其他人有所帮助。

    【讨论】:

      【解决方案2】:

      我没有看到 sprite.End() 被调用。从这里的文档 (http://msdn.microsoft.com/en-us/library/ms881042.aspx),Sprite.End()“将设备恢复到调用 Sprite.Begin 之前的状态。”

      我还会在绘制用户图元后执行 device.EndScene()。

      希望有帮助!

      【讨论】:

      • 感谢您的尝试,但是Sprite.End() 和Device.EndScene() 已经在我的源代码中,否则将无法正常工作。 :) 我尝试了很多东西,但它仍然不起作用......也许它与我的顶点缓冲区有关,但我真的不知道。 :(
      • 哦,我明白了。我使用 ILSpy 查找 Sprite 的实际代码,发现它所做的只是调用非托管 ID3DXSprite 的方法。也许这个 ID3DXSprite 设置的状态列表会有所帮助? link
      • 我发现如果我不使用标志 DoNotModifyRenderState,原语会正确呈现。然而,精灵不是。所以设备渲染状态可能存在一些问题。有什么想法吗?
      【解决方案3】:

      如果没有看到完整的代码,就不可能真正找到错误。我会检查精灵和我们的图元的 z 缓冲区值。如果那部分是正确的,那么您的原语就没有理由不应该过度绘制后缓冲区。 您是否设置了每个渲染周期的图元所需的渲染状态?默认情况下,d3dx sprite 会设置自己的渲染状态,这可能会弄乱您的图元。 并且,在绘制精灵时有一个标志 D3DXSPRITE_DONOTMODIFY_RENDERSTATE。

      ->当您更改 z 值时图元变暗时,我认为这是由您的光源(范围?)引起的

      【讨论】:

      • 抱歉,我无法验证您对我 3 岁问题的回答。 :) 还是谢谢你。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-02
      • 2012-12-06
      • 1970-01-01
      • 1970-01-01
      • 2019-06-21
      相关资源
      最近更新 更多