为啥我的 OpenGL 对象绘制相对于最后绘制的对象?

Posted

技术标签:

【中文标题】为啥我的 OpenGL 对象绘制相对于最后绘制的对象?【英文标题】:Why are my OpenGL objects drawing relative to the last object drawn?为什么我的 OpenGL 对象绘制相对于最后绘制的对象? 【发布时间】:2015-01-18 01:35:38 【问题描述】:

我很确定这是由于我对 GL_MODELVIEW 矩阵的工作原理缺乏了解。这是正在发生的事情的屏幕记录:http://youtu.be/3F7FLkVI7kA

如您所见,最底部的三角形是第一个绘制的三角形,并且按照我预期的方式移动其他 2 个三角形。第二个三角形相对于第一个三角形移动和旋转,第三个三角形相对于该组合​​移动和旋转。

我想要的是所有三个三角形在 3D 空间中都是静止的,但在旋转(就像第一个三角形一样)。

来源:

// Main loop
do 
    // Clear Screen
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Update camera
    glfwGetCursorPos(window, &cursorX, &cursorY);
    cam.update(0.001f, (int)cursorX, (int)cursorY);

    // Reset Matrix
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    // move camera
    glRotatef(cam.rotation.x, 1.0f, 0.0f, 0.0f);
    glRotatef(cam.rotation.y, 0.0f, 1.0f, 0.0f);

    // translate modelview matrix to position of the camera - everything should now draw relative to camera position
    glTranslatef(-cam.position.x, cam.position.y, -cam.position.z);

    // Draw ground
    drawGroundGrid(-25.0f);
    drawSpinningTriangle(0.0f, 0.0f, -5.0f);
    drawSpinningTriangle(3.14f, 3.0f, -6.0f);
    drawSpinningTriangle(-6.0f, 12.0f, -5.0f);

    // Swap buffers - back buffer is now front buffer to be rendered to next frame
    glfwSwapBuffers(window);
    glfwPollEvents();
    calcFPS();

 while (!glfwGetKey(window, GLFW_KEY_ESCAPE) && !glfwWindowShouldClose(window));// Main Loop End

[...]

void drawSpinningTriangle(float x, float y, float z) 
    glMatrixMode(GL_MODELVIEW);
    glTranslatef(x, y, z);
    glRotatef(glfwGetTime() * 50.0f, 0.0f, 1.0f, 0.0f);
    glBegin(GL_TRIANGLES);
    
        // Red vertex
        glColor3f(1.0f, 0.0f, 0.0f);
        glVertex3f(0.0f, 1.0f, 0.0f);

        // Yellow vertex
        glColor3f(1.0f, 1.0f, 0.0f);
        glVertex3f(-1.0f, -1.0f, 0.0f);

        // White vertex
        glColor3f(1.0f, 1.0f, 1.0f);
        glVertex3f(1.0f, -1.0f, 0.0f);
    
    glEnd();

【问题讨论】:

确保您的深度缓冲区已设置并启用。 已经完成了,但那不会只影响 z 剔除吗? 【参考方案1】:

首先使用矩阵堆栈已被弃用。管理自己的矩阵要好得多

其次,你应该在转换之前和绘制之后 pushMatrix 和 popMatrix:

void drawSpinningTriangle(float x, float y, float z) 
    glMatrixMode(GL_MODELVIEW);

    glPushMatrix();

    glTranslatef(x, y, z);
    glRotatef(glfwGetTime() * 50.0f, 0.0f, 1.0f, 0.0f);
    glBegin(GL_TRIANGLES);
    
        // Red vertex
        glColor3f(1.0f, 0.0f, 0.0f);
        glVertex3f(0.0f, 1.0f, 0.0f);

        // Yellow vertex
        glColor3f(1.0f, 1.0f, 0.0f);
        glVertex3f(-1.0f, -1.0f, 0.0f);

        // White vertex
        glColor3f(1.0f, 1.0f, 1.0f);
        glVertex3f(1.0f, -1.0f, 0.0f);
    
    glEnd();

    glPopMatrix();


这将保存和恢复最顶部的矩阵,因此两次调用之间的任何更改都将被删除。

【讨论】:

管理自己的矩阵是什么意思?那是推送和弹出矩阵吗? @AlexMohr:不。推送和弹出矩阵使用旧的、已弃用的 OpenGL 固定函数矩阵堆栈。没有一个严肃的程序曾经使用过这个功能;使用起来很麻烦,并且提供零收益。所以它从现代 OpenGL 中被删除了——很好摆脱。无论如何,你应该得到一个真正的矩阵数学库(最好是一个用于图形的库,如 GLM 或 linmath.h)并管理你自己的一组转换矩阵。您仍然可以进行分层转换,但要灵活得多。

以上是关于为啥我的 OpenGL 对象绘制相对于最后绘制的对象?的主要内容,如果未能解决你的问题,请参考以下文章

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

为啥我的 OpenGL 不绘制任何东西?

为啥我的三角形对象没有被绘制?

为啥我的点没有在我的鼠标在 OpenGL 中的位置绘制?

QOpenGLWidget 绘制对象

OpenGL基础篇——使用面向对象方法封装OpenGL函数