我在 XNA 中有一个体素(我的世界风格)引擎,世界被分成块,当一个立方体被修改时,我通过扫描所有立方体并检查面是否可见来重新创建顶点缓冲区。这通常以很好的速度工作,但是当立方体以某种方式排列时(这样顶点缓冲区会大得多),它可以接管一个帧来生成新的块。在最糟糕的配置中(显示最多可能的顶点),它可能需要长达 100 毫秒。以下部分代码代表 100 次中的大约 80-90 毫秒,当块更新时它运行了 131,072 次,在最坏的可能配置下它创建了 32,768 个立方体,而在所有其他运行中它创建了 0 个顶点。
我也在使用 i5 2500k,所以这在旧系统上可能真的很糟糕。
无论如何我都想不出提高速度,而且我对编程很陌生,所以我想我会在这里发布一些建议?谢谢。
public void GenerateCubeGeometryAtPosition(int x, int y, int z, byte id)
{
//We check if there's a cube in the six directions around the cube
//if there's no cube ot the cube is transparent we add the vertices to the vertex list
//if the cube is on the outside of the chunk we check the cube in the chunk next to it assuming it's loaded
//if we have to build part of the cube we make a new vertex
//first 3 bytes in the vertex are the position relative to the chunk
//4th byte is for normals, we check it in the shader to figure out the normal
//the next 2 bytes in the properties are for the texture positons on the texture atlas
//last 2 bytes are for other properties of the vertex like light/shade etc
//Check up and down
if (y > YSize - 2)
{
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(x, y + 1, z, 0f), GlobalWorld.Blocks[id].VertexPropertiesTop[0]));
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(1 + x, y + 1, z, 0f), GlobalWorld.Blocks[id].VertexPropertiesTop[1]));
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(x, y + 1, 1 + z, 0f), GlobalWorld.Blocks[id].VertexPropertiesTop[2]));
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(1 + x, y + 1, 1 + z, 0f), GlobalWorld.Blocks[id].VertexPropertiesTop[3]));
}
else if (Blocks[x, y + 1, z] == 0 || GlobalWorld.Blocks[Blocks[x, y + 1, z]].Transparent)
{
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(x, y + 1, z, 0f), GlobalWorld.Blocks[id].VertexPropertiesTop[0]));
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(1 + x, y + 1, z, 0f), GlobalWorld.Blocks[id].VertexPropertiesTop[1]));
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(x, y + 1, 1 + z, 0f), GlobalWorld.Blocks[id].VertexPropertiesTop[2]));
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(1 + x, y + 1, 1 + z, 0f), GlobalWorld.Blocks[id].VertexPropertiesTop[3]));
}
if (y != 0 && (Blocks[x, y - 1, z] == 0 || GlobalWorld.Blocks[Blocks[x, y - 1, z]].Transparent))
{
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(x, y, z, 1f), GlobalWorld.Blocks[id].VertexPropertiesBottom[0]));
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(x, y, 1 + z, 1f), GlobalWorld.Blocks[id].VertexPropertiesBottom[1]));
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(1 + x, y, z, 1f), GlobalWorld.Blocks[id].VertexPropertiesBottom[2]));
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(1 + x, y, 1 + z, 1f), GlobalWorld.Blocks[id].VertexPropertiesBottom[3]));
}
//check Right and Left of the cube and the adjacent chunk at the edges
if (x == 0)
{
if (this.RightChunk != -1 && (GlobalWorld.LoadedChunks[this.RightChunk].Blocks[XSize - 1, y, z] == 0 || GlobalWorld.Blocks[GlobalWorld.LoadedChunks[this.RightChunk].Blocks[XSize - 1, y, z]].Transparent))
{
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(x, y, z, 3f), GlobalWorld.Blocks[id].VertexPropertiesRight[0]));
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(x, y + 1, z, 3f), GlobalWorld.Blocks[id].VertexPropertiesRight[1]));
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(x, y, 1 + z, 3f), GlobalWorld.Blocks[id].VertexPropertiesRight[2]));
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(x, y + 1, 1 + z, 3f), GlobalWorld.Blocks[id].VertexPropertiesRight[3]));
}
}
else if (Blocks[x - 1, y, z] == 0 || GlobalWorld.Blocks[Blocks[x - 1, y, z]].Transparent)
{
//right
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(x, y, z, 3f), GlobalWorld.Blocks[id].VertexPropertiesRight[0]));
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(x, y + 1, z, 3f), GlobalWorld.Blocks[id].VertexPropertiesRight[1]));
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(x, y, 1 + z, 3f), GlobalWorld.Blocks[id].VertexPropertiesRight[2]));
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(x, y + 1, 1 + z, 3f), GlobalWorld.Blocks[id].VertexPropertiesRight[3]));
}
if (x > XSize - 2)
{
if (this.LeftChunk != -1 && (GlobalWorld.LoadedChunks[this.LeftChunk].Blocks[0, y, z] == 0 || GlobalWorld.Blocks[GlobalWorld.LoadedChunks[this.LeftChunk].Blocks[0, y, z]].Transparent))
{
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(1 + x, y, z, 2f), GlobalWorld.Blocks[id].VertexPropertiesLeft[0]));
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(1 + x, y, 1 + z, 2f), GlobalWorld.Blocks[id].VertexPropertiesLeft[1]));
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(1 + x, 1 + y, z, 2f), GlobalWorld.Blocks[id].VertexPropertiesLeft[2]));
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(1 + x, 1 + y, 1 + z, 2f), GlobalWorld.Blocks[id].VertexPropertiesLeft[3]));
}
}
else if (Blocks[x + 1, y, z] == 0 || GlobalWorld.Blocks[Blocks[x + 1, y, z]].Transparent)
{
//left
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(1 + x, y, z, 2f), GlobalWorld.Blocks[id].VertexPropertiesLeft[0]));
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(1 + x, y, 1 + z, 2f), GlobalWorld.Blocks[id].VertexPropertiesLeft[1]));
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(1 + x, 1 + y, z, 2f), GlobalWorld.Blocks[id].VertexPropertiesLeft[2]));
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(1 + x, 1 + y, 1 + z, 2f), GlobalWorld.Blocks[id].VertexPropertiesLeft[3]));
}
//check Back and Front of the cube and the adjacent chunk at the edges
if (z == 0)
{
if (this.BackChunk != -1 && (GlobalWorld.LoadedChunks[this.BackChunk].Blocks[x, y, ZSize - 1] == 0 || GlobalWorld.Blocks[GlobalWorld.LoadedChunks[this.BackChunk].Blocks[x, y, ZSize - 1]].Transparent))
{
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(x, y, z, 5f), GlobalWorld.Blocks[id].VertexPropertiesBack[0]));
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(1 + x, y, z, 5f), GlobalWorld.Blocks[id].VertexPropertiesBack[1]));
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(x, y + 1, z, 5f), GlobalWorld.Blocks[id].VertexPropertiesBack[2]));
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(1 + x, y + 1, z, 5f), GlobalWorld.Blocks[id].VertexPropertiesBack[3]));
}
}
else if (Blocks[x, y, z - 1] == 0 || GlobalWorld.Blocks[Blocks[x, y, z - 1]].Transparent)
{
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(x, y, z, 5f), GlobalWorld.Blocks[id].VertexPropertiesBack[0]));
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(1 + x, y, z, 5f), GlobalWorld.Blocks[id].VertexPropertiesBack[1]));
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(x, y + 1, z, 5f), GlobalWorld.Blocks[id].VertexPropertiesBack[2]));
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(1 + x, y + 1, z, 5f), GlobalWorld.Blocks[id].VertexPropertiesBack[3]));
}
if (z > ZSize - 2)
{
if (this.ForwardChunk != -1 && (GlobalWorld.LoadedChunks[this.ForwardChunk].Blocks[x, y, 0] == 0 || GlobalWorld.Blocks[GlobalWorld.LoadedChunks[this.ForwardChunk].Blocks[x, y, 0]].Transparent))
{
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(x, y, 1 + z, 4f), GlobalWorld.Blocks[id].VertexPropertiesFront[0]));
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(x, y + 1, 1 + z, 4f), GlobalWorld.Blocks[id].VertexPropertiesFront[1]));
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(1 + x, y, 1 + z, 4f), GlobalWorld.Blocks[id].VertexPropertiesFront[2]));
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(1 + x, y + 1, 1 + z, 4f), GlobalWorld.Blocks[id].VertexPropertiesFront[3]));
}
}
else if (Blocks[x, y, z + 1] == 0 || GlobalWorld.Blocks[Blocks[x, y, z + 1]].Transparent)
{
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(x, y, 1 + z, 4f), GlobalWorld.Blocks[id].VertexPropertiesFront[0]));
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(x, y + 1, 1 + z, 4f), GlobalWorld.Blocks[id].VertexPropertiesFront[1]));
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(1 + x, y, 1 + z, 4f), GlobalWorld.Blocks[id].VertexPropertiesFront[2]));
ChunkVertices.Add(new VertexPositionNormalSmall(new Byte4(1 + x, y + 1, 1 + z, 4f), GlobalWorld.Blocks[id].VertexPropertiesFront[3]));
}
}