PyOpengl:更改 gluPerspective 变量使立方体闪烁

PyOpengl: Changing gluPerspective variables makes cube flash

在 glutReshapeFunc 函数中使用 gluPerspective 时,方形图像在调整大小时闪烁并在片刻后消失。

from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *

width = 500
height = 500


def cube():
    glBegin(GL_QUADS)
    glColor3f(0, 1, 0)
    glVertex3f(10, 0, 0)
    glVertex3f(10, 10, 0)
    glVertex3f(10, 0, 0)
    glVertex3f(0, 0, 0)
    glVertex3f(10, 0, 0)
    glVertex3f(10, 0, 10)
    glVertex3f(0, 10, 0)
    glVertex3f(10, 10, 0)
    glVertex3f(0, 10, 0)
    glVertex3f(0, 0, 0)
    glVertex3f(0, 10, 0)
    glVertex3f(0, 10, 10)
    glVertex3f(0, 0, 10)
    glVertex3f(0, 0, 0)
    glVertex3f(0, 0, 10)
    glVertex3f(10, 0, 10)
    glVertex3f(0, 0, 10)
    glVertex3f(0, 10, 10)
    glVertex3f(10, 10, 10)
    glVertex3f(10, 10, 0)
    glVertex3f(10, 10, 10)
    glVertex3f(10, 0, 10)
    glVertex3f(10, 10, 10)
    glVertex3f(0, 10, 10)
    glEnd()


def showScreen():
    global width, height

    glClearColor(0, 0, 0, 1)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    cube()
    glutSwapBuffers()


def mouseTracker(mousex, mousey):
    print(f"Mouse pos: {mousex}, {mousey}")


def reshapeWindow(x, y):
    global width, height
    width = x
    height = y
    print(x, y)
    gluPerspective(45, (width / height), 0.0001, 1000)



glutInit()
glutInitDisplayMode(GLUT_RGBA)
glutInitWindowSize(500, 500)
wind = glutCreateWindow("OpenGL")
glutDisplayFunc(showScreen)
glutIdleFunc(showScreen)
glutMotionFunc(mouseTracker)
glutPassiveMotionFunc(mouseTracker)
glutReshapeFunc(reshapeWindow)
gluPerspective(45, (width / height), 0.0001, 1000)
glTranslatef(0, 0, -5)

while True:
    glutMainLoopEvent()
    glutPostRedisplay()

如果我像这样将 gluPerspective 放入 showScreen 函数中:

def showScreen():
    global width, height

    glClearColor(0, 0, 0, 1)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    cube()
    gluPerspective(45, (width / height), 0.0001, 1000)
    glutSwapBuffers()

方块在没有调整大小的情况下闪烁,但片刻后消失了。如果我完全移除 gluPerspective,图像就会变成三角形。有什么方法可以在不使图像闪烁的情况下更改 gluPerspective 变量?

您必须在绘制立方体之前调用 gluPerspective。矩阵运算不仅设置当前矩阵,而且定义一个新矩阵并将当前矩阵乘以新矩阵。因此,您必须加载 Identity matrix with glLoadIdentity before modifying the matrix. The legacy OpenGL provides different current matrices for the model view matrix and the projection matrix. Before changing a matrix, select the matrix mode with glMatrixMode:

reshape回调中更改投影矩阵:

def reshapeWindow(x, y):
    global width, height
    width = x
    height = y
    print(x, y)
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluPerspective(45, (width / height), 0.0001, 1000)
    glMatrixMode(GL_MODELVIEW)

在应用程序循环之前或在应用程序循环中设置模型视图矩阵:

glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glTranslatef(0, 0, -5)

gluPerspective defines a Viewing frustum。视图的中心是 (0, 0)。因此,您需要更改顶点坐标。

我建议在绘制 3D 网格时启用 Depth Test

基于您的代码的最小示例:

from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
import time

width = 500
height = 500

vertices = [(-1,-1,-1), ( 1,-1,-1), ( 1, 1,-1), (-1, 1,-1), (-1,-1, 1), ( 1,-1, 1), ( 1, 1, 1), (-1, 1, 1)]
faces = [(4,0,3,7), (1,0,4,5), (0,1,2,3), (1,5,6,2), (3,2,6,7), (5,4,7,6)]
colors = [(1, 0, 0), (0, 1, 0), (0, 0, 1), (1, 1, 0), (1, 0, 1), (0, 1, 1)]

def cube():
    glRotatef(1, 3, 1, 1)
    glBegin(GL_QUADS)
    for i, face in enumerate(faces):
        glColor3fv(colors[i])
        for vertex in face:
            glVertex3fv(vertices[vertex])
    glEnd()

def showScreen():
    glClearColor(0, 0, 0, 1)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    cube()
    glutSwapBuffers()

def mouseTracker(mousex, mousey):
    print(f"Mouse pos: {mousex}, {mousey}")

def reshapeWindow(x, y):
    global width, height
    width = x
    height = y
    print(x, y)
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluPerspective(45, (width / height), 0.0001, 1000)
    glMatrixMode(GL_MODELVIEW)

glutInit()
glutInitDisplayMode(GLUT_RGBA)
glutInitWindowSize(500, 500)
wind = glutCreateWindow("OpenGL")
glutDisplayFunc(showScreen)
glutIdleFunc(showScreen)
glutMotionFunc(mouseTracker)
glutPassiveMotionFunc(mouseTracker)
glutReshapeFunc(reshapeWindow)

glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glTranslatef(0, 0, -5)

glEnable(GL_DEPTH_TEST)

while True:
    glutMainLoopEvent()
    glutPostRedisplay()
    time.sleep(0.01)