Win32 消息队列在使用 OpenGL 渲染时被淹没

Win32 message queue gets flooded when rendering with OpenGL

本文关键字:淹没 OpenGL 消息 队列 Win32      更新时间:2023-10-16

我将Windows API的CreateWindow封装在一个我称之为GLWindow的类周围,我使用OpenGL渲染图像。 我花了一些时间,我什至封装了消息队列,所以基本上我的main函数看起来像这样:

int main()
{
GLWindow win;
win.create("OpenGL Window", false, 1600, 800, -1, -1, true);
win.hideCursor();
win.moveMouseToCenter();
init(); //initialize some opengl stuff
bool quit = false;
WindowEvent ev;
while (!quit) {
if (win.pollEvent(ev))
{
if (ev.type == ev.WindowClosed || (ev.type == ev.KeyboardKeyPressed && ev.keyboardKey.key == Keyboard::Key::Escape))
quit = true;
else
handleEvent(ev);
}
updateCamera(&win);
render(&win);
}
return 0;
}

render函数显然花费的时间最多,它会导致窗口过程函数被消息淹没,最终在WM_KEYDOWNWM_MOUSEMOVE消息中造成延迟,因此相机更新也会延迟。(updateCamera()内)

知道我能做什么吗?

问题是,您的代码在呈现帧之间处理一条消息。相反,它应该耗尽整个消息队列。这就像将消息轮询表达式的if替换为while一样简单。如果您遇到终止条件,立即break出圈可能也是一个好主意。

while (!quit) {
while (win.pollEvent(ev))
{
if (ev.type == ev.WindowClosed || (ev.type == ev.KeyboardKeyPressed && ev.keyboardKey.key == Keyboard::Key::Escape))
{
quit = true;
break;
}
else
handleEvent(ev);
}
updateCamera(&win);
render(&win);
}

基本上你的OOP抽象是垃圾。而且,正如评论指出的那样,您没有包含它。

win.pollEvent(ev)强烈暗示您仅针对单个窗口轮询事件。这是错误的 - 消息循环必须为线程上的所有窗口泵送消息。

它也完全不清楚handleEvent()做什么 - 我希望它调用TranslateMessage / DispatchMessage以确保消息到达您的 GLWindows 窗口程序。

所以现在,我们看不到你的WindowProc。它能处理WM_PAINT吗?它是否正确处理它?在消息中包含updateCamerarender意味着您可能没有正确处理您的绘画要求。虽然这是一种用于实现高帧速率渲染的模式,但编写一个正确泵送消息的游戏循环是困难的,并且您可能最好(现在)让窗口在计时器上更新,并通过调用 InvalidateRect 触发WM_PAINT消息来进行绘画。无论如何,您都必须正确处理,以便您可以优雅地处理窗口大小调整,最小化和被其他窗口覆盖。