使用OpenGL进行渲染时,Win32消息队列会被泛洪

时间:2017-05-29 19:28:30

标签: c++ windows winapi opengl

我将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()内)

知道我该怎么办?

2 个答案:

答案 0 :(得分:3)

问题是,您的代码处理渲染帧之间的单个消息。相反,它应该耗尽整个消息队列。这可以像使用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);
}

答案 1 :(得分:1)

基本上你的OOP抽象是垃圾。而且,正如评论所指出的那样,你没有把它包括在内。

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

它还完全不清楚handleEvent()的作用 - 我希望它调用TranslateMessage / DispatchMessage来确保消息到达你的GLWindows窗口过程。

现在,我们看不到您的WindowProc。它完全处理WM_PAINT吗?它能正确处理吗?在邮件中包含updateCamerarender意味着您可能无法正确处理您的绘画要求。虽然这是用于实现高帧率渲染的模式,但编写正确抽取消息的游戏循环很难,并且您可能会更好地服务(现在)让窗口更新计时器,并通过触发进行绘制通过调用InvalidateRect来WM_PAINT消息。无论如何你必须正确使用它,这样你就可以处理窗口大小调整,最大限度地减少其他窗口的覆盖范围。