OpenGL 对象不能正确渲染?

Posted

技术标签:

【中文标题】OpenGL 对象不能正确渲染?【英文标题】:OpenGL object not rendering correctly? 【发布时间】:2019-04-06 22:12:55 【问题描述】:

代码正常运行,没有任何错误,但对象显示为白色。我使用的 IDE 是 Eclipse。

我尝试了一些调试,在UCreateBuffers() 中发现错误#1282。

// header inclusions
#include <iostream>
#include <GL/glew.h>
#include <GL/freeglut.h>

//GLM math header inclusions
#include <GL/glm.hpp>
#include <GL/gtc/matrix_transform.hpp>
#include <GL/gtc/type_ptr.hpp>

using namespace std;

#define WINDOW_TITLE "Modern OpenGL" // window title macro

// shader program macro
#ifndef GLSL
#define GLSL(Version, Source) "#Version " #Version "\n" #Source
#endif

//variable declarations for shader, window size initialization, buffer and array objects
GLint shaderProgram, WindowWidth = 800, WindowHeight = 600;
GLuint VBO, VAO;

GLfloat cameraSpeed = 0.0005f;

GLchar currentKey; // will store key pressed

//global vector declarations
glm::vec3 cameraPosition = glm::vec3(0.0f, 0.0f, 5.0f);
glm::vec3 CameraUpY = glm::vec3(0.0f, 1.0f, 0.0f);
glm::vec3 CameraForwardZ = glm::vec3(0.0f, 0.0f, -1.0f);


// function prototypes
void UResizeWindow(int, int);
void URenderGraphics(void);
void UCreateShader(void);
void UCreateBuffers(void);
void UKeyboard(unsigned char key, int x, int y);
void UKeyReleased(unsigned char key, int x, int y);

//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; // variable to transfer color data to the fragment shader

        // 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); //transforms vertices to clip coordinates
    mobileColor = color; // references incoming color data


);

// fragment shader source code
const GLchar * fragmentShaderSource = GLSL(330,

        in vec3 mobileColor; // variable to hold incoming color data from vertex shader

        out vec4 gpuColor; // variable to pass color data to the gpu

    void main()
    
        gpuColor = vec4(mobileColor, 1.0); // sends color data to the gpu for rendering
    
);


//main program

int main(int argc, char* argv[])

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

    glutReshapeFunc(UResizeWindow);

    glewExperimental = GL_TRUE;
        if (glewInit() != GLEW_OK)
        
            std::cout << "Failed to initialize GLEW" << std::endl;
            return -1;
        

    UCreateShader();

    UCreateBuffers();

    //use the shader program
    glUseProgram(shaderProgram);


    glClearColor(0.0f, 0.0f, 0.0f, 1.0f); //set background color

    glutDisplayFunc(URenderGraphics);

    glutKeyboardFunc(UKeyboard); // detects key press

    glutKeyboardUpFunc(UKeyReleased); // detects key release

    glutMainLoop();

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

    return 0;


//resizes the window
void UResizeWindow(int w, int h)

    WindowWidth = w;
    WindowHeight = h;
    glViewport(0, 0, WindowWidth, WindowHeight);



// renders graphics
void URenderGraphics(void)


    glEnable(GL_DEPTH_TEST); // enable z-depth

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

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

     // Camera Movement Logic
     if(currentKey =='w')
         cameraPosition += cameraSpeed * CameraForwardZ;

     if(currentKey =='s')
         cameraPosition -= cameraSpeed * CameraForwardZ;

     if(currentKey =='a')
         cameraPosition -= glm::normalize(glm::cross(CameraForwardZ, CameraUpY)) * cameraSpeed;

     if(currentKey =='d')
         cameraPosition += glm::normalize(glm::cross(CameraForwardZ, CameraUpY)) * cameraSpeed;


    // 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::lookAt(cameraPosition, cameraPosition + CameraForwardZ, CameraUpY);

     //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
    glDrawArrays(GL_TRIANGLES, 0, 36);

    glBindVertexArray(0);

    glutSwapBuffers(); // flips the back buffer 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

        //fragment 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);


