OpenGL没有渲染我的立方体

时间:2018-02-18 15:37:25

标签: c++ opengl

我最近开始使用http://www.opengl-tutorial.org上的教程学习OpenGL。前几个教程很顺利,我在屏幕上显示了三角形。现在我转到了立方体教程,但我遇到了以下问题。我只对三角形程序做了两处大的改动来渲染我的立方体:

  • 我通过添加更多顶点将三角形更改为多维数据集
  • 我将所有初始化代码从我的main函数移动到其他不同的函数中。

问题在于,当我运行程序时,它编译得很好,并向我显示一个深蓝色屏幕(我为清除屏幕设置的颜色),但它不会渲染我的立方体。

我的完整代码在这里:

#include "common/shader/loadShader.h"
#include "common/logpp/log++.h"

#include <GL\glew.h>
#include <GL\glfw3.h>

#include <vector>

logpp::FileLog mainLog;

//Contains all functions for initializing OpenGL, GLEW and GLFW
namespace GLInit
{


    void SetGLFWWindowHints()
    {
        glfwWindowHint(GLFW_SAMPLES, 4);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); /*OpenGL 3.3*/
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
#ifdef __APPLE__
        glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    }

    void InitGLFW()
    {
        if (!glfwInit())
        {
            logpp::Console::error("Failed to initialize GLFW!");
            return;
        }


        SetGLFWWindowHints();
    }

    void InitGLEW()
    {
        glewExperimental = true; //Needed in core profile
        if (glewInit() != GLEW_OK)
        {
            logpp::Console::error("Failed to initialize GLEW!");
            return;
        }
    }

    GLuint CreateVAO()
    {
        GLuint VertexArrayID;
        glGenVertexArrays(1, &VertexArrayID);
        glBindVertexArray(VertexArrayID);

        return VertexArrayID;
    }

    GLFWwindow* CreateWin(int width, int height, char const* caption)
    {
        auto window = glfwCreateWindow(width, height, caption, nullptr, nullptr);
        if (window == nullptr)
        {
            std::string msg = "Failed to create window!";
            logpp::Console::error(msg);
            mainLog.write("[ERROR]: " + msg);
            glfwTerminate();
            return nullptr;
        }

        glfwMakeContextCurrent(window);

        return window;
    }

    GLFWwindow* Init(int width, int height, char const* caption)
    {

        InitGLFW();

        auto window = CreateWin(width, height, caption);

        InitGLEW();

        return window;
    }

}

using namespace GLInit;


int main()
{
    static const int VERTICES_IN_TRIANGLE = 3;


    PathConverter::setBase(R"(C:\Users\michi_000\Desktop\C++\OpenGL\A Colored Cube\x64\Debug\)");

    try
    {
        mainLog.open(PathConverter::convert("logs\\main.log"), false);

    }
    catch (logpp::FileLog::Exception e)
    {
        logpp::Console::error(e.what());
    }

    auto window = Init(800, 600, "A Colored Cube");
    auto VertexArrayID = CreateVAO();

    glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);

    static const std::vector<GLfloat> cube //Vertices for the cube
    {
        -1.0f,-1.0f,-1.0f, // triangle 1 : begin
        -1.0f,-1.0f, 1.0f,
        -1.0f, 1.0f, 1.0f, // triangle 1 : end
        1.0f, 1.0f,-1.0f, // triangle 2 : begin
        -1.0f,-1.0f,-1.0f,
        -1.0f, 1.0f,-1.0f, // triangle 2 : end
        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,-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,-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,
        -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, 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, 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,
        -1.0f, 1.0f, 1.0f,
        1.0f, 1.0f, 1.0f,
        -1.0f, 1.0f, 1.0f,
        1.0f,-1.0f, 1.0f
    }; 

    static const std::vector<GLfloat> cube_colors
    {
        0.583f,  0.771f,  0.014f,
        0.609f,  0.115f,  0.436f,
        0.327f,  0.483f,  0.844f,
        0.822f,  0.569f,  0.201f,
        0.435f,  0.602f,  0.223f,
        0.310f,  0.747f,  0.185f,
        0.597f,  0.770f,  0.761f,
        0.559f,  0.436f,  0.730f,
        0.359f,  0.583f,  0.152f,
        0.483f,  0.596f,  0.789f,
        0.559f,  0.861f,  0.639f,
        0.195f,  0.548f,  0.859f,
        0.014f,  0.184f,  0.576f,
        0.771f,  0.328f,  0.970f,
        0.406f,  0.615f,  0.116f,
        0.676f,  0.977f,  0.133f,
        0.971f,  0.572f,  0.833f,
        0.140f,  0.616f,  0.489f,
        0.997f,  0.513f,  0.064f,
        0.945f,  0.719f,  0.592f,
        0.543f,  0.021f,  0.978f,
        0.279f,  0.317f,  0.505f,
        0.167f,  0.620f,  0.077f,
        0.347f,  0.857f,  0.137f,
        0.055f,  0.953f,  0.042f,
        0.714f,  0.505f,  0.345f,
        0.783f,  0.290f,  0.734f,
        0.722f,  0.645f,  0.174f,
        0.302f,  0.455f,  0.848f,
        0.225f,  0.587f,  0.040f,
        0.517f,  0.713f,  0.338f,
        0.053f,  0.959f,  0.120f,
        0.393f,  0.621f,  0.362f,
        0.673f,  0.211f,  0.457f,
        0.820f,  0.883f,  0.371f,
        0.982f,  0.099f,  0.879f
    };

