Opengl 3d立方体不渲染

Posted

技术标签:

【中文标题】Opengl 3d立方体不渲染【英文标题】:Opengl 3d cube not rendering 【发布时间】:2019-04-07 12:00:24 【问题描述】:

似乎无法渲染我的对象,只出现黑屏。

// Shader program Macro
#ifndef GLSL
#define GLSL(Version, Source) "#version " #Version "\n" #Source
#endif

// variable declaritions for shader, windows size initialization, buffer and array objects
GLint shaderProgram, WindowWidth = 800, WindowHeight = 600;
GLuint VBO, VAO, EBO, texture;

函数

// Function prototypes
void UResizeWindow(int, int);
void URenderGraphics(void);
void UCreateShader(void);
void UCreateBuffers(void);

顶点和片段着色器

// vertex shader source code
const GLchar * vertexShaderSource = GLSL(330,
        layout (location = 0) in vec3 position; //vertex data from vertex attrib pointer 0
        layout (location = 1) in vec3 color; // color data from vertex attrib pointer 1

        out vec3 mobileColor;

        // global variables for the transform matrices
        uniform mat4 model;
        uniform mat4 view;
        uniform mat4 projection;

        void main()
        
            gl_Position = projection * view * model * vec4(position, 1.0f); // transform vertices to clip coordinates
            mobileColor = color; // references incoming color data
        
    );

const GLchar * fragmentShaderSource = GLSL(330,
        in vec3 mobileColor;

        out vec4 gpuColor;
    void main()
    
        gpuColor = vec4(mobileColor, 1.0);
    
    );
int main (int argc, char* argv[])

    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
    glutInitWindowSize(WindowWidth, WindowHeight);
    glutCreateWindow(WINDOW_TITLE);

    glutReshapeFunc(UResizeWindow);

    UCreateShader();
    UCreateBuffers();

    // use the shader program
    glUseProgram(shaderProgram);

    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glutDisplayFunc(URenderGraphics);
    glutMainLoop();

    //destroys buffer onjects once used
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteBuffers(1, &EBO);

    return 0;

// renders graphics
void URenderGraphics(void)

    glEnable(GL_DEPTH_TEST); // enables z-depth

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clears the screen

     glBindVertexArray(VAO); // activate the vertex array object before rendering and transforming them

        // transforms the object
         glm::mat4 model;
         model = glm::translate(model, glm::vec3(0.0f, 0.0f, 0.0f)); // place the object at the center of the viewport
         model = glm::rotate(model, 45.0f, glm::vec3(0.0, 1.0f, 0.0f)); // rotate the object 45 degrees on the x
         model = glm::scale(model, glm::vec3(2.0f, 2.0f, 2.0f)); // increase the object size by a scale of 2

         //transform the camera
         glm::mat4 view;
         view = glm::translate(view, glm::vec3(0.5f, 0.0f, -5.0f)); // moves teh world 0.5 units on x and -5 units in z;

         //creates a perspective projection
         glm::mat4 projection;
         projection = glm::perspective(45.0f, (GLfloat)WindowWidth / (GLfloat)WindowHeight, 0.1f, 100.0f);

         //retrieves and passes transform matrices to the shader program
         GLint modelLoc = glGetUniformLocation(shaderProgram, "model");
         GLint viewLoc = glGetUniformLocation(shaderProgram, "view");
         GLint projLoc = glGetUniformLocation(shaderProgram, "projection");

         glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
         glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
         glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));

     glutPostRedisplay();

     // draws the triangles
     glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);

     glBindVertexArray(0); // deactive the vertex array object

     glutSwapBuffers(); // flips the back with the front buffer every frame

着色器程序

// creates the shader program
void UCreateShader()

    //vertex shader
    GLint vertexShader = glCreateShader(GL_VERTEX_SHADER); // creates the vertex shader
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); // attaches the vertex shader to the source code
    glCompileShader(vertexShader); // compiles the vertex shader

    GLint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
    glCompileShader(fragmentShader);

    //shader program
    shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);

    // delete the vertex and fragment shaders once linked
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

