XNA тянет неправильную текстуру? - PullRequest
0 голосов
/ 04 сентября 2011

Я делаю (еще один) клон 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 Ответ

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

Попробовав несколько случайных вещей в отчаянии, я нашел решение для этого.Оказывается, что если вы используете один и тот же BasicEffect для разных текстур, он использует только последнюю присвоенную ему текстуру.Я перебирал список VertexBuffers и назначал разные текстуры для каждого.К тому времени, когда все перешло на видеокарту, была визуализирована только последняя использованная текстура, или она так выглядит.

Решением было создание отдельного базового эффекта для каждой необходимой мне текстуры и назначение только необходимых VertexBuffers.к конкретному базовому эффекту.

...