2010-10-24 81 views
0

注意:请在发布之前阅读所有内容,您将看到原因。多线程OpenGL/WinAPI应用程序

所以我有一个OpenGL/WinAPI应用程序。我正在做你期望的,通过做处理消息,渲染帧,处理消息,渲染帧的周期......

问题是,当我调整窗口大小或移动窗口时,屏幕冻结,它看起来相当丑陋。我知道,从以前的OpenGL版本开始,限制帧间处理消息的数量(通过数字或时间)是不可能的。看起来,Windows移动/调整窗口大小时会阻止我的应用程序。从expirimenting,我确实知道把窗口消息处理放到另一个线程中,忘记它会很好地工作,并有助于时间安排。

我的问题是:有没有更好的,破坏性较小或无线程的方式来做到这一点?我在做什么(除了多线程戏剧)还有什么不利之处?我很想知道多线程是否可以避免。

+4

我读了整个问题,但我仍然不明白为什么开始时需要注释。 – 2010-10-24 08:56:43

+0

渲染单个帧需要多长时间? – 2010-10-24 09:11:09

+0

它是一个引擎,所以这个部分是完全可变的。 – 2010-10-24 09:22:12

回答

3

当用户点击窗口的非客户区来移动或调整窗口大小时,DefwindowProc进入模态循环,因此您的游戏循环不再执行 - 直到用户取消或完成模态操作。

您可以使用窗口消息来检测模态操作的开始和结束:例如,WM_ENTERSIZEMOVE。问题的症结在于,如果你的OpenGL窗口不是全屏,或者它显示消息框,那么你不能依靠一个简单的游戏循环来继续渲染游戏 - 你需要切换到基于计时器的渲染器。

SetTimer可以创建一个定时器,即使在模态操作正在进行时也会发送WM_TIMER消息。

PS。关于线程的说明:如果跨线程共享上下文,则OpenGL上下文不是线程安全的,并且必须序列化(用户代码手动)访问。即使使用多个上下文,对实际设备的访问也会被序列化,因此多线程基于OpenGL的渲染器不会带来性能上的好处 - 除非(具有讽刺意味)您需要大量CPU密集型工作(然后像OpenMP并行化循环会比尝试设计更高级别的多线程渲染作业调度程序更有帮助。基本上来说:坚持使用OpenGL的单线程渲染器 - 它比几乎任何线程的尝试都会表现得更好,并且更具可预测性。

PPS。对于加窗的OpenGL应用程序,放弃传统的游戏循环方法来渲染每一帧可能会更好,并依靠RedrawWindow来向窗口发送WM_PAINT消息:在BeginPaint/EndPaint块内绘画意味着您的应用程序渲染行为更具可预测性, DesktopWindowManager进程可以处理其应用Aero Glass效果的工作,并试图更有效地实现桌面的同步更新。

+0

我想你误会了。只有一个线程处理OpenGL及其上下文。另一个是窗口处理。 – 2010-10-24 12:01:49

+0

没有。我只是希望...在反对多线程OpenGL的论点中完整。 UI线程+ OpenGl线程不提供任何性能优势,只是意味着无论如何都要序列化的活动现在必须在线程之间编组。另外,UI线程是操作系统给予前景提升的线程。在任何级别上将OpenGL渲染与窗口线程分开是没有意义的。 – 2010-10-24 12:37:30

0

作为解决方法的一个想法:渲染到一个FBO中,在每个调整大小消息的窗口中闪烁FBO(可能缩放它),并在消息队列为空时以适当的分辨率重新渲染FBO。

通过这种方式,您可以获得可预测的重绘效果,只需很少的工件并且无需线程。