【问题标题】:OpenGL renders in release mode but not debug modeOpenGL 在发布模式下渲染,但不是调试模式
【发布时间】:2016-03-19 10:00:51
【问题描述】:

现在我正在使用 Visual Studio 2015 编写一个基本的 OpenGL 包装器,我遇到了一个非常奇怪的现象,即当我在调试模式下构建和运行时,我的立方体没有被渲染。然而,在发布模式下,一切似乎都完美呈现。

值得注意的是,程序确实在调试模式下运行,它确实用我设置的绿色清除了屏幕。所以看起来OpenGL在一定程度上是有效的。问题是它没有像在发布模式下那样渲染我的立方体网格。我通过调试确认我的资产(着色器和图像文件)在调试模式下正确加载,所以这似乎不是问题。

在代码方面,以下是程序的有趣部分:

Main.cpp:

renderer.Clear(0.2f, 0.3f, 0.3f, 1.0f);

for(GLuint i = 0; i < 10; ++i) {
    renderer.PushMatrix();
    renderer.Translate(cubePositions[i].x, cubePositions[i].y, cubePositions[i].z);
    renderer.Rotate(20.0f * i, glm::vec3(1.0f, 0.3f, 0.5f));
    renderer.Render(cube);
    renderer.PopMatrix();
}

window.SwapBuffers();

Renderer.cpp:

void Renderer::updateMVP() const {
    glm::mat4 _proj = camera.GetProjectionMatrix();
    glm::mat4 _view = camera.GetViewMatrix();
    glm::mat4 _model = model.top();
    glUniformMatrix4fv(glGetUniformLocation(shader.GetProgram(), "projection"), 1, GL_FALSE, glm::value_ptr(_proj));
    glUniformMatrix4fv(glGetUniformLocation(shader.GetProgram(), "view"), 1, GL_FALSE, glm::value_ptr(_view));
    glUniformMatrix4fv(glGetUniformLocation(shader.GetProgram(), "model"), 1, GL_FALSE, glm::value_ptr(_model));
}

void Renderer::Clear(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) const {
    glClearColor(red, green, blue, alpha);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}

void Renderer::Render(const Mesh& mesh) const {
    shader.Use();
    updateMVP();
    mesh.Render(this->shader);
}

Mesh.cpp:

void Mesh::Render(const Shader& shader) const {
    assert(this->VAO);

    for (GLuint i = 0; i < this->textures.size(); ++i) {
        shader.BindTexture(this->textures[i], i);
    }

    glBindVertexArray(this->VAO);
    glDrawElements(GL_TRIANGLES, this->indices.size(), GL_UNSIGNED_INT, 0);
    glBindVertexArray(0);

    for (GLuint i = 0; i < this->textures.size(); ++i) {
        shader.UnbindTexture(i);
    }
}

我正在使用以下(静态)库:GLEWGLFWSOIL2

我也在使用仅标头库:GLM

在构建静态库时,我确保它们都是使用 Visual Studio 的 v140 平台工具集构建的。我在 Debug 和 Release 中都构建了每个静态库。 Debug 版本都是使用 /MDd CRT 构建的,Release 版本是使用 /MD CRT 构建的。

我所有的代码和项目配置文件都在这里开源:Github

非常感谢任何帮助!谢谢。