缓冲区

// creates the buffer and array objects
void UCreateBuffers()


    // position and color data
    GLfloat vertices[] = 
            0.5f, 0.5f, 0.0f,     1.0f, 0.0f, 0.0f,
            0.5f, -0.5f, 0.0f,    0.0f, 1.0f, 0.0f,
           -0.5f, -0.5f, 0.0f,     0.0f, 0.0f, 1.0f,
           -0.5f, 0.5f, 0.0f,     1.0f, 0.0f, 1.0f,

            0.5f, 0.5f, -1.0f,     0.5f, 0.5f, 1.0f,
            0.5f, 0.5f, -1.0f,     1.0f, 1.0f, 0.5f,
           -0.5f, 0.5f, -1.0f,     0.2f, 0.2f, 0.5f,
           -0.5f, -0.5f, -1.0f,     1.0f, 0.0f, 1.0f
    ;

    GLuint indices[] = 

            0,1,3,
            1,2,3,
            0,1,4,
            0,4,5,
            0,5,6,
            0,3,6,
            4,5,6,
            4,6,7,
            2,3,6,
            2,6,7,
            1,4,7,
            1,2,7
    ;

    //index data to share position data
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glGenBuffers(1, &EBO);

    // activate the vertex array object before binding and settings anvbos and vertex attribute pointers
    glBindVertexArray(VAO);

    //activate the VBO
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    //activate the element buffer object / indices
    glBindBuffer(GL_ARRAY_BUFFER, EBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    // set attrivute pointer 0 to hold position data
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
    glEnableVertexAttribArray(0); //enables vertex attribute

    // set attribute pointer 1 to hold color data
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
    glEnableVertexAttribArray(1);

    glBindVertexArray(0);

【问题讨论】:

【参考方案1】:

在绑定Vertex Array Object (glBindVertexArray(VAO)) 之后,顶点索引必须绑定到目标GL_ELEMENT_ARRAY_BUFFER 而不是GL_ARRAY_BUFFER

glBindVertexArray(VAO)

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);

注意,索引缓冲区的名称值(EBO)在绑定时(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO))在Vertex Array Object中说明。请参阅Index buffers。glDrawElements 绘制缓冲区的“索引”,该缓冲区由当前绑定的 VAO 引用。由于 VAO 中没有说明索引缓冲区,因此没有绘制任何内容。


进一步说明,OpenGL Mathematics (GLM) 库需要以弧度而不是度数为单位的角度。 使用glm::radians 将度数转换为辐射度。 身份矩阵必须由单个 1.0 参数 (glm::mat4 model(1.0f)) 初始化:

例如

// transforms the object
glm::mat4 model(1.0f);
model = glm::translate(model, glm::vec3(0.0f, 0.0f, 0.0f));
model = glm::rotate(model, glm::radians(45.0f), glm::vec3(0.0, 1.0f, 0.0f));
model = glm::scale(model, glm::vec3(2.0f, 2.0f, 2.0f));

//transform the camera
glm::mat4 view(1.0f);
view = glm::translate(view, glm::vec3(0.5f, 0.0f, -5.0f)); 

//creates a perspective projection
glm::mat4 projection(1.0f);
projection = glm::perspective(glm::radians(45.0f),
             (GLfloat)WindowWidth / (GLfloat)WindowHeight, 0.1f, 100.0f);

【讨论】:

以上是关于Opengl 3d立方体不渲染的主要内容,如果未能解决你的问题,请参考以下文章

渲染时 3D 立方体出现拉伸

SDL2和3D渲染

通过OpenGL理解前端渲染原理

OpenGL奇怪的立方体旋转

OpenGL ES之3D模型加载和渲染

在 OpenGL 中渲染透明块