XNA - Рисование квадов (и примитивов) в правильном порядке - PullRequest
2 голосов
/ 22 июня 2010

Я довольно новичок в 3D-материалах в XNA и, к сожалению, я столкнулся с проблемой, для которой не могу найти решение. (Даже не знаю, в чем проблема).

Короче говоря: я рисую четверки в моей игре, используя:

        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;

И это работает. Мой квадроцикл хорошо нарисован, и я счастлив. Однако есть одна небольшая проблема. Если один четырехугольник находится позади другого четырехугольника или обычной модели, способ, который определяет, что нарисовано сверху, - это порядок, в котором я их рисую.

Допустим, я рисую Quad A перед Quad B, тогда B будет отображаться как сверху Quad A, даже если он на 40 единиц меньше по оси Z. Выглядит очень запутанно, я должен сказать! ;)

Теперь у меня не было таких проблем с моими обычными сетками, это когда примитивы вовлечены, вещи становятся такими грязными. Та же самая проблема касается рисования обычных линий:

            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

Так что я действительно спрашиваю:

А) Это нормально? Должен ли я создать специальный движок, который решает, когда что рисовать? Я могу легко обойти это в своем проекте, рисуя вещи в нужное время, но я могу представить себе игру, в которой я не смог бы. Например, fps не может рисовать свои рекламные щиты повсюду! ;)

B) Если это не нормально, в чем может быть причина, и что может быть решением / хорошим способом устранения ошибки.

Буду признателен за любую помощь, чтобы разобраться с этим! :)

Ответы [ 2 ]

6 голосов
/ 22 июня 2010

Похоже, у вас отключен буфер глубины. Возможно, вы рисуете спрайты перед рукой? (Использование SpriteBatch изменит различные состояния рендеринга, необходимые для нормального трехмерного рисования.)

Попробуйте добавить эту строку кода, прежде чем рисовать какие-либо 3D-объекты:

GraphicsDevice.RenderState.DepthBufferEnable = true;

Ссылки по теме:

Для объяснения буфера глубины (или «Z-буфера»), вы можете проверить статью в википедии .

Чтобы кратко описать буфер глубины: это в основном растровое изображение вашей сцены, которое хранит информацию о том, как далеко "в" экран попадает каждый пиксель (глубина). Когда вы начнете рисовать свой второй объект, он сначала вычислит «глубину» каждого пикселя, который он собирается нарисовать, - и в областях, где уже есть объект «спереди» (пиксели с более близким значением глубины) в буфер глубины, он просто пропустит рисование для этих пикселей.

(Причина, по которой у вас нет проблем с вашими обычными сетками, возможно, вызвана отбраковкой задней поверхности и вашими сетками, не имеющими никаких «перекрывающихся битов», нарисованных в обратном порядке. )

Что касается хорошего способа отладки такого рода ошибок (странные проблемы с буфером глубины, неправильные состояния рендеринга и большинство других случаев, когда результат рендеринга не соответствует вашим ожиданиям), я настоятельно рекомендую установить DirectX SDK и учатся использовать PIX .

4 голосов
/ 15 августа 2012

Спасибо за ответ на этот вопрос!Просто продолжение для любого, кто хочет знать об этом ответе.В xna 4.0 это немного изменилось.

Некоторые трехмерные объекты листов были прозрачными для других трехмерных объектов.Это было связано с удалением:

GraphicsDevice.RenderState.DepthBufferEnable = true;

В XNA 4 это было заменено на:

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

Из этого источника: http://www.hexworld.co.uk/blog/?cat=9

...