Python OpenGL - 在 3d 场景上显示 2d 图形时出现问题

Python OpenGL - Issues displaying 2d graphics over a 3d scene

我的目标是使用 PyOpenGL 在旋转的立方体上显示静态三角形。但是,我没有运气达到我想要的结果;相反,我只剩下一个空白屏幕。我已经在单独的文件上用相应的矩阵投影测试了立方体和三角形,以确保场景本身不是问题。果然,事实并非如此。

三角脚本

在屏幕左下角显示一个三角形。

def reshape(width, height):

    glViewport(0, 0, width, height)
    glClearColor(0.0, 0.0, 0.0, 0.0)
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    glOrtho(0, width, 0, height, 0, 0.1)
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()

#--- func for defining triangle
def drawTriangle():

    ### clear color and depth buffer
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glLoadIdentity()

    ### draw triangle
    glBegin(GL_TRIANGLES)

    glColor3f(0.0, 1.0, 0.0)
    glVertex2f(0, 0)
    glVertex2f(100, 0)
    glVertex2f(0, 100)

    glEnd()
    glutSwapBuffers()

#--- func for main loop
def main():

    window = 0

    glutInit(sys.argv)
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE)
    glutInitWindowSize(640, 480)
    glutInitWindowPosition(200, 200)

    window = glutCreateWindow(b'OpenGL Python Triangle')

    glutReshapeFunc(reshape)
    glutDisplayFunc(drawTriangle)
    glutIdleFunc(drawTriangle)
    glutMainLoop()

if __name__ == '__main__':
    main()

立方体脚本

在屏幕中央显示一个立方体。

def reshape(width, height): 

        glClearColor(0.0, 0.0, 0.0, 0.0)
        glClearDepth(1.0) 
        glDepthMask(GL_TRUE)
        glDepthFunc(GL_LESS)
        glEnable(GL_DEPTH_TEST)
        glShadeModel(GL_SMOOTH)   
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluPerspective(45.0, float(width)/float(height), 0.1, 100.0)
        glMatrixMode(GL_MODELVIEW)

#--- func for defining cube
def drawCube():

        ### clear color and depth buffer
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        ### set position and rotation
        glLoadIdentity()
        glTranslatef(0.0,0.0,-6.0)
        glRotatef(30,1.0,0.0,0.0)
        glRotatef(0,0.0,1.0,0.0)
        glRotatef(30,0.0,0.0,1.0)

        ### draw cube
        glBegin(GL_QUADS)

        #/* Long list of vertices

        glEnd()
        glutSwapBuffers()

#--- func for main loop
def main():

        window = 0

        glutInit(sys.argv)
        glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH)
        glutInitWindowSize(640,480)
        glutInitWindowPosition(200,200)

        window = glutCreateWindow(b'OpenGL Python Cube')

        glutReshapeFunc(reshape)
        glutDisplayFunc(drawCube)
        glutIdleFunc(drawCube)
        glutMainLoop()

if __name__ == "__main__":
        main()

我认为深度测试可能会出现问题,但我未能提供任何证明该想法正确的结果。相反,它可能与组织矩阵投影有关。我订购它是为了先渲染 3d 场景,然后再渲染 2d 场景。

HUD 脚本

#--- 3D projection function
def render3d():

        global width, height

        ### clear buffers
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        glViewport(0, 0, width, height)

        ### projection mode
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluPerspective(45.0, float(width)/float(height), 0.1, 100.0)

        ### modelview mode
        glMatrixMode(GL_MODELVIEW)

        ### setup 3d shader
        glDepthFunc(GL_LESS)
        glEnable(GL_DEPTH_TEST)
        glShadeModel(GL_SMOOTH)

#--- 2D projection function
def render2d():

        global width, height

        ### projection mode
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluOrtho2D(0.0, width, height, 0.0)

        ### modelview mode
        glMatrixMode(GL_MODELVIEW)

        ### setup 2d shader
        glDisable(GL_DEPTH_TEST)

#--- reshape function
def reshape(new_width, new_height):

        global width, height

        ### apply new window size
        width = new_width
        height = new_height

