我是新手在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
})
};
}
答案 0 :(得分: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);
}
您可以更改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)