XNA - 以正确的顺序绘制四边形(和基元)

发布于 2024-09-06 13:56:21 字数 2051 浏览 7 评论 0原文

我对 XNA 中的 3D 内容相当陌生,不幸的是我遇到了一个无法找到解决方案的问题。 (甚至不知道问题是什么)。

简而言之:我在游戏中使用以下方法绘制四边形:

        effect.World = Matrix.Identity *
            Matrix.CreateRotationX(Rotation.X) *
            Matrix.CreateRotationY(Rotation.Y) *
            Matrix.CreateRotationZ(Rotation.Z) *
            Matrix.CreateTranslation(Position);

        // Apply camera-matrixes
        effect.View = viewMatrix;
        effect.Projection = projectionMatrix;

        graphics.VertexDeclaration = vertDec;

        // Begin effect drawing
        effect.Begin();
        foreach (EffectPass pass in
            effect.CurrentTechnique.Passes)
        {
            pass.Begin();
            graphics.DrawUserIndexedPrimitives
                <VertexPositionNormalTexture>(
                PrimitiveType.TriangleList,
                quad.Vertices, 0, 4,
                quad.Indexes, 0, 2);
            pass.End();
        }

        effect.End();

我的效果还具有以下属性:

        this.effect.TextureEnabled = true;
        this.effect.Texture = texture;

并且它有效。我的四边形画得很好,我很高兴。然而有一个小问题。如果一个四边形在另一个四边形或常规模型后面,则确定哪个在顶部绘制的方式是我绘制它们的顺序。

假设我在四边形 B 之前绘制四边形 A,那么 B 将显示为在四边形 A 的顶部,甚至如果 Z 轴小 40 个单位。我必须说,看起来很混乱! ;)

现在我的常规网格体还没有遇到任何这样的问题,当涉及基元时,事情就会变得如此混乱。绘制常规线条也存在同样的问题:

            graphics.DrawUserIndexedPrimitives<VertexPositionColor>(
                PrimitiveType.LineStrip,
                pointList,
                0,  // vertex buffer offset to add to each element of the index buffer
                6,  // number of vertices in pointList
                new short[] { 0, 1 },  // the index buffer
                0,  // first index element to read
                1   // number of primitives to draw

所以我真正要问的是:

A)这是正常的吗?我应该构建一个特殊的引擎来决定何时绘制什么? 我可以通过在正确的时间绘制东西来轻松地在我的项目中解决这个问题,但我可以想象一个我无法想象的游戏。例如,FPS 无法在各处绘制广告牌! ;)

B) 如果这不正常,可能是什么原因以及调试错误的解决方案/好方法是什么。 如果

有任何帮助来解决这个问题,我将不胜感激! :)

I'm fairly new to 3D-stuff in XNA and unfortunately I have encountered a problem I can't find the solution for. (Don't even know what the problem is).

To cut it short: I am drawing quads in my game using:

        effect.World = Matrix.Identity *
            Matrix.CreateRotationX(Rotation.X) *
            Matrix.CreateRotationY(Rotation.Y) *
            Matrix.CreateRotationZ(Rotation.Z) *
            Matrix.CreateTranslation(Position);

        // Apply camera-matrixes
        effect.View = viewMatrix;
        effect.Projection = projectionMatrix;

        graphics.VertexDeclaration = vertDec;

        // Begin effect drawing
        effect.Begin();
        foreach (EffectPass pass in
            effect.CurrentTechnique.Passes)
        {
            pass.Begin();
            graphics.DrawUserIndexedPrimitives
                <VertexPositionNormalTexture>(
                PrimitiveType.TriangleList,
                quad.Vertices, 0, 4,
                quad.Indexes, 0, 2);
            pass.End();
        }

        effect.End();

My effect also has these properties:

        this.effect.TextureEnabled = true;
        this.effect.Texture = texture;

And it works. My quad is drawn nicely and me is happy. However there is one slight problem. If one quad is behind another quad or regular model the way that determines which is drawn on top is the order that I draw them in.

Lets say I draw Quad A before Quad B, then B will be shown as on top of Quad A even if it is 40 units lesser in the Z-axis. Looks very confusing I must say! ;)

