如何调整 GLUT window 的大小?
How to resize a GLUT window?
from OpenGL.extensions import alternate
from OpenGL.GL import *
from OpenGL.GL.ARB.multitexture import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
class TestTexture():
def __init__(self):
self.window_width = 800
self.window_height = 800
def init(self):
glClearColor(0.0, 0.0, 0.0, 0.0)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glEnable(GL_TEXTURE_2D)
def display(self):
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glLoadIdentity()
glBegin(GL_TRIANGLES)
glVertex3f(-1.0, 0.0, 0.0)
glVertex3f(1.0, 0.0, 0.0)
glVertex3f(0.0, 1.0, 0.0)
glEnd()
glFlush()
glutSwapBuffers()
def reshape(self, w, h):
self.window_width = w
self.window_height = h
glViewport(0, 0, self.window_width, self.window_height)
def animate(self):
glutPostRedisplay()
def visible(self, vis):
if (vis == GLUT_VISIBLE):
glutIdleFunc(self.animate)
else:
glutIdleFunc(0)
def key_pressed(self, *args):
if args[0] == b"\x1b":
sys.exit()
def run(self):
glutInit(sys.argv)
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH)
glutInitWindowSize(self.window_width, self.window_height)
glutInitWindowPosition(800, 100)
glutCreateWindow(b'MCVE')
glutDisplayFunc(self.display)
glutReshapeFunc(self.reshape)
glutIdleFunc(self.animate)
glutVisibilityFunc(self.visible)
glutKeyboardFunc(self.key_pressed)
self.init()
glutMainLoop()
if __name__ == "__main__":
TestTexture().run()
我已经尝试了一些方法来正确调整大小和刷新此window,但到目前为止还没有成功。当 window 调整大小时,场景应该实时正确渲染,但事实并非如此,相反,场景仅在您释放鼠标时更新(不调用重塑函数),或者在调整大小时它会得到一个更新的机会很少,但最终的结果绝对不酷
值得一提的是,pyqt opengl 应用程序可以正常调整大小并且启用了 show window contents while dragging 选项。
已在windows7、PyOpenGL==3.1.1和python3.5.1_x86
上进行测试
所以问题是,我如何实时正确地调整和刷新过剩 window?
首先要注意的是 glViewport
不属于重塑处理程序(如果我每次写这篇文章都有一分钱的话……)。
您 运行 遇到的问题不是您可以从 GLUT "outside" 中轻松解决的问题,因为它本质上归结为如何实现主循环的内部结构。为了在技术上调整大小期间平滑更新 window 的内容,主循环必须通过平滑地交错调整大小事件与显示函数的调用来适应这种情况。 glutPostRedisplay
标记主循环重绘的方式将每隔几个调整大小步骤调用一次显示函数,但它可能伴随着闪烁和抖动的重绘。
最好的办法是做一些通常不受欢迎的事情:在调整大小处理程序的末尾调用显示函数(包括缓冲区交换)并且不要调用 glutPostRedisplay
。然而,这可能仍然容易出现闪烁,具体取决于 WSI 背景擦除的实施方式。这样做的问题是,调整大小事件可能会排队,并且调整大小的步骤早已开始滞后于用户操作。
要真正平滑地调整大小更新,需要一个适当编写的主循环,它合并 input/resize 事件以避免队列延迟问题,并允许在没有自动背景擦除的情况下进行调整大小绘图操作以支持平滑更新。 GLUT 的当前实现不会这样做。
from OpenGL.extensions import alternate
from OpenGL.GL import *
from OpenGL.GL.ARB.multitexture import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
class TestTexture():
def __init__(self):
self.window_width = 800
self.window_height = 800
def init(self):
glClearColor(0.0, 0.0, 0.0, 0.0)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glEnable(GL_TEXTURE_2D)
def display(self):
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glLoadIdentity()
glBegin(GL_TRIANGLES)
glVertex3f(-1.0, 0.0, 0.0)
glVertex3f(1.0, 0.0, 0.0)
glVertex3f(0.0, 1.0, 0.0)
glEnd()
glFlush()
glutSwapBuffers()
def reshape(self, w, h):
self.window_width = w
self.window_height = h
glViewport(0, 0, self.window_width, self.window_height)
def animate(self):
glutPostRedisplay()
def visible(self, vis):
if (vis == GLUT_VISIBLE):
glutIdleFunc(self.animate)
else:
glutIdleFunc(0)
def key_pressed(self, *args):
if args[0] == b"\x1b":
sys.exit()
def run(self):
glutInit(sys.argv)
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH)
glutInitWindowSize(self.window_width, self.window_height)
glutInitWindowPosition(800, 100)
glutCreateWindow(b'MCVE')
glutDisplayFunc(self.display)
glutReshapeFunc(self.reshape)
glutIdleFunc(self.animate)
glutVisibilityFunc(self.visible)
glutKeyboardFunc(self.key_pressed)
self.init()
glutMainLoop()
if __name__ == "__main__":
TestTexture().run()
我已经尝试了一些方法来正确调整大小和刷新此window,但到目前为止还没有成功。当 window 调整大小时,场景应该实时正确渲染,但事实并非如此,相反,场景仅在您释放鼠标时更新(不调用重塑函数),或者在调整大小时它会得到一个更新的机会很少,但最终的结果绝对不酷
值得一提的是,pyqt opengl 应用程序可以正常调整大小并且启用了 show window contents while dragging 选项。
已在windows7、PyOpenGL==3.1.1和python3.5.1_x86
上进行测试所以问题是,我如何实时正确地调整和刷新过剩 window?
首先要注意的是 glViewport
不属于重塑处理程序(如果我每次写这篇文章都有一分钱的话……)。
您 运行 遇到的问题不是您可以从 GLUT "outside" 中轻松解决的问题,因为它本质上归结为如何实现主循环的内部结构。为了在技术上调整大小期间平滑更新 window 的内容,主循环必须通过平滑地交错调整大小事件与显示函数的调用来适应这种情况。 glutPostRedisplay
标记主循环重绘的方式将每隔几个调整大小步骤调用一次显示函数,但它可能伴随着闪烁和抖动的重绘。
最好的办法是做一些通常不受欢迎的事情:在调整大小处理程序的末尾调用显示函数(包括缓冲区交换)并且不要调用 glutPostRedisplay
。然而,这可能仍然容易出现闪烁,具体取决于 WSI 背景擦除的实施方式。这样做的问题是,调整大小事件可能会排队,并且调整大小的步骤早已开始滞后于用户操作。
要真正平滑地调整大小更新,需要一个适当编写的主循环,它合并 input/resize 事件以避免队列延迟问题,并允许在没有自动背景擦除的情况下进行调整大小绘图操作以支持平滑更新。 GLUT 的当前实现不会这样做。