OpenGL纹理闪烁/有时在窗口大小上移动

Opengl texture flickers/moves sometimes on window resize

本文关键字:窗口大小 移动 纹理 闪烁 OpenGL      更新时间:2023-10-16

我有一个小问题。

我有一个带有OpenGL子窗口的窗口,到目前为止,所有OpenGL窗口都在窗口右下方呈现纹理。

如果我从左至右快速调整窗口的大小,则纹理有时会向左移动,就像它的重新粉刷不够快,甚至不知道我直接绘制绘制到OpenGL上下文。

我删除问题的唯一方法是在调整主窗口大小时将OpenGL窗口的无效我已经在上下文上画了。

如果 bHandled是false,则称为defwndproc,否则将返回函数

主窗口wm_size

int ControllerMainWnd::OnSize(WPARAM wParam, LPARAM lParam, bool & bHandled)
{
    bHandled = true;
    int width = LOWORD(lParam);
    int height = HIWORD(lParam);
    //Set OpenGL Window Size
    ::SetWindowPos(glHandle, 0, 0, 0, width, height, SWP_NOZORDER);
    //Invalidate OpenGL Window
    ::InvalidateRect(glHandle, 0, FALSE); // if i comment this out my texture sometime moves
    return 0;
}

OpenGL窗口

int ControllerGL::OnPaint(WPARAM wParam, LPARAM lParam, bool & bHandled)
{
    //bHandled = true;
    //LRESULT lRes = defWinProc(WM_PAINT, wParam, lParam);
    Paint();
    //return lRes;
    return 0;
}
int ControllerGL::OnSize(WPARAM wParam, LPARAM lParam, bool & bHandled)
{
    bHandled = true;
    int width = LOWORD(lParam);
    int height = HIWORD(lParam);
    modelGL->setWindowSize(width, height);
    Paint();
    return 0;
}
int ControllerGL::OnEraseBkgnd(WPARAM wParam, LPARAM lParam, bool & bHandled)
{
    bHandled = true;
    return 1L;
}
auto ControllerGL::Paint() -> void
{
    openGLcontext->activateContext();
    modelGL->draw();
    openGLcontext->swapBuffers();
}

您的问题可能与您每次在调整大小期间移动鼠标时要导致窗口重新涂抹2次的事实相关联。

首先,在调整大小时,Windows会自动使Windows区域无效(您可以使用类样式CS_HREDRAW和CS_VREDRAW来控制此区域,该样式应始终设置为OpenGL Windows,因为调整大小通常需要完整的窗口。

然后,您(冗余(手动使窗口rect无效。然后,您将其迫使它进行绘画 - 现在已经排队了未来的油漆。

OpenGL窗口的OnPaint处理程序应该看起来像:

int ControllerGL::OnPaint(WPARAM wParam, LPARAM lParam, bool & bHandled)
{
    PAINTSTRUCT ps;
    HDC hdc = BeginPaint(hwnd,&ps);
    wglMakeCurrent(hdc,hglrc);
    scene->Display();
    SwapBuffers(hdc);
    wglMakeCurrent(hdc,NULL);
    EndPaint(hwnd,&ps);
    bHandled = true;
    return 0;
}

我将其作为一种练习,以正确封装HWND和HGLRC,以这种方式编写它,明确显示SwapBuffers在DC上工作,而不是在隐式OpenGL上下文上工作,并且应用一个动态获得的窗口范围DC。

大多数OpenGL样本都非常懒惰,并且使用类DC,只需将OpenGL内容留下"活动",但是只要线程上的两个窗口试图执行OpenGL,就会失败。最好省略CS_OWNDC(如果有(并在实际需要时获取(并发布(DC。

即。如果您想更传统地处理WM_Size(类似于Glut Reshape回调(,您将执行此操作:

int ControllerGL::OnSize(WPARAM wParam, LPARAM lParam, bool & bHandled)
{
    bHandled = true;
    int width = LOWORD(lParam);
    int height = HIWORD(lParam);
    HDC hdc = GetDC(hwnd);
    wglMakeCurrent(hdc,hglrc);
    scene->Reshape(width,height);
    wglMakeCurrent(hdc,NULL);
    ReleaseDC(hwnd,hdc);
    return 0;
}

ControllerGL到我称为scene的所有其他电话,您称为modelGL