OpenGL实例化渲染不起作用,只显示一个实例

时间:2017-09-02 08:41:45

标签: c++ opengl graphics

我正在编写一个带有实例的迷你OpenGL程序。但是当我运行代码时,只显示了一个实例。我认为应该很容易,但我失败了。这是代码:

    #include <stdio.h>
    #include <stdlib.h>
    #include <GL/glew.h>
    #include <GLFW/glfw3.h>
    #include <iostream>
    #include <GL/glut.h>
    #include <vector>
    #include <fstream>
    #include <string> 
    #include <glm/glm.hpp>
    #include <glm/gtc/matrix_transform.hpp>
    #include <vector>

    #define WIDTH  1280
    #define HEIGHT 720

    static const std::string vertexShader = 
        "#version 330 core\n"
        "in vec3 position;\n"
        "in vec3 color;\n"
        "in ivec3 Glob_pos;\n"
        "uniform mat4 MVP;\n"
        "out vec3 ToFragColor;\n"
        "void main(){\n"
        "   gl_Position = MVP * vec4(vec3(Glob_pos) + position,1.0);\n"
        "   ToFragColor = color;\n"
        "}\n";

    static const std::string fragmentShader = 
        "#version 330 core\n"
        "in vec3 ToFragColor;\n"
        "uniform vec3 Cam;\n"
        "out vec3 out_color;\n"
        "void main(){\n"    
        "   out_color = ToFragColor;\n"
        "}\n";

    static const GLfloat CUBE_VERT[12*3*2*3] = {

        -1.0f,-1.0f,-1.0f,  1.0f, 0.0f, 1.0f,
        -1.0f,-1.0f, 1.0f,  0.0f, 0.0f, 1.0f,
        -1.0f, 1.0f, 1.0f,  0.0f, 1.0f, 1.0f,

         1.0f, 1.0f,-1.0f,  1.0f, 1.0f, 1.0f,
        -1.0f,-1.0f,-1.0f,  0.0f, 0.0f, 1.0f,   
        -1.0f, 1.0f,-1.0f,  0.0f, 1.0f, 1.0f,

         1.0f,-1.0f, 1.0f,  1.0f, 1.0f, 0.0f,   
        -1.0f,-1.0f,-1.0f,  0.0f, 0.0f, 0.0f,
         1.0f,-1.0f,-1.0f,  1.0f, 0.0f, 0.0f,

         1.0f, 1.0f,-1.0f,  1.0f, 1.0f, 1.0f,        
         1.0f,-1.0f,-1.0f,  1.0f, 0.0f, 1.0f,
        -1.0f,-1.0f,-1.0f,  0.0f, 0.0f, 1.0f,

        -1.0f,-1.0f,-1.0f,  1.0f, 0.0f, 1.0f,
        -1.0f, 1.0f, 1.0f,  0.0f, 1.0f, 1.0f,
        -1.0f, 1.0f,-1.0f,  1.0f, 1.0f, 1.0f,

         1.0f,-1.0f, 1.0f,  1.0f, 1.0f, 0.0f,
        -1.0f,-1.0f, 1.0f,  0.0f, 1.0f, 0.0f,
        -1.0f,-1.0f,-1.0f,  0.0f, 0.0f, 0.0f,

        -1.0f, 1.0f, 1.0f,  1.0f, 1.0f, 1.0f,
        -1.0f,-1.0f, 1.0f,  1.0f, 0.0f, 1.0f,
         1.0f,-1.0f, 1.0f,  0.0f, 0.0f, 1.0f,

         1.0f, 1.0f, 1.0f,  1.0f, 1.0f, 1.0f,
         1.0f,-1.0f,-1.0f,  0.0f, 0.0f, 1.0f,
         1.0f, 1.0f,-1.0f,  0.0f, 1.0f, 1.0f,

         1.0f,-1.0f,-1.0f,  0.0f, 0.0f, 1.0f,
         1.0f, 1.0f, 1.0f,  1.0f, 1.0f, 1.0f,
         1.0f,-1.0f, 1.0f,  1.0f, 0.0f, 1.0f,

         1.0f, 1.0f, 1.0f,  0.0f, 1.0f, 1.0f,
        -1.0f, 1.0f, 1.0f,  1.0f, 1.0f, 1.0f,
         1.0f,-1.0f, 1.0f,  0.0f, 0.0f, 1.0f,

                //TOP
         1.0f, 1.0f, 1.0f,  1.0f, 1.0f, -1.0f,
         1.0f, 1.0f,-1.0f,  1.0f, 0.0f, -1.0f,
        -1.0f, 1.0f,-1.0f,  0.0f, 0.0f, -1.0f,

         1.0f, 1.0f, 1.0f,  1.0f, 1.0f, -1.0f,
        -1.0f, 1.0f,-1.0f,  0.0f, 0.0f, -1.0f,
        -1.0f, 1.0f, 1.0f,  0.0f, 1.0f, -1.0f

    };

    GLuint LoadShaders();

    void setup(GLuint programID);
    void render(GLuint programID);
    void computeMatricesFromInputs(GLFWwindow* window);

    GLuint vao, vbo, ib;
    GLuint MatrixID;
    GLuint CamID;

    //For model view matrix calculation
    glm::vec3 CamLoc = glm::vec3(0,0,-5);
    glm::mat4 Projection = glm::perspective(glm::radians(45.0f), (float) WIDTH / (float)HEIGHT, 1.0f, 1000.0f);
    glm::mat4 View = glm::lookAt(
        CamLoc,
        glm::vec3(0,0,0),
        glm::vec3(0,1,0) 
    );
    glm::mat4 Model = glm::mat4(1.0f);
    glm::mat4 mvp = Projection * View * Model; 
    glm::vec3 direction;
    float horizontalAngle = 3.14f;
    float verticalAngle = 0.0f;
    float initialFoV = 45.0f;
    float speed = 3.0f;
    float mouseSpeed = 0.005f;
    float mtimeScale = 0.1f;
    float ktimeScale = 1.0f;
    float FoV = initialFoV; //- 5 * glfwGetMouseWheel();
    double lastPos[] = { 0,0 };
    const glm::vec3 null = glm::vec3(0,0,0);
    //For model view matrix calculation -- end

    std::vector<int> instanceObj;

    int main(int argc, char **argv){
        glutInit(&argc, argv);
        glfwInit();

        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

        GLFWwindow* window;
        window = glfwCreateWindow(WIDTH, HEIGHT, "DearDaniel's OpenGL", NULL, NULL);

        glfwMakeContextCurrent(window);

        glewExperimental = true; 
        glewInit();

        glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);

        GLuint programID = LoadShaders();
        MatrixID     = glGetUniformLocation(programID, "MVP");
        CamID        = glGetUniformLocation(programID, "Cam");

        glEnable (GL_DEPTH_TEST); glDepthFunc (GL_LESS);
        glEnable(GL_CULL_FACE); glCullFace(GL_BACK);

        glClearColor(0.0f, 0.0f, 0.4f, 0.0f);

        glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);

        setup(programID);

        do{
            glUseProgram(programID);    
            computeMatricesFromInputs(window);
            render(programID);
            glfwSwapBuffers(window);
            glfwPollEvents();
        } while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS && glfwWindowShouldClose(window) == 0 );

        glDeleteProgram(programID);

        return 0;

    }

    GLuint LoadShaders(){

        GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
        GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);

        char const * VertexSourcePointer = vertexShader.c_str();
        glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
        glCompileShader(VertexShaderID);

        char const * FragmentSourcePointer = fragmentShader.c_str();
        glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
        glCompileShader(FragmentShaderID);

        GLuint ProgramID = glCreateProgram();
        glAttachShader(ProgramID, VertexShaderID);
        glAttachShader(ProgramID, FragmentShaderID);
        glLinkProgram(ProgramID);

        glDetachShader(ProgramID, VertexShaderID);
        glDetachShader(ProgramID, FragmentShaderID);

        glDeleteShader(VertexShaderID);
        glDeleteShader(FragmentShaderID);

        return ProgramID;
    } 

    void setup(GLuint programID) {
        glGenVertexArrays(1, &vao);
        glBindVertexArray(vao);
        glGenBuffers(1, &vbo);
        glBindBuffer(GL_ARRAY_BUFFER, vbo);
        glBufferData(GL_ARRAY_BUFFER, 12*3*2*3*sizeof(int), CUBE_VERT, GL_STATIC_DRAW);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)                  0);
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
        glGenBuffers(1, &ib);
        glBindBuffer(GL_ARRAY_BUFFER, ib);
        glVertexAttribPointer(2, 3,   GL_INT, GL_FALSE, 3 * sizeof(  int), (void*)                  0);
        glEnableVertexAttribArray(0);
        glEnableVertexAttribArray(1);
        glEnableVertexAttribArray(2);
        glVertexAttribDivisor(2, 1);
        glBindVertexArray(0);
    }

    void render(GLuint programID) {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glBindVertexArray(vao);

        glBindBuffer(GL_ARRAY_BUFFER, ib);
        instanceObj.clear();
        for (int i = 0; i < 32; i+=2) 
            for (int j = 0; j < 32; j +=2) 
                for (int k = 0; k < 32; k +=2) {
                        instanceObj.push_back(i);
                        instanceObj.push_back(j);
                        instanceObj.push_back(k);
        }
        glBufferData(GL_ARRAY_BUFFER, sizeof(int)*instanceObj.size(), &instanceObj[0], GL_STATIC_DRAW);

        glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &mvp[0][0]);
        glUniform3f(CamID, CamLoc.x, CamLoc.y, CamLoc.z);
        glDrawArraysInstanced(GL_TRIANGLES, 0, 36, 16*16*16);
        glBindVertexArray(0);
    }

    void computeMatricesFromInputs(GLFWwindow* window){

        static double lastTime = glfwGetTime();
        double currentTime = glfwGetTime();
        float deltaTime = float(currentTime - lastTime);
        double xpos, ypos;

        glfwGetCursorPos(window, &xpos, &ypos);

        float hori = horizontalAngle + mouseSpeed * float( xpos - lastPos[0] ) * mtimeScale;
        float vert = verticalAngle   + mouseSpeed * float( ypos - lastPos[1] ) * mtimeScale;
        horizontalAngle = hori;
        if (vert > -3.14f/2.0f && vert < 3.14f/2.0f) verticalAngle = vert;

        lastPos[0] = xpos;
        lastPos[1] = ypos;

        direction = glm::vec3 (
            cos(verticalAngle) * sin(horizontalAngle), 
            sin(verticalAngle),
            cos(verticalAngle) * cos(horizontalAngle)
        );

        glm::vec3 right = glm::vec3(
            sin(horizontalAngle - 3.14f/2.0f), 
            0,
            cos(horizontalAngle - 3.14f/2.0f)
        );

        glm::vec3 up = glm::cross( right, direction );

        if (glfwGetKey( window, GLFW_KEY_UP ) == GLFW_PRESS)    CamLoc += direction * deltaTime * speed * ktimeScale;
        if (glfwGetKey( window, GLFW_KEY_DOWN ) == GLFW_PRESS)  CamLoc -= direction * deltaTime * speed * ktimeScale;
        if (glfwGetKey( window, GLFW_KEY_RIGHT ) == GLFW_PRESS) CamLoc += right * deltaTime * speed * ktimeScale;
        if (glfwGetKey( window, GLFW_KEY_LEFT ) == GLFW_PRESS)  CamLoc -= right * deltaTime * speed * ktimeScale;

        Projection = glm::perspective(glm::radians(FoV), 4.0f / 3.0f, 0.1f, 100.0f);

        View = glm::lookAt(
            CamLoc,           // Camera is here
            CamLoc+direction, // and looks here : at the same position, plus "direction"
            up                  // Head is up (set to 0,-1,0 to look upside-down)
        );

        lastTime = currentTime;

        mvp = Projection * View;

        for (int i = 0; i < 4; ++i) {
            for (int j = 0; j < 4; ++j) {
                printf("%f ", mvp[i][j]);
            }
            printf("\n");
        }

    }