void UCreateBuffers()


    GLfloat vertices[] = 
                                //positions           //Color
                                -0.5f, -0.5f, -0.5f,  1.0f, 0.0f, 0.0f,
                                 0.5f, -0.5f, -0.5f,  1.0f, 0.0f, 0.0f,
                                 0.5f,  0.5f, -0.5f,  1.0f, 0.0f, 0.0f,
                                 0.5f,  0.5f, -0.5f,  1.0f, 0.0f, 0.0f,
                                -0.5f,  0.5f, -0.5f,  1.0f, 0.0f, 0.0f,
                                -0.5f, -0.5f, -0.5f,  1.0f, 0.0f, 0.0f,

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

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

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

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

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

                            ;


    //generate buffer Ids
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);

    //activate the vertex array object before binding and setting any VBOs and Vertex Attribute Pointers
    glBindVertexArray(VAO);

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

    //set attribute 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); // enables vertex attribute

    glBindVertexArray(0);// enable the Vao which is good pratice





// implements the UKeyboar function
void UKeyboard(unsigned char key, GLint x, GLint y)

    switch(key)

    case 'w':
        cout << "You pressed w!" <<endl;
        break;

    case 's':
        cout << "You pressed s!" <<endl;
        break;

    case 'a':
        cout << "You pressed a!" <<endl;
        break;

    case 'd':
        cout << "You pressed d!" <<endl;
        break;

    default:
        cout << "Press a key!" << endl;

    



//implements the UkeyRelease function
void UKeyReleased(unsigned char key, GLint x, GLint y)

    cout << "Key released!" <<endl;

【问题讨论】:

您的“缓冲函数:...”只是显示与着色器相同的文本。然而,看看你如何设置你的 VAO 是相当重要的,因为我怀疑问题可能在那里(考虑到你的颜色似乎来自哪里)。另外,我没有看到你在任何地方打电话给glUseProgram() @Michael 我在上面做了一些编辑。添加了 Main 和更改缓冲区功能。我是 glUseProgram(shaderProgram) 好的。您提到在某处出现错误 1282。这究竟发生在哪里?除此之外,一般来说查看enabling debug output 可能不会有什么坏处。 尝试在几个位置渲染对象时发生这种情况 【参考方案1】:

着色器无法编译。 GLSL 区分大小写。版本限定符必须是 #version 而不是 #Version

#define GLSL(Version, Source) "#Version " #Version "\n" #Source

#define GLSL(Version, Source) "#version " #Version "\n" #Source

我建议检查编译和链接错误并添加错误日志记录。

编译错误可以通过glGetShaderiv/glGetShaderInfoLog得到:

例如

#include <vector>
void UCompileShader( GLuint shader )

    glCompileShader( shader );

    GLint status;
    glGetShaderiv( shader, GL_COMPILE_STATUS, &status );
    if ( status == GL_FALSE )
    
        GLint logLen;
        glGetShaderiv( shader, GL_INFO_LOG_LENGTH, &logLen );
        std::vector< char >log( logLen );
        GLsizei written;
        glGetShaderInfoLog( shader, logLen, &written, log.data() );
        std::cout << "compile error:" << std::endl << log.data() << std::endl;
    

链接错误可以通过glGetProgramiv/glGetProgramInfoLog得到:

例如

void ULinkShader( GLuint program )

    glLinkProgram( program );

    GLint status;
    glGetProgramiv( program, GL_LINK_STATUS, &status );
    if ( status == GL_FALSE )
    
        GLint logLen;
        glGetProgramiv( program, GL_INFO_LOG_LENGTH, &logLen );
        std::vector< char >log( logLen );
        GLsizei written;
        glGetProgramInfoLog( program, logLen, &written, log.data() );
        std::cout  << "link error:" << std::endl << log.data() << std::endl;
    

//creates the shader program
void UCreateShader()

    //vertex shader
    GLint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); 
    UCompileShader(vertexShader); // compiles the vertex shader

    //fragment shader
    GLint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
    UCompileShader(fragmentShader);

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

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

【讨论】:

兔子谢谢你。一切正常。 IDE 不抛出错误或警告的原因是什么。对于大写单词? @solidsandwich 驱动程序生成错误。但是您必须通过glGetProgramiv 得到错误。一个选项是启用Debug Output。

以上是关于OpenGL 对象不能正确渲染?的主要内容,如果未能解决你的问题,请参考以下文章

基于OpenGL编写一个简易的2D渲染框架-07 鼠标事件和键盘事件

OpenGL:多种渲染方法.. 何时使用哪个?

实例渲染 OpenGL

OpenGL 多重渲染目标 - 黑色输出

opengl 纹理无法正确渲染

OpenGL顶点缓冲区不正确的渲染