C ++ OpenGL从文件渲染简单OBJ

时间:2015-03-17 21:15:34

标签: c++ opengl render

我目前正在学习一个基本的OpenGL教程,其目标是从.OBJ文件中读取数据,然后渲染模型。本教程位于此处 - http://www.opengl-tutorial.org/beginners-tutorials/tutorial-7-model-loading/

目前,我的程序打开指定的OBJ文件,并使用本教程中讨论的解析引擎解析它 - http://www.opengl-tutorial.org/beginners-tutorials/tutorial-7-model-loading/#Reading_the_file

我尝试渲染的对象是位于同一教程页面URL上的多维数据集。

我相信我的问题在于我的显示(无效)功能。在我的main()中执行glutDisplayFunc(display);后,我会看到一个黑色的窗口,而不是我渲染的模型。

这是我当前的显示(无效)功能:

void display(void)
{
    GLuint vbo;

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

    glBegin(GL_TRIANGLES);
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3) * 3, &vertices[0], GL_STATIC_DRAW);
    glDrawElements(GL_TRIANGLES, vertices.size() * sizeof(glm::vec3) * 3, GL_UNSIGNED_INT, &vertices[0]);

    // check OpenGL error
    GLenum err;
    while ((err = glGetError()) != GL_NO_ERROR)
    {
        printf("OpenGL error: %u", err);
    }

    glEnd();

    glutSwapBuffers();
}

这是我的解析器读入的数据,也许是解析问题:

Success: GLEW_OK Success: Opened OBJ File cube.obj Read in Vertices: 1.000000, -1.000000, -1.000000 Read in Vertices: 1.000000, -1.000000, 1.000000 Read in Vertices: -1.000000, -1.000000, 1.000000 Read in Vertices: -1.000000, -1.000000, -1.000000 Read in Vertices: 1.000000, 1.000000, -1.000000 Read in Vertices: 0.999999, 1.000000, 1.000001 Read in Vertices: -1.000000, 1.000000, 1.000000 Read in Vertices: -1.000000, 1.000000, -1.000000 Read in texture coordinate: 0.748573, 0.750412 Read in texture coordinate: 0.749279, 0.501284 Read in texture coordinate: 0.999110, 0.501077 Read in texture coordinate: 0.999455, 0.750380 Read in texture coordinate: 0.250471, 0.500702 Read in texture coordinate: 0.249682, 0.749677 Read in texture coordinate: 0.001085, 0.750380 Read in texture coordinate: 0.001517, 0.499994 Read in texture coordinate: 0.499422, 0.500239 Read in texture coordinate: 0.500149, 0.750166 Read in texture coordinate: 0.748355, 0.998230 Read in texture coordinate: 0.500193, 0.998728 Read in texture coordinate: 0.498993, 0.250415 Read in texture coordinate: 0.748953, 0.250920 Read in Normals: 0.000000, 0.000000, -1.000000 Read in Normals: -1.000000, -0.000000, -0.000000 Read in Normals: -0.000000, -0.000000, 1.000000 Read in Normals: -0.000001, 0.000000, 1.000000 Read in Normals: 1.000000, -0.000000, 0.000000 Read in Normals: 1.000000, 0.000000, 0.000001 Read in Normals: 0.000000, 1.000000, -0.000000 Read in Normals: -0.000000, -1.000000, 0.000000 Reached end of file Out Vertices Size: 234

glGetError()一次没有为我生成错误,所以我无法以这种方式调试问题。

有任何建议/意见吗?

1 个答案:

答案 0 :(得分:2)

这些命令(包括glGetError (...))都不在glBegin (...)glEnd (...)之间有效。如果您将调用移至glGetError以后glEnd,则应该GL_INVALID_OPERATION一次或多次。

删除glBeginglEnd,它们在此代码中没有用处,只会使其余的命令无效。

  

名称

     
    

glBegin - 分隔基元或一组类似基元的顶点

  
     

C规范

     
    

void glBegin(GLenum模式);

  
     

描述

     
    

[...]

         

glBegin和glEnd之间只能使用GL命令的子集。命令是glVertex,glColor,glSecondaryColor,glIndex,glNormal,glFogCoord,glTexCoord,glMultiTexCoord,glVertexAttrib,glEvalCoord,glEvalPoint,glArrayElement,glMaterial和glEdgeFlag。此外,可以使用glCallList或glCallLists来执行仅包含前面命令的显示列表。 如果在glBegin和glEnd之间执行任何其他GL命令,则会设置错误标志并忽略该命令。

  

关于代码的其余部分,您不应该每帧生成一个新的缓冲区。在初始化期间执行一次,添加顶点指针,并将绘制命令更改为glDrawArrays (...)

glDrawArrays (GL_TRIANGLES, 0, vertices.size());
只有拥有索引缓冲区时才会使用

glDrawElements (...)。除非我完全误解了数据的结构,否则vertices是您的顶点数据,并且不存储索引列表。


更新1:

在阅读了您的问题基于的教程后,加载.obj模型时需要进行以下更改:

GLuint buffers [3];
glGenBuffers(3, buffers);

// Position Buffer = 0
glBindBuffer(GL_ARRAY_BUFFER, buffers [0]);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW);
glVertexPointer (3, GL_FLOAT, 0, NULL);
// ^^^^^^^^^^^^ Sources data from VBO bound to `GL_ARRAY_BUFFER`, so a NULL pointer is OK
glEnableClientState (GL_VERTEX_ARRAY); // Use this array for drawing

// Tex Coords = 1
glBindBuffer (GL_ARRAY_BUFFER, buffers [1]);
glBufferData (GL_ARRAY_BUFFER, uvs.size () * sizeof (glm::vec2), &uvs [0], GL_STATIC_DRAW);
glTexCoordPointer   (2, GL_FLOAT, 0, NULL);
glEnableClientState (GL_TEXTURE_COORD_ARRAY);

// Normals = 2
glBindBuffer (GL_ARRAY_BUFFER, buffers [2]);
glBufferData (GL_ARRAY_BUFFER, normals.size () * sizeof (glm::vec3), &normals [0], GL_STATIC_DRAW);
glNormalPointer (GL_FLOAT, 0, NULL);
glEnableClientState (GL_NORMAL_ARRAY);

请注意,一旦学会使用着色器,就应该停止使用glVertexPointer (...)glEnableClientState (...)等功能。您需要使用glVertexAttribPointer (...)glEnableVertexAttribArray (...)代替。

我用这种方式编写代码,这样你就可以立即开始运行,但这并不是编写GL软件的现代方式。