我使用以下命令编译我的代码:

   g++ miniGL.cpp -Wall -std=c++11 -L/usr/local/lib -pthread -lGLEW -lGLU -lGL -lglut -lglfw3 -ldl -lrt -lXrandr -lXxf86vm -lXi -lXinerama -lX11 -lXcursor -lglfw -o ogl

我的目的是在屏幕上渲染16 * 16 * 16个立方体,但只有一个显示。我花了十多个小时进行调试。现在我放弃了,无耻地寻求帮助。

1 个答案:

答案 0 :(得分:0)

在为顶点属性glVertexAttribIPointer定义通用顶点属性数据的数组时,必须使用in ivec3 Glob_pos;glVertexAttribPointer仅用于浮点属性(整数数据将转换为浮点数)。

请参阅glVertexAttribPointer

  

对于glVertexAttribPointer,如果规范化设置为GL_TRUE,则表示以整数格式存储的值将映射到范围[-1,1](对于有符号值)或[ 0,1](对于无符号值)访问它们并转换为浮点。否则,值将直接转换为浮动而不进行规范化。

     

对于glVertexAttribIPointer,只有整数类型GL_BYTEGL_UNSIGNED_BYTEGL_SHORTGL_UNSIGNED_SHORTGL_INTGL_UNSIGNED_INT为公认。 值始终保留为整数值

注意,可能Glob_pos从未设置,并且始终具有相同但未定义的值。


由于您不使用glGetAttribLocation来获取顶点属性(positioncolorGlob_pos)的属性索引,因此您应该使用Layout Qualifiers:< / p>

layout (location = 0) in vec3 position;
layout (location = 1) in vec3 color;
layout (location = 2) in ivec3 Glob_pos;