Now I haven't had any problem like this with my regular meshes, it is when primitives are involved things get this messy. The very same problem goes for drawing regular lines:

            graphics.DrawUserIndexedPrimitives<VertexPositionColor>(
                PrimitiveType.LineStrip,
                pointList,
                0,  // vertex buffer offset to add to each element of the index buffer
                6,  // number of vertices in pointList
                new short[] { 0, 1 },  // the index buffer
                0,  // first index element to read
                1   // number of primitives to draw

So what I'm asking really is:

A) Is this normal? Should I build a special engine which decides when to draw what? I can easily work around this in my project by drawing stuff at the right time but I can imagine a game where I could not. A fps for example couldn't draw its billboards all over the place! ;)

B) If this is not normal, what could be the cause and what would be a solution/good way to debug the error.

I would appreciate any help to sort this out! :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

筑梦 2024-09-13 13:56:21

听起来你已经关闭了深度缓冲区。也许您事先正在绘制精灵? (使用 SpriteBatch 将更改正常 3D 绘图所需的各种渲染状态。)

尝试在绘制任何 3D 对象之前添加此行代码:

GraphicsDevice.RenderState.DepthBufferEnable = true;

相关链接:

有关深度缓冲区(或“Z 缓冲区”)的说明,您可以可以查看维基百科文章

简要描述深度缓冲区:它基本上是场景的位图图像,存储每个像素“进入”屏幕的距离(深度)。当您去绘制第二个对象时,它将首先计算即将绘制的每个像素的“深度” - 并且在“前面”已经存在对象的区域(具有更接近深度值的像素)深度缓冲区,它将简单地跳过这些像素的绘制。

(您的常规网格体没有问题的原因可能是由于 backface-culling 并且您的网格体没有按从后到前的顺序绘制任何“重叠位”。)

至于调试此类错误的好方法(奇怪的深度缓冲区问题、错误的渲染状态以及大多数其他情况)您的渲染输出不是您所期望的),我强烈建议安装 DirectX SDK学习使用 PIX

It sounds like you've got the depth buffer turned off. Perhaps you are drawing sprites before hand? (Using SpriteBatch will change various render states needed for normal 3D drawing.)

Try adding this line of code before you draw any 3D objects:

GraphicsDevice.RenderState.DepthBufferEnable = true;

Related Links:

For an explaination of the depth buffer (or "Z-buffer"), you could check the wikipedia article.

To describe the depth buffer briefly: It is basically a bitmap image of your scene that stores how far "into" the screen each pixel is (the depth). When you go to draw your second object, it will first calculate the "depth" of each pixel it is about to draw - and in the areas where there is already an object "in front" (pixels with a closer depth value) in the depth buffer, it will simply skip drawing for those pixels.

(The reason you don't have problems with your regular meshes is probably thanks to backface-culling and your meshes not having any "overlapping bits" being drawn in a back-to-front order.)

As for a good way to debug this kind of error (weird depth buffer problems, wrong render states, and most other cases where your rendered output is not what you expect), I strongly recommend installing the DirectX SDK and learning to use PIX.

烦人精 2024-09-13 13:56:21

感谢您回答这个问题!只是对其他想知道这个答案的人的跟进。在xna 4.0中,它发生了一些变化。

某些 3D 图块对象对于其他 3D 对象是透明的。这是由于删除了:

GraphicsDevice.RenderState.DepthBufferEnable = true;

在 XNA 4 中,它被替换为:

DepthStencilState depthBufferState = new DepthStencilState(); 
depthBufferState.DepthBufferEnable = true;
GraphicsDevice.DepthStencilState = depthBufferState;

取自此来源: http://www.hexworld.co.uk/blog/?cat=9

Thanks for answering this question! Just a follow up for anybody else who wants to know about this answer. In xna 4.0, it has changed a little bit.

Some 3D tile objects were transparent to other 3D objects. This was due to the removal of:

GraphicsDevice.RenderState.DepthBufferEnable = true;

In XNA 4 this was replaced by:

DepthStencilState depthBufferState = new DepthStencilState(); 
depthBufferState.DepthBufferEnable = true;
GraphicsDevice.DepthStencilState = depthBufferState;

Taken from this source: http://www.hexworld.co.uk/blog/?cat=9

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文