OpenGL Square无法正确渲染

时间:2015-04-25 04:37:17

标签: opengl d

正确渲染:

enter image description here

渲染不正确:

enter image description here

正确的渲染来自于我每平方使用6个顶点。不正确的渲染是当我尝试重新使用顶点并将其降低到每平方4个顶点时。

这是代码(我在示例中将addSquare称为6次):

module src.UltraMesh;
import grape;
import std.conv;
import std.stdio;
import grape.shader;
import std.math;
import std.stdio;
import std.traits;
import std.conv;
import std.algorithm;
import std.array;
import std.range;

class UltraMesh
{
    Appender!(float[]) vertices;
    Appender!(int[]) indices;
    Appender!(ubyte[]) color;
    bool wireframe;
    ubyte colorR, colorB, colorG, colorA;
    GLuint indiceBuffer;
    GLuint vertexBuffer;
    GLuint colorBuffer;
    GLuint vaoID;
    int indiceBufferSize = 0;
    int vertexBufferSize = 0;
    int colorBufferSize = 0;
    bool updateBuffers = true;
    GLint cameraUniformLocation;
    this()
    {
        if (program is null) {
            initializeShader();
        }
        wireframe = false;
        colorR = to!ubyte(255);
        colorB = to!ubyte(0);
        colorG = to!ubyte(0);
        colorA = to!ubyte(255);
        vertices = appender!(float[]); //Points
        indices = appender!(int[]); //Edges
        color = appender!(ubyte[]);

        glGenVertexArrays(1, &vaoID); // Create our Vertex Array Object  
        glBindVertexArray(vaoID); // Bind our Vertex Array Object so we can use it  

        //Create buffer for indices
        glGenBuffers(1, &indiceBuffer);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indiceBuffer); 
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, int.sizeof*3, null, GL_DYNAMIC_DRAW);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 

        //Create buffer for vertices
        glGenBuffers(1, &vertexBuffer);
        //Bind the buffer so we can work on it
        glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); 
        glBufferData(GL_ARRAY_BUFFER, float.sizeof*9, null, GL_DYNAMIC_DRAW);
        //Bind to the attribute so we can do stuff to it
        glBindAttribLocation(program, 0, cast(char*)"position");
        //Get the attribute location?
        GLint _location = glGetAttribLocation(program, cast(char*)"position");
        //Enable it for drawing
        glEnableVertexAttribArray(_location);
        //Describe the data of the attribute?
        glVertexAttribPointer(_location, 3, GL_FLOAT, GL_FALSE, 0, null);
        //Unbind the buffer
        glBindBuffer(GL_ARRAY_BUFFER, 0); 

        //Create buffer for colors
        glGenBuffers(1, &colorBuffer);
        //Bind the buffer so we can work on it
        glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
        glBufferData(GL_ARRAY_BUFFER, byte.sizeof*12, null, GL_DYNAMIC_DRAW);
        //Bind to the attribute so we can do stuff to it
        glBindAttribLocation(program, 1, cast(char*)"color");
        //Get the attribute location?
        _location = glGetAttribLocation(program, cast(char*)"color");
        //Enable it for drawing
        glEnableVertexAttribArray(_location);
        //Describe the data of the attribute?
        glVertexAttribPointer(_location, 4, GL_UNSIGNED_BYTE, GL_FALSE, 0, null);
        //Unbind the buffer
        glBindBuffer(GL_ARRAY_BUFFER, 0); 


        cameraUniformLocation = glGetUniformLocation(program, cast(char*)"pvmMatrix"); 

        glEnableVertexAttribArray(0); // Disable our Vertex Array Object  
        glBindVertexArray(0); // Disable our Vertex Buffer Object  
    }
    ~this() {
        glDeleteBuffers(1, &indiceBuffer);
        glDeleteBuffers(1, &vertexBuffer);
        glDeleteBuffers(1, &colorBuffer);
    }
    void updateAllBuffers() {
        updateIndiceBufferPartial(0, to!int(indices.data.length));
        updateVertexBufferPartial(0, to!int(vertices.data.length));
        updateColorBufferPartial(0, to!int(color.data.length));
    }
    void updateColorBuffer() {
        updateColorBufferPartial(0, to!int(color.data.length));
    }void updateVertexBuffer() {
        updateVertexBufferPartial(0, to!int(vertices.data.length));
    }void updateIndiceBuffer() {
        updateIndiceBufferPartial(0, to!int(indices.data.length));
    }
    void reserveIndiceBuffer(int length) {
        indiceBufferSize = length;
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indiceBuffer); 
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, int.sizeof*length, null, GL_DYNAMIC_DRAW);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 
    }
    void updateIndiceBufferPartial(int start, int length) {
        if (indiceBufferSize <= start+length) {
            indiceBufferSize = to!int(indiceBufferSize * 2 + 3);
            if (indiceBufferSize < start+length) {indiceBufferSize=start+length+3;}
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indiceBuffer); 
            glBufferData(GL_ELEMENT_ARRAY_BUFFER, int.sizeof*indiceBufferSize, null, GL_DYNAMIC_DRAW);
            glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, indices.data.length*int.sizeof, indices.data.ptr);
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 
        } else {
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indiceBuffer);
            glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, start*int.sizeof, length*int.sizeof, indices.data[start..start+length].ptr);
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 
        }
    }

    void reserveVertexBuffer(int length) {
        vertexBufferSize = length;
        glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); 
        glBufferData(GL_ARRAY_BUFFER, float.sizeof*length, null, GL_DYNAMIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
    }
    void updateVertexBufferPartial(int start, int length) {
        if (vertexBufferSize <= start+length) {
            vertexBufferSize = to!int(vertexBufferSize * 2 + 9);
            if (vertexBufferSize < start+length) {vertexBufferSize=start+length+9;}
            glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); 
            glBufferData(GL_ARRAY_BUFFER, float.sizeof*vertexBufferSize, null, GL_DYNAMIC_DRAW);
            glBufferSubData(GL_ARRAY_BUFFER, 0, vertices.data.length*float.sizeof, vertices.data.ptr);
            glBindBuffer(GL_ARRAY_BUFFER, 0); 
        } else {
            glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
            glBufferSubData(GL_ARRAY_BUFFER, start*float.sizeof, length*float.sizeof, vertices.data[start..start+length].ptr);
            glBindBuffer(GL_ARRAY_BUFFER, 0); 
        }
    }
    void reserveColorBuffer(int length) {
        colorBufferSize = length;
        glBindBuffer(GL_ARRAY_BUFFER, colorBuffer); 
        glBufferData(GL_ARRAY_BUFFER, byte.sizeof*length, null, GL_DYNAMIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER, 0); 
    }
    void updateColorBufferPartial(int start, int length) {
        if (colorBufferSize <= start+length) {
            colorBufferSize = to!int(colorBufferSize * 2 + 12);
            if (colorBufferSize < start+length) {colorBufferSize=start+length+12;}
            glBindBuffer(GL_ARRAY_BUFFER, colorBuffer); 
            glBufferData(GL_ARRAY_BUFFER, byte.sizeof*colorBufferSize, null, GL_DYNAMIC_DRAW);
            glBufferSubData(GL_ARRAY_BUFFER, 0, color.data.length*byte.sizeof, color.data.ptr);
            glBindBuffer(GL_ARRAY_BUFFER, 0); 
        } else {
            glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
            glBufferSubData(GL_ARRAY_BUFFER, start*byte.sizeof, length*byte.sizeof, color.data[start..start+length].ptr);
            glBindBuffer(GL_ARRAY_BUFFER, 0); 
        }
    }


    VertexGroup addTriangle(double triangleX, double triangleY, double triangleZ, double width) {
        if (vertices.capacity() == 0) {
            vertices.reserve(vertices.data.length*2 + 9);
        }
        if (indices.capacity() == 0) {
            indices.reserve(indices.data.length*2 + 3);
        }
        if (color.capacity() == 0) {
            color.reserve(color.data.length*2 + 12);
        }
        int firstVertex = to!int(vertices.data.length);
        int firstIndice = to!int(indices.data.length);
        int firstColor = to!int( color.data.length);


        vertices.put( [triangleX-width/2.0, triangleY-width/2.0, triangleZ,
            triangleX+width/2.0, triangleY-width/2.0, triangleZ,
            triangleX, triangleY+width/2.0, triangleZ ] );

        //Add the lines to connect vertices
        int n = to!int(indices.data.length);
        indices.put( [n, n+1, n+2] );

        //For each vertex we need a color R, G, B, A
        color.put( [colorR, colorG, colorB, colorA,
            colorR, colorG, colorB, colorA,
            colorR, colorG, colorB, colorA] );

        int lastVertex = to!int(vertices.data.length);
        int lastIndice = to!int(indices.data.length);
        int lastColor = to!int(color.data.length);

        if (updateBuffers) {
            updateIndiceBufferPartial(firstIndice, lastIndice-firstIndice);
            updateVertexBufferPartial(firstVertex, lastVertex-firstVertex);
            updateColorBufferPartial(firstColor, lastColor-firstColor);
        }

        return VertexGroup(firstVertex, lastVertex, firstColor, lastColor, firstIndice, lastIndice, this);

    }

    VertexGroup addSquare(double squareX, double squareY, double squareZ, double size) {
        if (vertices.capacity() == 0) {
            vertices.reserve(vertices.data.length*2 + 12);
        }
        if (indices.capacity() == 0) {
            indices.reserve(indices.data.length*2 + 6);
        }
        if (color.capacity() == 0) {
            color.reserve(color.data.length*2 + 16);
        }
        int firstVertex = to!int(vertices.data.length);
        int firstIndice = to!int(indices.data.length);
        int firstColor = to!int( color.data.length);

        vertices.put(
                [ squareX-size/2.0, squareY-size/2.0, squareZ,
                squareX-size/2.0, squareY+size/2.0, squareZ,
                squareX+size/2.0, squareY-size/2.0, squareZ,
                squareX+size/2.0, squareY+size/2.0, squareZ] );

        //Add the lines to connect vertices
        int n = to!int(indices.data.length);
        indices.put( [n, n+1, n+2, n+3, n+2, n+1] );

        //For each vertex we need a color R, G, B, A
        color.put( [colorR, colorG, colorB, colorA,
                colorR, colorG, colorB, colorA,
                colorR, colorG, colorB, colorA,
                colorR, colorG, colorB, colorA] );

        int lastVertex = to!int(vertices.data.length);
        int lastIndice = to!int(indices.data.length);
        int lastColor = to!int(color.data.length);

        if (updateBuffers) {
            updateIndiceBufferPartial(firstIndice, lastIndice-firstIndice);
            updateVertexBufferPartial(firstVertex, lastVertex-firstVertex);
            updateColorBufferPartial(firstColor, lastColor-firstColor);
        }

        return VertexGroup(firstVertex, lastVertex, firstColor, lastColor, firstIndice, lastIndice, this);

    }

    void render(Camera camera) {
        program.use();

        //Set the camera location uniform
        glUniformMatrix4fv(cameraUniformLocation, 1, GL_FALSE, camera.pvMat4.mat.ptr);

        // Wireframe Checking
        if (wireframe) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
        scope(exit) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

        //Draw the indices
        //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indiceBuffer);
        glBindVertexArray(vaoID); // Bind our Vertex Array Object  
        //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indiceBuffer);
        glDrawArrays(DrawMode.Triangles, 0, to!int(indices.data.length));
        //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
        //glBindVertexArray(0); // Unbind our Vertex Array Object  
        //glDrawElements(DrawMode.Triangles, to!int(indices.data.length), GL_UNSIGNED_INT, cast(void*)(0) );
        //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    }
}
static Shader vs;
static Shader fs;
static ShaderProgram program = null;
static void initializeShader() {
    vs = new Shader(ShaderType.Vertex, vertexShaderSource);
    fs = new Shader(ShaderType.Fragment, fragmentShaderSource);
    program = new ShaderProgram(vs, fs);
}
static immutable vertexShaderSource = q{
    #version 150
    in vec3 position;
    in vec4 color;
    uniform mat4 pvmMatrix;
    out vec4 vColor;

    void main() {
        vColor = color;
        gl_Position = pvmMatrix * vec4(position, 1.0);
    }
};