【问题讨论】:

    标签: c++ debugging opengl visual-studio-2015


    【解决方案1】:

    问题:

    我觉得自己很傻。我进行了一堆 glError 检查,并设法将问题归结为生成立方体网格的函数,而我依赖于 RVO。但是对于 Visual Studio,RVO 显然只在发布模式下完成,而不是在调试模式下完成。因此,我的网格的析构函数在创建后立即被调用,在渲染之前将其从 GPU 内存中删除。

    解决办法:

    始终始终关注Rule of 5。解决方案是简单地将复制和移动构造函数/赋值运算符添加到我的 Mesh 和 Texture 类中,以防止释放它们的托管资源。

    网格析构函数:

    Mesh::~Mesh() {
        glDeleteVertexArrays(1, &this->VAO);
        glDeleteBuffers(1, &this->VBO);
        glDeleteBuffers(1, &this->EBO);
    }
    

    立方体创建功能:

    sr::Mesh createCube() {
        sr::Mesh mesh;
        mesh.AddTexture(sr::Texture("wood_container.jpg", "Texture1"));
        mesh.AddTexture(sr::Texture("awesome_face.png", "Texture2"));
    
        glm::vec3 p1(-0.5f, -0.5f,  0.5f);
        glm::vec3 p2( 0.5f, -0.5f,  0.5f);
        glm::vec3 p3( 0.5f,  0.5f,  0.5f);
        glm::vec3 p4(-0.5f,  0.5f,  0.5f);
        glm::vec3 p5( 0.5f, -0.5f, -0.5f);
        glm::vec3 p6(-0.5f, -0.5f, -0.5f);
        glm::vec3 p7(-0.5f,  0.5f, -0.5f);
        glm::vec3 p8( 0.5f,  0.5f, -0.5f);
    
        glm::vec2 tc00(0.0f, 0.0f);
        glm::vec2 tc01(0.0f, 1.0f);
        glm::vec2 tc10(1.0f, 0.0f);
        glm::vec2 tc11(1.0f, 1.0f);
    
        glm::vec3 norm;
    
        GLuint v1, v2, v3, v4, v5, v6, v7, v8;
    
        // Front
        norm = glm::vec3(0.0f, 0.0f, 1.0f);
        v1 = mesh.AddVertex(p1, norm, tc00);
        v2 = mesh.AddVertex(p2, norm, tc10);
        v3 = mesh.AddVertex(p3, norm, tc11);
        v4 = mesh.AddVertex(p4, norm, tc01);
        mesh.AddTriangle(v1, v2, v3);
        mesh.AddTriangle(v1, v3, v4);
    
        // Back
        norm = glm::vec3(0.0f, 0.0f, -1.0f);
        v5 = mesh.AddVertex(p5, norm, tc00);
        v6 = mesh.AddVertex(p6, norm, tc10);
        v7 = mesh.AddVertex(p7, norm, tc11);
        v8 = mesh.AddVertex(p8, norm, tc01);
        mesh.AddTriangle(v5, v6, v7);
        mesh.AddTriangle(v5, v7, v8);
    
        // Right
        norm = glm::vec3(1.0f, 0.0f, 0.0f);
        v2 = mesh.AddVertex(p2, norm, tc00);
        v5 = mesh.AddVertex(p5, norm, tc10);
        v8 = mesh.AddVertex(p8, norm, tc11);
        v3 = mesh.AddVertex(p3, norm, tc01);
        mesh.AddTriangle(v2, v5, v8);
        mesh.AddTriangle(v2, v8, v3);
    
        // Left
        norm = glm::vec3(-1.0f, 0.0f, 0.0f);
        v6 = mesh.AddVertex(p6, norm, tc00);
        v1 = mesh.AddVertex(p1, norm, tc10);
        v4 = mesh.AddVertex(p4, norm, tc11);
        v7 = mesh.AddVertex(p7, norm, tc01);
        mesh.AddTriangle(v6, v1, v4);
        mesh.AddTriangle(v6, v4, v7);
    
        // Top
        norm = glm::vec3(0.0f, 1.0f, 0.0f);
        v4 = mesh.AddVertex(p4, norm, tc00);
        v3 = mesh.AddVertex(p3, norm, tc10);
        v8 = mesh.AddVertex(p8, norm, tc11);
        v7 = mesh.AddVertex(p7, norm, tc01);
        mesh.AddTriangle(v4, v3, v8);
        mesh.AddTriangle(v4, v8, v7);
    
        // Bottom
        norm = glm::vec3(0.0f, -1.0f, 0.0f);
        v6 = mesh.AddVertex(p6, norm, tc00);
        v5 = mesh.AddVertex(p5, norm, tc10);
        v2 = mesh.AddVertex(p2, norm, tc11);
        v1 = mesh.AddVertex(p1, norm, tc01);
        mesh.AddTriangle(v6, v5, v2);
        mesh.AddTriangle(v6, v2, v1);
    
        mesh.Build();
    
        return mesh;
    }
    

    【讨论】: