为什么 GLUT window 不响应重新显示请求?
Why doesn't GLUT window respond to redisplay requests?
我有一个程序可以在没有 display/UI 的情况下执行大部分工作,但随后需要以低延迟方式短暂显示一些内容。我通过 PyOpenGL 使用 GLUT 在单独的线程中显示 window ,然后在必要时用主线程中的内容填充它。我遇到的问题是 GLUT window 似乎只在鼠标光标移过 window 时才识别出已发出重新显示请求。这看起来很奇怪,显然我希望 GLUT window 尽快更新,而不是无限期地等待鼠标光标移动。
我怀疑这可能是特定于平台的问题。我已确认该行为可在 Ubuntu 16.04.2 和 14.04.5 上重现。
要重现的完整代码如下(需要 PyOpenGL)。此代码所需的行为是让 GLUT window 显示黑色,然后在一秒钟后自动切换为红色,然后是绿色,然后是蓝色,然后退出,所有这些在脚本启动后都没有任何鼠标移动。相反,GLUT window 将在程序启动时显示黑色,并且它将无限期地保持黑色,直到鼠标光标移过 window(然后变为红色,直到再次移动鼠标,等等)。光标在 window 内部还是外部都没有关系——它必须被移动,否则 onDisplay 处理程序将不会触发。
如何让下面的程序 运行 完成而不管鼠标在做什么?
from OpenGL.GLUT import *
from OpenGL.GLU import *
from OpenGL.GL import *
import sys
import threading
import time
hWin = None
displayevent = threading.Event()
bgcolor = (0,0,0,1)
def onDisplay():
print(" [onDisplay] Started")
glClearColor(*bgcolor)
glClear(GL_COLOR_BUFFER_BIT)
glutSwapBuffers()
print(" [onDisplay] Finished")
displayevent.set()
print(" [onDisplay] Exiting")
def runGl():
global hWin
glutInit(sys.argv)
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB)
glutInitWindowPosition(0, 0)
hWin = glutCreateWindow("GLWindow")
glutDisplayFunc(onDisplay)
print("[runGl] Entering main GLUT loop")
glutMainLoop()
print("[runGl] Exited main GLUT loop")
glThread = threading.Thread(target=runGl)
print("[main] Showing GLUT window")
glThread.start()
print("[main] Waiting for GLUT window to initialize")
time.sleep(1)
print("[main] GLUT window initialization (assumed) complete")
colors = [(1, 0, 0, 1), (0, 1, 0, 1), (0, 0, 1, 1)]
for i in range(len(colors)):
print("[main] --- Iteration %d ---" % i)
print("[main] Waiting...")
time.sleep(1)
print("[main] Trigging display update")
bgcolor = colors[i]
displayevent.clear()
glutPostRedisplay()
print("[main] Waiting for redraw to complete")
displayevent.wait()
print("[main] Redraw is complete")
print("[main] Closing window")
glutDestroyWindow(hWin)
print("[main] All done.")
您必须从初始化 GLUT 的同一线程调用 glutPostRedisplay()
。
How can I call glutPostRedisplay
on the thread that is fully occupied by glutMainLoop
反过来想一想。使用该事件告诉您的主循环发生了某些变化。
def display():
glClearColor(*bgcolor)
glClear(GL_COLOR_BUFFER_BIT)
glutSwapBuffers()
def idle():
if displayevent.is_set():
glutPostRedisplay()
使用glutIdleFunc(idle)
.
这样您的主循环将继续 运行 并检查是否设置了 displayevent
。然后在你的循环中而不是 displayevent.wait()
你调用 displayevent.set()
.
您当然可以在调用 glutSwapBuffers()
后设置一个额外的事件。然后你可以等待那个事件。
这与您执行异步加载的方式类似。您有一个辅助线程加载并处理图像数据。然后当它完成时你将它标记为这样并且主/渲染线程调用 glTexImage2D()
.
我有一个程序可以在没有 display/UI 的情况下执行大部分工作,但随后需要以低延迟方式短暂显示一些内容。我通过 PyOpenGL 使用 GLUT 在单独的线程中显示 window ,然后在必要时用主线程中的内容填充它。我遇到的问题是 GLUT window 似乎只在鼠标光标移过 window 时才识别出已发出重新显示请求。这看起来很奇怪,显然我希望 GLUT window 尽快更新,而不是无限期地等待鼠标光标移动。
我怀疑这可能是特定于平台的问题。我已确认该行为可在 Ubuntu 16.04.2 和 14.04.5 上重现。
要重现的完整代码如下(需要 PyOpenGL)。此代码所需的行为是让 GLUT window 显示黑色,然后在一秒钟后自动切换为红色,然后是绿色,然后是蓝色,然后退出,所有这些在脚本启动后都没有任何鼠标移动。相反,GLUT window 将在程序启动时显示黑色,并且它将无限期地保持黑色,直到鼠标光标移过 window(然后变为红色,直到再次移动鼠标,等等)。光标在 window 内部还是外部都没有关系——它必须被移动,否则 onDisplay 处理程序将不会触发。
如何让下面的程序 运行 完成而不管鼠标在做什么?
from OpenGL.GLUT import *
from OpenGL.GLU import *
from OpenGL.GL import *
import sys
import threading
import time
hWin = None
displayevent = threading.Event()
bgcolor = (0,0,0,1)
def onDisplay():
print(" [onDisplay] Started")
glClearColor(*bgcolor)
glClear(GL_COLOR_BUFFER_BIT)
glutSwapBuffers()
print(" [onDisplay] Finished")
displayevent.set()
print(" [onDisplay] Exiting")
def runGl():
global hWin
glutInit(sys.argv)
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB)
glutInitWindowPosition(0, 0)
hWin = glutCreateWindow("GLWindow")
glutDisplayFunc(onDisplay)
print("[runGl] Entering main GLUT loop")
glutMainLoop()
print("[runGl] Exited main GLUT loop")
glThread = threading.Thread(target=runGl)
print("[main] Showing GLUT window")
glThread.start()
print("[main] Waiting for GLUT window to initialize")
time.sleep(1)
print("[main] GLUT window initialization (assumed) complete")
colors = [(1, 0, 0, 1), (0, 1, 0, 1), (0, 0, 1, 1)]
for i in range(len(colors)):
print("[main] --- Iteration %d ---" % i)
print("[main] Waiting...")
time.sleep(1)
print("[main] Trigging display update")
bgcolor = colors[i]
displayevent.clear()
glutPostRedisplay()
print("[main] Waiting for redraw to complete")
displayevent.wait()
print("[main] Redraw is complete")
print("[main] Closing window")
glutDestroyWindow(hWin)
print("[main] All done.")
您必须从初始化 GLUT 的同一线程调用 glutPostRedisplay()
。
How can I call
glutPostRedisplay
on the thread that is fully occupied byglutMainLoop
反过来想一想。使用该事件告诉您的主循环发生了某些变化。
def display():
glClearColor(*bgcolor)
glClear(GL_COLOR_BUFFER_BIT)
glutSwapBuffers()
def idle():
if displayevent.is_set():
glutPostRedisplay()
使用glutIdleFunc(idle)
.
这样您的主循环将继续 运行 并检查是否设置了 displayevent
。然后在你的循环中而不是 displayevent.wait()
你调用 displayevent.set()
.
您当然可以在调用 glutSwapBuffers()
后设置一个额外的事件。然后你可以等待那个事件。
这与您执行异步加载的方式类似。您有一个辅助线程加载并处理图像数据。然后当它完成时你将它标记为这样并且主/渲染线程调用 glTexImage2D()
.