static immutable fragmentShaderSource = q{
    #version 150
    in vec4 vColor;
    out vec4 FragColor;

    void main() {
        FragColor = vColor;
    }
};
struct VertexGroup {
    int firstVertex, lastVertex;
    int firstColor, lastColor;
    int firstIndice, lastIndice;
    UltraMesh ultraMesh;
    float centerX = 0;
    float centerY = 0;
    float centerZ = 0;
    static VertexGroup opCall(int fV, int lV, int fC, int lC, int fI, int lI, UltraMesh uM)
    {
        VertexGroup vg = VertexGroup.init;
        vg.firstVertex = fV;
        vg.lastVertex = lV;
        vg.firstColor = fC;
        vg.lastColor = lC;
        vg.firstIndice = fI;
        vg.lastIndice = lI;
        vg.ultraMesh = uM;
        vg.calculateCenter();
        return vg;
    }
    void calculateCenter() {
        int vCount = (lastVertex - firstVertex)/3;
        for (int i = firstVertex; i < lastVertex; i+= 3) {
            //writeln("X: ", ultraMesh.vertices.data[i], ", Y: ", ultraMesh.vertices.data[i+1]);
            centerX += ultraMesh.vertices.data[i]/vCount;
            centerY += ultraMesh.vertices.data[i+1]/vCount;
            centerZ += ultraMesh.vertices.data[i+2]/vCount;
        }
    }
    void rotateX(float angle) {
        float s = sin(angle);
        float c = cos(angle);
        for (int i = firstVertex; i < lastVertex; i+=3) {
            float z = ultraMesh.vertices.data[i+2] - centerZ;
            float y = ultraMesh.vertices.data[i+1] - centerY;
            ultraMesh.vertices.data[i+2] = z * c - y * s + centerZ;
            ultraMesh.vertices.data[i+1] = y * c + z * s + centerY;
        }
        if (ultraMesh.updateBuffers) ultraMesh.updateVertexBufferPartial(firstVertex, lastVertex-firstVertex);
    }
    void rotateY(float angle) {
        float s = sin(angle);
        float c = cos(angle);
        for (int i = firstVertex; i < lastVertex; i+=3) {
            float x = ultraMesh.vertices.data[i] - centerX;
            float z = ultraMesh.vertices.data[i+2] - centerZ;
            ultraMesh.vertices.data[i] = x * c - z * s + centerX;
            ultraMesh.vertices.data[i+2] = z * c + x * s + centerZ;
        }
        if (ultraMesh.updateBuffers) ultraMesh.updateVertexBufferPartial(firstVertex, lastVertex-firstVertex);
    }
    void rotateZ(float angle) {
        float s = sin(angle);
        float c = cos(angle);
        for (int i = firstVertex; i < lastVertex; i+=3) {
            float x = ultraMesh.vertices.data[i] - centerX;
            float y = ultraMesh.vertices.data[i+1] - centerY;
            ultraMesh.vertices.data[i] = x * c - y * s + centerX;
            ultraMesh.vertices.data[i+1] = y * c + x * s + centerY;
        }
        if (ultraMesh.updateBuffers) ultraMesh.updateVertexBufferPartial(firstVertex, lastVertex-firstVertex);
    }
    void translateX(float value) {
        for (int i = firstVertex; i < lastVertex; i+= 3) {
            ultraMesh.vertices.data[i] += value;
        }
        centerX += value;
        if (ultraMesh.updateBuffers) ultraMesh.updateVertexBufferPartial(firstVertex, lastVertex-firstVertex);
    }
    void translateY(float value) {
        for (int i = firstVertex; i < lastVertex; i+= 3) {
            ultraMesh.vertices.data[i+1] += value;
        }
        centerY += value;
        if (ultraMesh.updateBuffers) ultraMesh.updateVertexBufferPartial(firstVertex, lastVertex-firstVertex);
    }
    void translateZ(float value) {
        for (int i = firstVertex; i < lastVertex; i+= 3) {
            ultraMesh.vertices.data[i+2] += value;
        }
        centerZ += value;
        if (ultraMesh.updateBuffers) ultraMesh.updateVertexBufferPartial(firstVertex, lastVertex-firstVertex);
    }
    void setPosition(float xPos, float yPos, float zPos) {
        float moveX = xPos-centerX;
        float moveY = yPos-centerY;
        float moveZ = zPos-centerZ;
        centerX = xPos;
        centerY = yPos;
        centerZ = zPos;
        for (int i = firstVertex; i < lastVertex; i+= 3) {
            ultraMesh.vertices.data[i] += moveX;
            ultraMesh.vertices.data[i+1] += moveY;
            ultraMesh.vertices.data[i+2] += moveZ;
        }
        if (ultraMesh.updateBuffers) ultraMesh.updateVertexBufferPartial(firstVertex, lastVertex-firstVertex);
    }
    void setColor(float r, float g, float b, float a) {
        ubyte rByte = to!ubyte(to!int(r*255));
        ubyte gByte = to!ubyte(to!int(g*255));
        ubyte bByte = to!ubyte(to!int(b*255));
        ubyte aByte = to!ubyte(to!int(a*255));
        for (int i = firstColor; i < lastColor; i += 4) {
            ultraMesh.color.data[i] = rByte;
            ultraMesh.color.data[i+1] = gByte;
            ultraMesh.color.data[i+2] = bByte;
            ultraMesh.color.data[i+3] = aByte;
        }
        if (ultraMesh.updateBuffers) ultraMesh.updateColorBufferPartial(firstColor, lastColor-firstColor);
    }
}

Pastebin以获得更好的格式:

http://pastebin.com/1B9B2KsU

我相信我正确设置了指数,知道为什么会这样吗?

1 个答案:

答案 0 :(得分:-1)

n应该等于vertices/3而不是indices