/*  static const std::vector<GLfloat> cube
    {
        1.0, -1.0, 0.0,
        -1.0, -1.0, 0.0,
        0.0, 1.0, 0.0
    };*/

    static const std::vector<GLfloat>::size_type triangleCount = cube.size() / VERTICES_IN_TRIANGLE;

    GLuint programID = LoadShaders(PathConverter::convert("shaders\\vertex.glsl").c_str(),
        PathConverter::convert("shaders\\fragment.glsl").c_str());

    GLuint vertexBuffer;
    glGenBuffers(1, &vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, cube.size(), &cube, GL_STATIC_DRAW);

    GLuint colorbuffer;
    glGenBuffers(1, &colorbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
    glBufferData(GL_ARRAY_BUFFER, cube_colors.size(), &cube_colors, GL_STATIC_DRAW);

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

    do 
    {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glUseProgram(programID);

        glEnableVertexAttribArray(0); //enable vertices
        glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
        glVertexAttribPointer(0, triangleCount, GL_FLOAT, GL_FALSE, 0, nullptr);

        glDisableVertexAttribArray(0);

        // 2nd attribute buffer : colors
        glEnableVertexAttribArray(1);
        glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
        glVertexAttribPointer(
            1,                                // attribute. No particular reason for 1, but must match the layout in the shader.
            3,                                // size
            GL_FLOAT,                         // type
            GL_FALSE,                         // normalized?
            0,                                // stride
            nullptr                          // array buffer offset
        );

        glDisableVertexAttribArray(1);

        logpp::Console::debug("Drawing triangles");
        glDrawArrays(GL_TRIANGLES, 0, triangleCount);
//      glDisableVertexAttribArray(0);

        glfwSwapBuffers(window);
        glfwPollEvents();
    } while (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS
            && !glfwWindowShouldClose(window));

    glfwTerminate();

    return 0;
}

最后一点,如果我删除了颜色属性并将整个立方体设置为红色,它仍会提供相同的深蓝色屏幕。

2 个答案:

答案 0 :(得分:4)

代码中有几个问题:

您在绘制前禁用所有顶点属性。对glDisableVertexAttribArray的调用必须在glDrawArrays之后,否则在绘制时不会附加任何数据。

更好的解决方案是在主循环之前移动VAO设置,从不调用glDisableVertexAttribArray。无论如何,指针永远不会改变,存储顶点属性设置正是VAO的制作方式。似乎教程在解释/使用它们时非常不理想。

另一个问题是这一行:

glVertexAttribPointer(0, triangleCount, GL_FLOAT, GL_FALSE, 0, nullptr);

应生成GL_INVALID_VALUE错误,因为大小(第二个参数)只允许为1,2,3或4.在您的情况下,triangleCount等于12.大小描述了每个元素的数量< / strong>的顶点应该消耗。因此,如果属性是vec3类型,那么它应该是3。

在询问SO之前,您应该始终检查glGetError是否返回任何错误。这节省了大量时间,因为您已经知道哪条线存在问题。

另请注意,triangleCount实际上并不包含三角形数,而是包含顶点数。

答案 1 :(得分:3)

第一个问题是glBufferData的第二个参数是缓冲区的大小(以字节为单位)。进一步operator &不返回指向std::vector数据的指针。您必须使用std::vector::data()

GLuint vertexBuffer;
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER,
   cube.size()*sizeof(GLfloat),
   cube.data(),
   GL_STATIC_DRAW);  

GLuint colorbuffer;
glGenBuffers(1, &colorbuffer);
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
glBufferData(GL_ARRAY_BUFFER,
    cube_colors.size()*sizeof(GLfloat),
    cube_colors.data(),
    GL_STATIC_DRAW);

进一步glDisableVertexAttribArray,禁用通用顶点属性数组。这必须在绘图后完成。 size参数 glVertexAttribPointer指定每个通用顶点属性的组件数,并且必须为1,2,3,4:

glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);  

glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, nullptr);

glDrawArrays(GL_TRIANGLES, 0, triangleCount);

glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);