XNA тянет неправильную текстуру?
Я делаю (другой) MineCraft клон, и я столкнулся с интересной проблемой. У меня есть общедоступное перечисление, в котором перечислены все типы кубов, которыми может быть конкретный куб, и у меня есть трехмерный массив, содержащий кубы. Каждый куб имеет определенный тип, и я перебираю этот массив, чтобы получить вершины для каждого куба, а затем передаю эти вершины в буфер вершин, предназначенный для определенного типа куба. Когда я создаю случайный массив кубов или один куб и говорю ему, какой должна быть текстура, все рисует, как и ожидалось. Сейчас я пытаюсь выяснить, как нарисовать случайную "поверхность" кубиков травы, и заполнить все, что ниже по оси Y кубиками грязи. Но происходит самое странное: самый верхний кубик - это грязь, и он наполняет все нижние кубиками травы! Когда я отключаю петлю, чтобы заполнить подземелье грязью, самый верхний куб отображает траву, как и предполагалось.
Вот то, что я считаю соответствующими частями кода. Вот где установлен тип куба:
// Create a random surface level
Perlin perlin = new Perlin();
for (int x = 0; x < Game.ChunkWidth_X; x++)
{
for (int z = 0; z < Game.ChunkDepth_Z; z++)
{
double XVal = Convert.ToDouble(x) * 1.1;
double ZVal = Convert.ToDouble(z) * 1.1;
double YVal = Game.ChunkHeight_Y / 2 * 1.1;
double PerlinValue = perlin.GetValue(XVal, YVal, ZVal);
int YVal_new = Convert.ToInt32(YVal + (PerlinValue * 10));
if (YVal_new > Game.ChunkHeight_Y - 1) { YVal_new = Game.ChunkHeight_Y - 1; }
if (YVal_new < 0) { YVal_new = 0; }
// Set the grass cube
Cube NewCube = new Cube(new Vector3(0.5f, 0.5f, 0.5f), new Vector3(x, YVal_new, z));
NewCube.cubeType = CubeType.Grass;
CubeGrid[x, YVal_new, z] = NewCube;
// Fill below it with dirt
for (int y = YVal_new - 1; y >= 0; y--)
{
Cube NewCube2 = new Cube(new Vector3(0.5f, 0.5f, 0.5f), new Vector3(x, y, z));
NewCube2.cubeType = CubeType.Dirt;
CubeGrid[x, y, z] = NewCube2;
}
// Fill above it with air
for (int y = YVal_new + 1; y < Game.ChunkHeight_Y; y++)
{
Cube NewCube2 = new Cube(new Vector3(0.5f, 0.5f, 0.5f), new Vector3(x, y, z));
NewCube2.cubeType = CubeType.Air;
CubeGrid[x, y, z] = NewCube2;
}
}
}
Вот где я вытягиваю вершины, чтобы поместить в соответствующий буфер:
Dictionary<CubeType, List<VertexPositionNormalTexture>> DrawableVertices = new Dictionary<CubeType, List<VertexPositionNormalTexture>>();
// Get the proper vertices for each cube type and put in the appropriate dictionary
for (int x = 0; x < Game.ChunkWidth_X; x++)
{
for (int z = 0; z < Game.ChunkDepth_Z; z++)
{
for (int y = 0; y < Game.ChunkHeight_Y; y++)
{
CubeGrid[x,y,z].CreateVertices();
string test = CubeGrid[x, y, z].cubeType.ToString();
foreach (VertexPositionNormalTexture TargetVertex in CubeGrid[x, y, z].DisplayableVertices)
{
if (!DrawableVertices.ContainsKey(CubeGrid[x, y, z].cubeType))
{
List<VertexPositionNormalTexture> NewList = new List<VertexPositionNormalTexture>();
NewList.Add(TargetVertex);
DrawableVertices.Add(CubeGrid[x, y, z].cubeType, NewList);
}
else
{
DrawableVertices[CubeGrid[x, y, z].cubeType].Add(TargetVertex);
}
}
}
}
}
Вот вторая часть этого:
foreach (KeyValuePair<CubeType, List<VertexPositionNormalTexture>> KVP in DrawableVertices)
{
VertexBuffer cubeBuffer = new VertexBuffer(device, typeof(VertexPositionNormalTexture), KVP.Value.Count, BufferUsage.WriteOnly);
cubeBuffer.SetData(KVP.Value.ToArray());
// Update our collection of vertex buffers
CubeType_VertexBuffers[KVP.Key] = cubeBuffer;
// Get the triangle count for the buffer
CubeType_TriangleCount[KVP.Key] = KVP.Value.Count / 3;
}
Наконец, вот моя ничья:
// Go through each vertex buffer we have created, and draw it.
foreach (KeyValuePair<CubeType, VertexBuffer> KVP in CubeType_VertexBuffers)
{
foreach (EffectPass pass in testEffect.CurrentTechnique.Passes)
{
if (CubeType_TriangleCount[KVP.Key] > 0) // if this buffer has triangles, draw it.
{
pass.Apply();
testEffect.View = camera.ViewMatrix;
testEffect.TextureEnabled = true;
testEffect.Projection = camera.ProjectionMatrix;
testEffect.World = worldMatrix;
testEffect.Texture = CubeType_Texture[KVP.Key];
device.SetVertexBuffer(KVP.Value);
device.DrawPrimitives(PrimitiveType.TriangleList, 0, CubeType_TriangleCount[KVP.Key]);
}
}
}
base.Draw(gameTime);
Самое странное, что когда я вручную устанавливаю типы кубов, все рисуется с правильной текстурой, как и ожидалось. Какие еще вещи я должен попытаться устранить? Я пытался создать определенный эффект для каждого типа куба, но безрезультатно.
1 ответ
Попробовав несколько случайных вещей в отчаянии, я нашел решение для этого. Оказывается, что если вы используете один и тот же BasicEffect для разных текстур, он использует только последнюю присвоенную ему текстуру. Я перебирал список VertexBuffers и назначал разные текстуры для каждого. К тому времени, когда все перешло на видеокарту, была визуализирована только последняя использованная текстура, или она так выглядит.
Решение состояло в том, чтобы создать отдельный BasicEffect для каждой необходимой мне текстуры и назначить только VertexBuffers, необходимые для конкретного BasicEffect.