OpenGL 绘制网格不正确

Posted

技术标签:

【中文标题】OpenGL 绘制网格不正确【英文标题】:OpenGL drawing meshes incorrectly 【发布时间】:2014-04-05 15:46:15 【问题描述】:

我正在尝试用 C++ 制作 OpenGL 引擎,但无法正确渲染网格。网格在渲染时创建的面连接网格上的两个随机点,或者网格上的一个随机点与 0,0,0。

问题可以看这里:

(我做了一个线框图,以便更清楚地看到问题)

代码:

// Render all meshes (Graphics.cpp)
for( int curMesh = 0; curMesh < numMesh; curMesh++ ) 
    // Save pointer of buffer
    meshes[curMesh]->updatebuf();
    Buffer buffer = meshes[curMesh]->buffer;

    // Update model matrix
    glm::mat4 mvp = Proj*View*(meshes[curMesh]->model);

    // Initialize vertex array
    glBindBuffer( GL_ARRAY_BUFFER, vertbuffer );
    glBufferData( GL_ARRAY_BUFFER, sizeof(GLfloat)*buffer.numcoords*3, meshes[curMesh]->verts, GL_STATIC_DRAW );

    // Pass information to shader
    GLuint posID = glGetAttribLocation( shader, "s_vPosition" );
    glVertexAttribPointer( posID, 3, GL_FLOAT, GL_FALSE, 0, (void*)0 );
    glEnableVertexAttribArray( posID );
    
    // Check if texture applicable
    if( meshes[curMesh]->texID != NULL && meshes[curMesh]->uvs != NULL ) 
        // Initialize uv array
        glBindBuffer( GL_ARRAY_BUFFER, uvbuffer );
        glBufferData( GL_ARRAY_BUFFER, sizeof(GLfloat)*buffer.numcoords*2, meshes[curMesh]->uvs, GL_STATIC_DRAW );

        // Pass information to shader
        GLuint uvID = glGetAttribLocation( shader, "s_vUV" );
        glVertexAttribPointer( uvID, 2, GL_FLOAT, GL_FALSE, 0, (void*)(0) );        
        glEnableVertexAttribArray( uvID );
        
        // Set mesh texture
        glActiveTexture( GL_TEXTURE0 );
        glBindTexture( GL_TEXTURE_2D, meshes[curMesh]->texID );
        GLuint texID = glGetUniformLocation( shader, "Sampler" );
        glUniform1i( texID, 0 );
    

    // Actiavte shader
    glUseProgram( shader );
        
    // Set MVP matrix
    GLuint mvpID = glGetUniformLocation( shader, "MVP" );
    glUniformMatrix4fv( mvpID, 1, GL_FALSE, &mvp[0][0] );

    // Draw verticies on screen
    bool wireframe = true;
    if( wireframe )
        for(int i = 0; i < buffer.numcoords; i += 3)
            glDrawArrays(GL_LINE_LOOP, i, 3);
    else
        glDrawArrays( GL_TRIANGLES, 0, buffer.numcoords );

// Mesh Class (Graphics.h)
class mesh 
public:
    mesh();
    void updatebuf();
    Buffer buffer;
    GLuint texID;
    bool updated;

    GLfloat* verts;
    GLfloat* uvs;

    glm::mat4 model;
;

我的 Obj 加载代码在这里:https://www.dropbox.com/s/tdcpg4vok11lf9d/ObjReader.txt(它很粗糙,没有组织,但应该仍然可以工作)

【问题讨论】:

你能发布你的示例文件吗?你在加载器中做了一堆假设,这些假设可能会或可能不会被数据尊重,但如果没有数据就很难判断。 @DirkR 也许这可能是问题所在,这是我正在使用的 teapot.obj 文件:dropbox.com/s/z8fy46x3zeadg0s/teapot.obj.txt 嗯,好的,这应该是可行的。所以我的建议是放弃你自己的加载器,改用 assimp (assimp.sourceforge.net),它支持更多的格式并且被广泛使用。 编写自己的有效加载程序并非不可能。我会仔细检查数据,看看缓冲区内容是否符合您的预期。这很乏味,但你肯定会以这种方式找到根本原因。经常犯的一个常见错误是没有将索引移动 1(OpenGL 从 0 开始计数,OBJ 从 1 开始计数)。我会尝试从目标文件中手动删除一些面,只留下有问题的顶点,然后首先确认 VBO 实际上具有正确的数据。 【参考方案1】:

对我来说,这看起来像是一个原始的重启问题。如果没有看到一些代码,很难说出究竟是什么问题。看看上面和下面的大约 20 行,包括绘制调用渲染茶壶,这将有很大帮助。 IE。对应的 glDrawArrays、glDrawElements 或 glBegin 调用之前的 20 行和之后的 20 行。

【讨论】:

我认为这与重新启动三角形有关,但 OBJ 文件中没有任何内容表示顶点断点,所以我怎么知道新三角形列表何时开始? (顺便说一句,我发布了代码)【参考方案2】:

这是因为您的三角形没有连接到线框看起来很完美。 如果三角形未连接,则应构建索引缓冲区。

【讨论】:

以上是关于OpenGL 绘制网格不正确的主要内容,如果未能解决你的问题,请参考以下文章

绘制多边形网格时的 Opengl 性能问题

为啥绘制我的 OpenGL-ES VBO 网格会阻止其他三角形显示?

OpenGL索引缓冲区对象元素顺序绘制不正确

渲染在 OpenGL 中使用 Assimp 加载的动画模型时折叠的网格

opengl多层次细节LOD四叉树网格无限动态绘制

多个网格、多个 VBO、多个 VAO、OpenGL 4.1