OpenGL 4.1索引绘图问题

时间:2015-02-15 12:37:33

标签: c# opengl rendering opentk

我正在尝试渲染大量的立方体,例如" Minecraft"一个使用C#+ OpenTK + OpenGL 4.1的块。 为此,我创建了一个类型为" ElementArrayBuffer"的缓冲区。索引和类型" ArrayBuffer"的缓冲区存储顶点。 但我认为要描述它,比检查代码更困难。 如果有人有疑问请告诉我。

所以现在问题。 渲染结果不是我想要的,我不明白为什么和什么是错的。 如果我渲染这个我得到这个结果: enter image description here

class Chunk
{
    // The size of the chunk
    // One unit means one cube
    public const int WIDTH = 5;
    public const int HEIGHT = 5;
    public const int DEPTH = 2;

    private int[][][] mData;

    // The attribute location the the shader program
    private int mVePositionLocation;

    private int mVertexArray;
    private int mIndexBuffer;
    private int mVertexBuffer;

    private int mIndexCount;

    public Chunk(int pVePositionLocation)
    {
        mVePositionLocation = pVePositionLocation;

        GenerateData();
        GenerateMesh();
    }

    private void GenerateData()
    {
        mData = new int[DEPTH][][];
        for(int z = 0; z < DEPTH; z++)
        {
            mData[z] = new int[HEIGHT][];
            for(int y = 0; y < HEIGHT; y++)
            {
                mData[z][y] = new int[WIDTH];
                for(int x = 0; x < WIDTH; x++)
                {
                    mData[z][y][x] = 1;
                }
            }
        }


    }
    private void GenerateMesh()
    {
        Queue<float> vertices = new Queue<float>();
        Queue<uint> indices = new Queue<uint>();
        uint offset = 0;

        for (int z = 0; z < DEPTH; z++)
        {
            for (int y = 0; y < HEIGHT; y++)
            {
                for (int x = 0; x < WIDTH; x++)
                {
                    // If the value is bigger than 0 there is a cube so it should be generated
                    if(mData[z][y][x] > 0)
                    {
                        GenerateCube(x, y, z, offset, vertices, indices);

                        // Normally 36 indices offset, but for now I only generate the front face of each cube so only 6 indices
                        offset += 6;
                    }
                }
            }
        }

        // Create and fill the buffer with the indices
        mIndexBuffer = GL.GenBuffer();
        GL.BindBuffer(BufferTarget.ElementArrayBuffer, mIndexBuffer);
        GL.BufferData<uint>(BufferTarget.ElementArrayBuffer, (IntPtr)(indices.Count * sizeof(uint)), indices.ToArray(), BufferUsageHint.StaticDraw);

        mVertexArray = GL.GenVertexArray();
        GL.BindVertexArray(mVertexArray);

        // The buffer with the vertices
        mVertexBuffer = GL.GenBuffer();
        GL.BindBuffer(BufferTarget.ArrayBuffer, mVertexBuffer);
        GL.BufferData<float>(BufferTarget.ArrayBuffer, (IntPtr)(vertices.Count * sizeof(float)), vertices.ToArray(), BufferUsageHint.StaticDraw);

        // The shader only needs the position
        GL.EnableVertexAttribArray(mVePositionLocation);
        GL.VertexAttribPointer(mVePositionLocation, 3, VertexAttribPointerType.Float, false, 3 * sizeof(float), 0);

        // Store the index count, so I can render later
        mIndexCount = indices.Count;
    }
    private void GenerateCube(int pX, int pY, int pZ, uint pOffset, Queue<float> pVertices, Queue<uint> pIndices)
    {
        // Front face vertices
        pVertices.Enqueue(pX);
        pVertices.Enqueue(pY);
        pVertices.Enqueue(pZ + Cube.DEPTH);

        pVertices.Enqueue(pX + Cube.WIDTH);
        pVertices.Enqueue(pY);
        pVertices.Enqueue(pZ + Cube.DEPTH);

        pVertices.Enqueue(pX);
        pVertices.Enqueue(pY + Cube.HEIGHT);
        pVertices.Enqueue(pZ + Cube.DEPTH);

        pVertices.Enqueue(pX + Cube.WIDTH);
        pVertices.Enqueue(pY + Cube.HEIGHT);
        pVertices.Enqueue(pZ + Cube.DEPTH);

        // Front face indices
        pIndices.Enqueue(pOffset + 0);
        pIndices.Enqueue(pOffset + 2);
        pIndices.Enqueue(pOffset + 3);

        pIndices.Enqueue(pOffset + 0);
        pIndices.Enqueue(pOffset + 3);
        pIndices.Enqueue(pOffset + 1);
    }

    public void Render()
    {
        GL.BindBuffer(BufferTarget.ElementArrayBuffer, mIndexBuffer);
        GL.BindVertexArray(mVertexArray);
        GL.DrawElements(BeginMode.Triangles, mIndexCount, DrawElementsType.UnsignedInt, 0);
    }
}

着色器程序:

    string vertexShaderSource = "#version 410\n" +
                                "\n" +
                                "uniform mat4 un_Projection; \n" +
                                "uniform mat4 un_Transform; \n" +
                                "\n" +
                                "layout(location = 0) in vec3 ve_Position;\n" +
                                "\n" +
                                "out vec4 fr_Color;" +
                                "\n" +
                                "void main()\n" +
                                "{\n" +
                                "   fr_Color = vec4(1, 0, 0, 1);\n" +
                                "   gl_Position = un_Projection * un_Transform * vec4(ve_Position.xyz, 1);\n" +
                                "}\n";

    string fragmentShaderSource =   "#version 410\n" +
                                    "\n" +
                                    "in vec4 fr_Color;\n" +
                                    "\n" +
                                    "out vec4 fi_Color;\n" +
                                    "\n" +
                                    "void main()\n" +
                                    "{\n" +
                                    "   fi_Color = fr_Color;\n" +
                                    "}\n";

如果有人想要完整的项目文件夹: http://www.file-upload.net/download-10301899/Project.zip.html

1 个答案:

答案 0 :(得分:0)

好的,我发现了错误。 我不应该

// Normally 36 indices offset, but for now I only generate the front face of each cube so only 6 indices
offset += 6;

应该是

// 4 vertices a face so add 4 offset a cube
offset += 4;