在opengl中渲染obj文件时的黑色窗口

时间:2018-10-16 06:16:38

标签: c++ qt opengl wavefront

我在ubuntu 18.4的qt5中使用了opengl,我想加载一个简单的多维数据集(存储在.obj文件中)并进行渲染。我在这里http://www.opengl-tutorial.org/beginners-tutorials/tutorial-7-model-loading/遵循了该教程,但是最后我得到了一个黑色的窗口。这是我的代码,非常感谢:

myopengl.hpp

class MyOpenGL : public QOpenGLWidget, protected QOpenGLFunctions
{
public:
MyOpenGL(const QString& obj_file);

protected:
    virtual void initializeGL() Q_DECL_OVERRIDE;
    virtual void paintGL() Q_DECL_OVERRIDE;
    virtual void resizeGL(int width, int height) Q_DECL_OVERRIDE;
    void CheckGLerror();

private:
    std::vector< glm::vec3 > vertices;
    std::vector< glm::vec2 > uvs;
    std::vector< glm::vec3 > normals;

/*  Render data  */
    GLuint VAO, VBO, EBO;
};

myopengl.cpp

MyOpenGL ::MyOpenGL (const QString& obj_file) :
VAO(0),
VBO(0),
EBO(0)
{
    std::vector< unsigned int > vertex_indices, uv_indices, normal_indices;
    std::vector< glm::vec3 > temp_vertices;
    std::vector< glm::vec2 > temp_uvs;
    std::vector< glm::vec3 > temp_normals;

//parse obj file
QFile file(obj_file);
file.open(QFile::ReadOnly | QFile::Text);
QTextStream in(&file);
while(!in.atEnd()) {
    QString line = in.readLine();
    QStringList list = line.replace(",","").split(' ', QString::SkipEmptyParts);
    if (list.size() >= 3) {
        if (list.at(0) == "v") {  //veertex
            bool ok1, ok2, ok3;
            float v1 = list.at(1).toFloat(&ok1);
            float v2 = list.at(2).toFloat(&ok2);
            float v3 = list.at(3).toFloat(&ok3);
            if (ok1 && ok2 && ok3) {
                glm::vec3 vertex;
                vertex.x = v1;
                vertex.y = v2;
                vertex.z = v3;
                temp_vertices.push_back(vertex);
            }
        } else if (list.at(0) == "vn") {
            bool ok1, ok2, ok3;
            float v1 = list.at(1).toFloat(&ok1);
            float v2 = list.at(2).toFloat(&ok2);
            float v3 = list.at(3).toFloat(&ok3);
            if (ok1 && ok2 && ok3) {
                glm::vec3 normal;
                normal.x = v1;
                normal.y = v2;
                normal.z = v3;
                temp_normals.push_back(normal);
            }
        } else if (list.at(0) == "vt") {
            bool ok1, ok2;
            float v1 = list.at(1).toFloat(&ok1);
            float v2 = list.at(2).toFloat(&ok2);
            if (ok1 && ok2) {
                glm::vec2 uv;
                uv.x = v1;
                uv.y = v2;
                temp_uvs.push_back(uv);
            }
        } else if (list.at(0) == "f") {
            bool f_ok1, f_ok2, f_ok3;
            bool t_ok1, t_ok2, t_ok3;
            bool n_ok1, n_ok2, n_ok3;
            unsigned int v_index1, v_index2, v_index3;
            unsigned int t_index1, t_index2, t_index3;
            unsigned int n_index1, n_index2, n_index3;
            QStringList f_list = list.at(1).split('/');
            if (f_list.size() >= 3) {
                v_index1 = f_list.at(0).toUInt(&f_ok1);
                if (f_ok1) {
                    v_index1 -= 1;
                }
                t_index1 = f_list.at(1).toUInt(&t_ok1);
                if (t_ok1) {
                    t_index1 -= 1;
                }
                n_index1 = f_list.at(2).toUInt(&n_ok1);
                if (n_ok1) {
                    n_index1 -= 1;
                }
            }
            f_list = list.at(2).split('/');
            if (f_list.size() >= 3) {
                v_index2 = f_list.at(0).toUInt(&f_ok2);
                if (f_ok2) {
                    v_index2 -= 1;
                }
                t_index2 = f_list.at(1).toUInt(&t_ok2);
                if (t_ok2) {
                    t_index2 -= 1;
                }
                n_index2 = f_list.at(2).toUInt(&n_ok2);
                if (n_ok2) {
                    n_index2 -= 1;
                }
            }
            f_list = list.at(3).split('/');
            if (f_list.size() >= 3) {
                v_index3 = f_list.at(0).toUInt(&f_ok3);
                if (f_ok3) {
                    v_index3 -= 1;
                }
                t_index3 = f_list.at(1).toUInt(&t_ok3);
                if (t_ok3) {
                    t_index3 -= 1;
                }
                n_index3 = f_list.at(2).toUInt(&n_ok3);
                if (n_ok3) {
                    n_index3 -= 1;
                }
            }
            if (f_ok1 && f_ok2 && f_ok3 && n_ok1 && n_ok2 && n_ok3
                    && t_ok1 && t_ok2 && t_ok3) {
                vertex_indices.push_back(v_index1);
                vertex_indices.push_back(v_index2);
                vertex_indices.push_back(v_index3);

                uv_indices.push_back(t_index1);
                uv_indices.push_back(t_index2);
                uv_indices.push_back(t_index3);

                normal_indices.push_back(n_index1);
                normal_indices.push_back(n_index2);
                normal_indices.push_back(n_index3);
            }
        }

    }
}
file.close();

for (unsigned int i = 0; i < vertex_indices.size(); ++i) {
    glm::vec3 vertex = temp_vertices.at(vertex_indices.at(i));
    vertices.push_back(vertex);
}
for (unsigned int i = 0; i < uv_indices.size(); ++i) {
    glm::vec2 uv = temp_uvs.at(uv_indices.at(i));
    uvs.push_back(uv);
}
for (unsigned int i = 0; i < normal_indices.size(); ++i) {
    glm::vec3 normal = temp_normals.at(normal_indices.at(i));
    normals.push_back(normal);
}
}

void MyOpenGL::initializeGL()
{
    initializeOpenGLFunctions();
    glClearColor(0.0,0.0,0.0,1);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);
    glDisable(GL_CULL_FACE);
    glEnable(GL_LIGHT0);

    glewExperimental = GL_TRUE;
    GLenum status = glewInit();
    if (status != GLEW_OK)
    {
        glfwTerminate();
        std::system("pause");
        return;
    }
    glGenVertexArrays(1, &this->VAO);
    glBindVertexArray(this->VAO);
    glGenBuffers(1, &this->VBO);
    glBindBuffer(GL_ARRAY_BUFFER, this->VBO);
    glBufferData(GL_ARRAY_BUFFER, this->vertices.size() * sizeof(glm::vec3), &this->vertices[0], GL_STATIC_DRAW);
    glBindVertexArray(0);
}

void MyOpenGL::resizeGL(int width, int height)
{
    glViewport(0,0,width,height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-width/2,width/2,-height/2,height/2,-1,1);
    glMatrixMode(GL_MODELVIEW);
}

void MyOpenGL::paintGL()
{
    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, this->VBO);
    glDrawArrays(GL_TRIANGLES, 0, vertices.size());
    glDisableVertexAttribArray(0);

}

1 个答案:

答案 0 :(得分:0)

您必须通过glVertexAttribPointer定义一组通用顶点属性数据。

请注意,vertex buffer object只是顶点数据的数据存储。但是您必须指定如何“使用”它们。顶点属性的规范和状态存储在vertex array object中。要绘制网格时,绑定顶点数组对象就足够了:

规范

glBindVertexArray(this->VAO);
glBindBuffer(GL_ARRAY_BUFFER, this->VBO);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);

绘制

glBindVertexArray(this->VAO);
glDrawArrays(GL_TRIANGLES, 0, vertices.size());
glBindVertexArray(0);

扩展名:

  

使用顶点着色器和片段着色器是否必要?我没有用它们作为电流。

如果没有着色器,则必须分别使用Fixed Function PipelineglVertexPointer使用glEnableClientState( GL_VERTEX_ARRAY )并定义固定的函数属性。
但是,由于仅使用一个属性,即属性索引为0的顶点坐标,因此仍可以通过glVertexAttribPointerglEnableVertexAttribArray定义属性。
参见What are the Attribute locations for fixed function pipeline in OpenGL 4.0++ core profile?

请注意,在这种情况下,您必须使用compatibility OpenGL Context