如何在DirectX(2D)中使原始图形正确覆盖精灵

3
我在使用Direct3D9渲染精灵和基本图形时遇到了问题。我想要制作一个简单的2D游戏,使用精灵绘制,然而我发现还需要使用基本图形来绘制简单的矩形,线条等等。问题出在重叠上。
如果我只使用Device.DrawUserPrimitives()绘制基本图形,一切都很好,基本图形能够正确地被渲染。如果我只使用Sprite.Draw()绘制精灵,也是可以的。但是当我同时绘制精灵和基本图形时,所有的精灵会自动覆盖基本图形或者使它们变成黑色。
我尝试禁用Z缓冲区,在绘制精灵时禁用写入Z缓冲区等等,但结果都一样。我设法通过更改基本图形的z位置,让基本图形覆盖精灵,但是这样做会使所有的基本图形都变成黑色... :(
请注意,我已经尝试过先绘制基本图形和后绘制精灵,但并没有帮助。
下面是一些绘制精灵和基本图形的代码片段(变量名已更改,以便理解即使您不了解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位置int颜色的结构体,而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. 所有图元都会正确地呈现,直到我绘制精灵为止。但即使我停止绘制精灵,图元仍然保持暗/黑色,直到我重置应用程序为止。
如果您需要我的源代码的其他片段,请在此处编写,并我会更新这个。
3个回答

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

我希望这能帮助到其他遇到这个问题的人。


0

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

在绘制用户基元后,我也会执行device.EndScene()。

希望这能帮到你!


谢谢你的尝试,但Sprite.End()和Device.EndScene()已经在我的源代码中了,否则它就不会工作。 :) 我尝试了很多方法,但仍然不起作用...也许与我的顶点缓冲有关,但我真的不知道。 :( - TomsonTom
哦,我明白了。我使用ILSpy查找Sprite的实际代码,并看到它所做的所有事情就是调用来自未托管的ID3DXSprite的方法。也许这个ID3DXSprite设置的状态列表会有帮助?链接 - Ani
我发现如果不使用DoNotModifyRenderState标志,基元会被正确渲染。但是精灵却没有被正确渲染。因此设备渲染状态可能存在问题。有什么想法吗? - TomsonTom

0

没有看到你完整的代码,很难找到错误。我会检查精灵和基元的z缓冲区值。如果这部分正确,那么你的基元就没有理由不覆盖后备缓冲区。 你每个渲染周期都设置了基元所需的渲染状态吗?d3dx精灵默认设置自己的渲染状态,也许这会搞乱你的基元。 此外,在绘制精灵时有一个D3DXSPRITE_DONOTMODIFY_RENDERSTATE标志。

->当你改变z值时,基元变暗,我认为这是由于你的光源(范围?)引起的。


抱歉,我无法验证您对我三年前问题的回答。 :) 无论如何,谢谢。 - TomsonTom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接