#--- 3D cube function
def scene3d():

        ### setup polygon location & orientation
        glTranslatef(0.0, 0.0, -6.0)
        glRotatef(30, 1.0, 0.0, 0.0)
        glRotatef(0, 1.0, 1.0, 0.0)
        glRotatef(30, 0.0, 0.0, 1.0)

        ### draw cube
        glBegin(GL_QUADS)

        glColor3f(0.0,1.0,0.0)
        glVertex3f( 1.0, 1.0,-1.0)
        glVertex3f(-1.0, 1.0,-1.0)
        glVertex3f(-1.0, 1.0, 1.0)
        glVertex3f( 1.0, 1.0, 1.0) 

        glColor3f(1.0,0.0,0.0)
        glVertex3f( 1.0,-1.0, 1.0)
        glVertex3f(-1.0,-1.0, 1.0)
        glVertex3f(-1.0,-1.0,-1.0)
        glVertex3f( 1.0,-1.0,-1.0) 

        glColor3f(0.0,1.0,1.0)
        glVertex3f( 1.0, 1.0, 1.0)
        glVertex3f(-1.0, 1.0, 1.0)
        glVertex3f(-1.0,-1.0, 1.0)
        glVertex3f( 1.0,-1.0, 1.0)

        glColor3f(1.0,1.0,0.0)
        glVertex3f( 1.0,-1.0,-1.0)
        glVertex3f(-1.0,-1.0,-1.0)
        glVertex3f(-1.0, 1.0,-1.0)
        glVertex3f( 1.0, 1.0,-1.0)

        glColor3f(0.0,0.0,1.0)
        glVertex3f(-1.0, 1.0, 1.0) 
        glVertex3f(-1.0, 1.0,-1.0)
        glVertex3f(-1.0,-1.0,-1.0) 
        glVertex3f(-1.0,-1.0, 1.0) 

        glColor3f(1.0,0.0,1.0)
        glVertex3f( 1.0, 1.0,-1.0) 
        glVertex3f( 1.0, 1.0, 1.0)
        glVertex3f( 1.0,-1.0, 1.0)
        glVertex3f( 1.0,-1.0,-1.0)

        glEnd()

#--- 2D triangle function
def scene2d():

        ### draw triangle
        glBegin(GL_TRIANGLES)

        glColor3f(0.0, 1.0, 0.0)
        glVertex2f(0, 0)
        glVertex2f(100, 0)
        glVertex2f(0, 100)

        glEnd()

#--- draw function
def draw():

        ### 3D scene
        render3d()
        scene3d()

        ### 2D scene
        glPushMatrix()

        render2d()
        scene2d()

        glPopMatrix()

        ### swap buffers
        glutSwapBuffers()

#--- main loop function
def main():

        window = 0

        glutInit(sys.argv)
        glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH)
        glutInitWindowSize(640,480)
        glutInitWindowPosition(200,200)

        window = glutCreateWindow(b'OpenGL Python HUD')

        glutReshapeFunc(reshape)
        glutDisplayFunc(draw)
        glutIdleFunc(draw)
        glutMainLoop()

#--- only run if this is the main module
if __name__ == "__main__":
        main()

为了解释,我定义了两个矩阵投影函数:一个用于3d场景(render3d),另一个用于2d场景(render2d)。下一个函数 (reshape) 是获取当前的 window 大小,以便我可以将其输入到矩阵投影的比例中。以下函数 (scene3d) 创建立方体并将其设置在场景的中心,而 (scene2d) 创建三角形并将其设置在场景的左下角。 (draw) 函数按顺序排列所有内容,首先渲染 3d 场景,然后渲染 2d 场景 [我将其嵌套在 push 和 pop 矩阵下]。最后,主函数创建 window 并开始循环。

非常感谢您提供反馈。谢谢你,祝你有愉快的一天!

draw() 里面考虑一下:

def draw():
    render3d()
    scene3d()

    glPushMatrix()
    render2d()
    scene2d()
    glPopMatrix()

注意到有什么遗漏了吗?

另一部分也应该有一个glPushMatrix()glPopMatrix():

def draw():
    glPushMatrix()
    render3d()
    scene3d()
    glPopMatrix()

    glPushMatrix()
    render2d()
    scene2d()
    glPopMatrix()

您看到黑屏的原因是因为您在 scene3d() 内呼叫 glTranslatef()。因此,启动应用程序后几毫秒内的所有内容都会在屏幕外翻译。

添加缺失的 glPushMatrix()glPopMatrix(),您应该会看到: