PyOpenGL 在 glClear 之后不会多次重绘三角形带
PyOpenGL does not redraw triangle strip more than once after 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, 1.0, 1.0,
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, -1.0, -1.0,
1.0, 1.0, 1.0,
1.0, 1.0, -1.0,
-1.0, 1.0, 1.0,
-1.0, 1.0, -1.0,
-1.0, -1.0, 1.0,
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
-1.0, 1.0, -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, 0, data)
GL.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 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, 0, 0, -1.0, 0, 0, 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, 0, 0, 1)
GL.glClear(GL.GL_COLOR_BUFFER_BIT|GL.GL_DEPTH_BUFFER_BIT)
GL.glTranslatef(-10, 0, 0)
solidCube()
GL.glMatrixMode(GL.GL_PROJECTION)
GL.glLoadIdentity()
GLU.gluLookAt(0, 0, 0, -1.0, 0, 0, 0, 1, 0)
pygame.display.flip()
clock.tick(50)
pygame.quit()
此代码没有引发任何错误,但没有显示多维数据集超过一帧,而是闪烁一次,然后不再显示。然后我就开始调试了。
我的gluLookAt
和gluPerspective
是静态值,没有变化。因此,我不可能没有看到立方体(它正确渲染了第一帧,这些是正确的值)。我的立方体的位置也是静止的,它没有移动到任何地方,也没有超出我的 FOV。所以,归结为没有绘制立方体。我从代码中删除了 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, 0, 0, -1.0, 0, 0, 0, 1, 0)
GL.glClearColor(0, 0, 0, 1)
GL.glClear(GL.GL_COLOR_BUFFER_BIT|GL.GL_DEPTH_BUFFER_BIT)
GL.glTranslatef(-10, 0, 0)
solidCube()
pygame.display.flip()
请注意,OpenGL 是一个状态引擎。设置状态后,它会一直保留直到再次更改,甚至超出帧范围。
受矩阵运算影响的矩阵用glMatrixMode
. The matrix operations, like gluPerspective
, gluLookAt
, glRotate
, glScale
, glTranslatef
, not only set a matrix, they define a new matrix and multiply the current matrix by the new matrix. Therefore you can "reset" a current matrix with glLoadIdentity
. glLoadIdentity
assigns the 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,
1.0, 1.0, 1.0,
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, -1.0, -1.0,
1.0, 1.0, 1.0,
1.0, 1.0, -1.0,
-1.0, 1.0, 1.0,
-1.0, 1.0, -1.0,
-1.0, -1.0, 1.0,
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
-1.0, 1.0, -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, 0, data)
GL.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 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)
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, 0, 0, -1.0, 0, 0, 0, 1, 0)
GL.glClearColor(0, 0, 0, 1)
GL.glClear(GL.GL_COLOR_BUFFER_BIT|GL.GL_DEPTH_BUFFER_BIT)
GL.glTranslatef(-5, 0, 0)
GL.glRotatef(angle, 0, 1, 0)
angle += 1
GL.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_LINE)
solidCube()
pygame.display.flip()
clock.tick(50)
pygame.quit()
在使用 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, 1.0, 1.0,
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, -1.0, -1.0,
1.0, 1.0, 1.0,
1.0, 1.0, -1.0,
-1.0, 1.0, 1.0,
-1.0, 1.0, -1.0,
-1.0, -1.0, 1.0,
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
-1.0, 1.0, -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, 0, data)
GL.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 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, 0, 0, -1.0, 0, 0, 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, 0, 0, 1)
GL.glClear(GL.GL_COLOR_BUFFER_BIT|GL.GL_DEPTH_BUFFER_BIT)
GL.glTranslatef(-10, 0, 0)
solidCube()
GL.glMatrixMode(GL.GL_PROJECTION)
GL.glLoadIdentity()
GLU.gluLookAt(0, 0, 0, -1.0, 0, 0, 0, 1, 0)
pygame.display.flip()
clock.tick(50)
pygame.quit()
此代码没有引发任何错误,但没有显示多维数据集超过一帧,而是闪烁一次,然后不再显示。然后我就开始调试了。
我的gluLookAt
和gluPerspective
是静态值,没有变化。因此,我不可能没有看到立方体(它正确渲染了第一帧,这些是正确的值)。我的立方体的位置也是静止的,它没有移动到任何地方,也没有超出我的 FOV。所以,归结为没有绘制立方体。我从代码中删除了 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, 0, 0, -1.0, 0, 0, 0, 1, 0)
GL.glClearColor(0, 0, 0, 1)
GL.glClear(GL.GL_COLOR_BUFFER_BIT|GL.GL_DEPTH_BUFFER_BIT)
GL.glTranslatef(-10, 0, 0)
solidCube()
pygame.display.flip()
请注意,OpenGL 是一个状态引擎。设置状态后,它会一直保留直到再次更改,甚至超出帧范围。
受矩阵运算影响的矩阵用glMatrixMode
. The matrix operations, like gluPerspective
, gluLookAt
, glRotate
, glScale
, glTranslatef
, not only set a matrix, they define a new matrix and multiply the current matrix by the new matrix. Therefore you can "reset" a current matrix with glLoadIdentity
. glLoadIdentity
assigns the 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,
1.0, 1.0, 1.0,
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, -1.0, -1.0,
1.0, 1.0, 1.0,
1.0, 1.0, -1.0,
-1.0, 1.0, 1.0,
-1.0, 1.0, -1.0,
-1.0, -1.0, 1.0,
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
-1.0, 1.0, -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, 0, data)
GL.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 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)
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, 0, 0, -1.0, 0, 0, 0, 1, 0)
GL.glClearColor(0, 0, 0, 1)
GL.glClear(GL.GL_COLOR_BUFFER_BIT|GL.GL_DEPTH_BUFFER_BIT)
GL.glTranslatef(-5, 0, 0)
GL.glRotatef(angle, 0, 1, 0)
angle += 1
GL.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_LINE)
solidCube()
pygame.display.flip()
clock.tick(50)
pygame.quit()