XNA Vertex Buffer рисует очень неправильно - PullRequest
1 голос
/ 21 сентября 2011

Я новичок в использовании буфера вершин в XNA.В моем проекте я создаю один, используя очень большое количество вершин.Раньше я рисовал примитивы с DrawUserIndexedPrimitives (), но я вырос из этого и нуждаюсь в большей эффективности, поэтому я пытаюсь выяснить основы буферов.

Я думаю, что я успешно реализовалбуфер (и были очень довольны улучшением производительности), за исключением того, что все лица выглядят неправильно.Вот как примитивы выглядели без буфера: http://i.imgur.com/ygsnB.jpg (предполагаемый вид), а вот как они выглядят без: http://i.imgur.com/rQN1p.jpg

Вот мой код для загрузки буфера вершин и индекса буфера:

private void RefreshVertexBuffer()
    {
        List<VertexPositionNormalTexture> vertices = new List<VertexPositionNormalTexture>();
        List<int> indices = new List<int>();
        //rebuild the vertex list and index list
        foreach(var entry in blocks)
        {
            Block block = entry.Value;
            for (int q = 0; q < block.Quads.Count; q++)
            {
                vertices.AddRange(block.Quads[q].Corners);
                int offset = vertices.Count;
                foreach (Triangle tri in block.Quads[q].Triangles)
                {
                    indices.Add(tri.Indices[0] + offset);
                    indices.Add(tri.Indices[1] + offset);
                    indices.Add(tri.Indices[2] + offset);
                }
            }
        }

        vertexBuffer = new DynamicVertexBuffer(graphics, typeof(VertexPositionNormalTexture), vertices.Count, BufferUsage.None);
        indexBuffer = new DynamicIndexBuffer(graphics, IndexElementSize.ThirtyTwoBits, indices.Count, BufferUsage.None);
        vertexBuffer.SetData<VertexPositionNormalTexture>(vertices.ToArray(), 0, vertices.Count);
        indexBuffer.SetData<int>(indices.ToArray(), 0, indices.Count);

    }

и вот вызов отрисовки для простого рендеринга:

public void Render(Planet planet, Camera camera)
    {
        effect.View = camera.View;
        effect.Projection = camera.Projection;

        effect.World = planet.World;

        foreach (KeyValuePair<Vector3, Block> entry in planet.Geometry.Blocks)
        {
            int blockID = planet.BlockMap.Blocks[entry.Value.U][entry.Value.V][entry.Value.W];
            if (blockID == 1)
                effect.Texture = dirt;
            else if (blockID == 2)
                effect.Texture = rock;
            effect.CurrentTechnique.Passes[0].Apply();
            foreach (Quad quad in entry.Value.Quads)
            {
                foreach (Triangle tri in quad.Triangles)
                {
                    graphics.DrawUserIndexedPrimitives<VertexPositionNormalTexture>(PrimitiveType.TriangleList,
                        quad.Corners, 0, quad.Corners.Length, tri.Indices, 0, 1);
                }
            }
        }
    }

... и для рендеринга буфера вершин:

public void RenderFromBuffer(Planet planet, Camera camera)
    {
        effect.View = camera.View;
        effect.Projection = camera.Projection;
        effect.World = planet.World;

        graphics.SetVertexBuffer(planet.Geometry.VertexBuffer);
        graphics.Indices = planet.Geometry.IndexBuffer;

        effect.CurrentTechnique.Passes[0].Apply();
        graphics.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, planet.Geometry.VertexBuffer.VertexCount, 0, planet.Geometry.IndexBuffer.IndexCount / 6);
    }

Мои индексы могут бытьвыкл?Или это связано с некоторыми странностями, связанными с тем, как графическое устройство работает с индексированным буфером и пользователем?

Редактировать: Это также может быть связано с тем, как я сшиваю индексы треугольника.Когда я строил этот проект с DrawUserIndexedPrimitives, я столкнулся с некоторыми проблемами, похожими на эту, когда треугольники, обращенные к определенному направлению, рисовали бы на неправильной «стороне» (или, если выбрано неправильное лицо).Итак, я придумал это решение:

Triangle[] tris;
        if (faceDirection == ADJACENT_FACE_NAMES.BOTTOM | faceDirection == ADJACENT_FACE_NAMES.OUTER | faceDirection == ADJACENT_FACE_NAMES.LEFT)
        {
            //create the triangles for the quad
            tris = new Triangle[2]{
                new Triangle( //the bottom triangle
                    new int[3] {
                        0, //the bottom left corner
                        1, //the bottom right corner
                        2 //the top left corner
                    }),
                new Triangle( //the top triangle
                    new int[3] {
                        1, //the bottom right corner
                        3, //the top right corner
                        2 //the top left corner
                    })};
        }
        else
        {
            tris = new Triangle[2]{
                            new Triangle(
                                new int[3] {
                                    2, //the top left corner
                                    1, 
                                    0
                                }),
                                new Triangle(
                                    new int[3] {
                                        2,
                                        3,
                                        1
                                    })
                        };
        }

1 Ответ

1 голос
/ 21 сентября 2011

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

  1. Вы можете изменить порядок индексов треугольника.

            foreach (Triangle tri in block.Quads[q].Triangles)
            {
                indices.Add(tri.Indices[1] + offset);
                indices.Add(tri.Indices[0] + offset);
                indices.Add(tri.Indices[2] + offset);
            }
    
  2. Вы можете изменить свойRasterizerState ...

    Состояние растеризатора по умолчанию - RasterizerState.CullClockwise ...

    Вы можете изменить его на RasterizerState.CullCounterClockwise

РЕДАКТИРОВАТЬ:

в этой строке есть ошибка:

 graphics.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, planet.Geometry.VertexBuffer.VertexCount, 0, planet.Geometry.IndexBuffer.IndexCount / 6)

должно быть:

 graphics.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, planet.Geometry.VertexBuffer.VertexCount, 0, planet.Geometry.IndexBuffer.IndexCount / 3)
...