如何解决在 glClear
在使用 PyOpenGL 和 pygame 编写非常简单的介绍性代码时,我偶然发现了一个逻辑错误。立方体(用三角形条带和 glDrawArray
渲染)将在第一帧出现一次,然后在之后的所有帧中消失。
MRE:
import pygame
pygame.init()
from OpenGL import GL
from OpenGL import glu
def solidCube():
vertices = (-1.0,1.0,-1.0,-1.0)
GL.glColor3f(255,255,255)
GL.glEnableClientState(GL.GL_VERTEX_ARRAY)
data = (GL.GLfloat * len(vertices))(*vertices)
GL.glVertexPointer(3,GL.GL_FLOAT,data)
GL.glDrawArrays(GL.GL_TRIANGLE_STRIP,14)
GL.gldisableClientState(GL.GL_VERTEX_ARRAY)
display = (600,500)
screen = pygame.display.set_mode(display,pygame.DOUBLEBUF|pygame.OPENGL)
GL.glMatrixMode(GL.GL_PROJECTION)
GL.glLoadIdentity()
glu.gluPerspective(90,(display[0]/display[1]),0.1,100.0)
glu.gluLookAt(0,1,0)
game = 1
clock = pygame.time.Clock()
while game:
for event in pygame.event.get():
if event.type == pygame.QUIT:
game = 0
GL.glMatrixMode(GL.GL_MODELVIEW)
GL.glLoadIdentity()
GL.glClearColor(0,1)
GL.glClear(GL.GL_COLOR_BUFFER_BIT|GL.GL_DEPTH_BUFFER_BIT)
GL.glTranslatef(-10,0)
solidCube()
GL.glMatrixMode(GL.GL_PROJECTION)
GL.glLoadIdentity()
glu.gluLookAt(0,0)
pygame.display.flip()
clock.tick(50)
pygame.quit()
这段代码没有出现错误,而是没有显示多维数据集超过一帧,而是闪烁一次,然后不再显示。然后我开始调试。
我的 gluLookAt
和 gluPerspective
是静态值,它们没有改变。因此,不可能是我没有看到立方体(它在第一帧正确渲染,这些是正确的值)。我的立方体的位置也是静态的,它没有移动到任何地方,也没有超出我的视野。所以,归结为立方体没有被绘制。我从代码中删除了 glClear
语句,立方体忽明忽暗。我过去遇到过类似的问题,对象仅位于两个视频缓冲区之一中,因此 pygame.display.flip()
会在两者之间快速交换,使其出现和消失。
因此,我能够找到我的问题:立方体被绘制一次,然后渲染(正确)。在此之后,它会清除两个缓冲区并且立方体不会被重绘,所以我只剩下一个空白屏幕。
总而言之,我的问题是:为什么我的三角带立方体没有被多次绘制,我该如何解决这个问题,并让它重新绘制?
解决方法
你只是混淆了矩阵。投影矩阵应设置为当前 GL_PROJECTION
矩阵,模式视图矩阵应设置为当前 GL_MODELVIEW
。
GL.glMatrixMode(GL.GL_PROJECTION)
GL.glLoadIdentity()
GLU.gluPerspective(90,(display[0]/display[1]),0.1,100.0)
game = 1
clock = pygame.time.Clock()
while game:
for event in pygame.event.get():
if event.type == pygame.QUIT:
game = 0
GL.glMatrixMode(GL.GL_MODELVIEW)
GL.glLoadIdentity()
GLU.gluLookAt(0,-1.0,1,0)
GL.glClearColor(0,1)
GL.glClear(GL.GL_COLOR_BUFFER_BIT|GL.GL_DEPTH_BUFFER_BIT)
GL.glTranslatef(-10,0)
solidCube()
pygame.display.flip()
请注意,OpenGL 是一个状态引擎。设置状态后,它会一直保留直到再次更改,甚至超出帧。
受矩阵运算影响的矩阵用 glMatrixMode
指定。矩阵运算,如gluPerspective
、gluLookAt
、glRotate
、glScale
、glTranslatef
,不仅设置了一个矩阵,还定义了一个新矩阵并乘以当前矩阵由新矩阵。因此,您可以使用 glLoadIdentity
“重置”当前矩阵。 glLoadIdentity
将 Identity matrix 分配给当前矩阵。
完整示例:
import numpy as np
import pygame
pygame.init()
from OpenGL import GL
from OpenGL import GLU
def solidCube():
vertices = (-1.0,1.0,-1.0)
GL.glColor3f(255,255,255)
GL.glEnableClientState(GL.GL_VERTEX_ARRAY)
data = (GL.GLfloat * len(vertices))(*vertices)
GL.glVertexPointer(3,GL.GL_FLOAT,data)
GL.glDrawArrays(GL.GL_TRIANGLE_STRIP,14)
GL.glDisableClientState(GL.GL_VERTEX_ARRAY)
display = (600,500)
screen = pygame.display.set_mode(display,pygame.DOUBLEBUF|pygame.OPENGL)
GL.glMatrixMode(GL.GL_PROJECTION)
GL.glLoadIdentity()
GLU.gluPerspective(90,100.0)
angle = 0
game = 1
clock = pygame.time.Clock()
while game:
for event in pygame.event.get():
if event.type == pygame.QUIT:
game = 0
GL.glMatrixMode(GL.GL_MODELVIEW)
GL.glLoadIdentity()
GLU.gluLookAt(0,1)
GL.glClear(GL.GL_COLOR_BUFFER_BIT|GL.GL_DEPTH_BUFFER_BIT)
GL.glTranslatef(-5,0)
GL.glRotatef(angle,0)
angle += 1
GL.glPolygonMode(GL.GL_FRONT_AND_BACK,GL.GL_LINE)
solidCube()
pygame.display.flip()
clock.tick(50)
pygame.quit()
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。