Opengl 在wxWidgets中调整窗口大小时视口或投影未正确调整大小

Opengl 在wxWidgets中调整窗口大小时视口或投影未正确调整大小,opengl,wxwidgets,Opengl,Wxwidgets,我有一个wxWigets应用程序,使用contrib包中的wxGLCanvas小部件。每次刷新小部件时,我都会在渲染场景之前重新创建投影矩阵和视口。问题是,在调整帧大小后,无论是通过拖动、最大化还是w/e,小部件都会正确调整大小,但视口或投影无法真正辨别哪个未调整大小,因此场景最终会被裁剪 现在来看一些代码 wxGLCanvas小部件的构造函数如下所示: int attrib_list[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER }; RenderCanvas::

我有一个wxWigets应用程序,使用contrib包中的wxGLCanvas小部件。每次刷新小部件时,我都会在渲染场景之前重新创建投影矩阵和视口。问题是,在调整帧大小后,无论是通过拖动、最大化还是w/e,小部件都会正确调整大小,但视口或投影无法真正辨别哪个未调整大小,因此场景最终会被裁剪

现在来看一些代码

wxGLCanvas小部件的构造函数如下所示:

int attrib_list[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER };

RenderCanvas::RenderCanvas(wxFrame* parent) : wxGLCanvas(parent, idRender, wxPoint(200, -1), wxSize(800, 600), wxFULL_REPAINT_ON_RESIZE, wxT("GLCanvas"), attrib_list)
{
    Connect(idRender, wxEVT_PAINT, wxPaintEventHandler(RenderCanvas::PaintIt));
    Connect(idRender, wxEVT_SIZE, wxSizeEventHandler(RenderCanvas::Resize));

    Connect(idRender, wxEVT_LEFT_DOWN, wxMouseEventHandler(RenderCanvas::OnMouseLeftDown));
    Connect(idRender, wxEVT_LEFT_UP, wxMouseEventHandler(RenderCanvas::OnMouseLeftUp));
    Connect(idRender, wxEVT_MOTION, wxMouseEventHandler(RenderCanvas::OnMouseMotion));
}
void RenderCanvas::Render()
{
    Prepare2DViewport(0,GetClientSize().y,GetClientSize().x, 0);

    glClear(GL_COLOR_BUFFER_BIT);

    //Renders stuff...

    glFlush();
    SwapBuffers();
}
我对PaintIt方法的估计过高,如下所示:

void RenderCanvas::PaintIt(wxPaintEvent& event)
{
    SetCurrent();
    wxPaintDC(this);

    Render();
    Refresh(false);
}
以及调整大小的方法:

void RenderCanvas::Resize(wxSizeEvent& event)
{
    Refresh();
}
上面使用的渲染方法如下所示:

int attrib_list[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER };

RenderCanvas::RenderCanvas(wxFrame* parent) : wxGLCanvas(parent, idRender, wxPoint(200, -1), wxSize(800, 600), wxFULL_REPAINT_ON_RESIZE, wxT("GLCanvas"), attrib_list)
{
    Connect(idRender, wxEVT_PAINT, wxPaintEventHandler(RenderCanvas::PaintIt));
    Connect(idRender, wxEVT_SIZE, wxSizeEventHandler(RenderCanvas::Resize));

    Connect(idRender, wxEVT_LEFT_DOWN, wxMouseEventHandler(RenderCanvas::OnMouseLeftDown));
    Connect(idRender, wxEVT_LEFT_UP, wxMouseEventHandler(RenderCanvas::OnMouseLeftUp));
    Connect(idRender, wxEVT_MOTION, wxMouseEventHandler(RenderCanvas::OnMouseMotion));
}
void RenderCanvas::Render()
{
    Prepare2DViewport(0,GetClientSize().y,GetClientSize().x, 0);

    glClear(GL_COLOR_BUFFER_BIT);

    //Renders stuff...

    glFlush();
    SwapBuffers();
}
最后,调用glViewport和glOrtho函数的Prepare2DViewport是:

void RenderCanvas::Prepare2DViewport(int x, int h, int w, int y)
{
    glClearColor(0.7f, 0.7f, 0.7f, 1.0f); // Grey Background
    glEnable(GL_TEXTURE_2D);   // textures

    glEnable(GL_BLEND);
    glEnable(GL_LINE_SMOOTH);
    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);


    glViewport(x, y, w, -h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(x, (float)w, y, (float)h, -1.0f, 1.0f);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}
还应该注意的是,我曾尝试使用GetSize而不是GetClientSize,但效果相同。另外,我在Ubuntu 12.04上,wxWidgets正在使用GTK

更新:


还应该注意的是,我已经实现了单击/拖动功能,但没有显示,每次单击或拖动鼠标时,小部件都会刷新。话虽如此,我尝试断开wxEVT_SIZE事件的连接,但在调整大小并单击并拖动之后,同样的效果仍然存在。

快速浏览一下您的代码,我注意到您的调整大小事件处理程序所做的只是要求再次刷新。这在我看来并不正确。调整大小处理程序通常会进行一些计算,在请求刷新之前调用一个或多个子窗口的调整大小处理程序等等。因此,我认为您的问题是画布在重新绘制之前没有调整大小。这可以解释为什么要剪辑场景。不确定修复程序是什么-希望这将是一个足够的提示,这样您可以朝正确的方向看。

快速浏览一下您的代码,我注意到您的调整大小事件处理程序除了要求再次刷新外,没有做任何事情。这在我看来并不正确。调整大小处理程序通常会进行一些计算,在请求刷新之前调用一个或多个子窗口的调整大小处理程序等等。因此,我认为您的问题是画布在重新绘制之前没有调整大小。这可以解释为什么要剪辑场景。不确定修复方法是什么-希望这将是一个足够的提示,这样您可以朝正确的方向看。

好的,所以这对我来说是一个非常非常愚蠢的错误

在这一行

glViewport(x, y, w, -h);

我不小心将高度设置为负值。删除负号修复了该问题。我不知道为什么它会导致作物歉收。我想如果高度为负数,我就看不见任何东西了,但它是有效的,所以我想我不能抱怨。再次感谢大家的帮助

好吧,结果我犯了一个非常非常愚蠢的错误

在这一行

glViewport(x, y, w, -h);

我不小心将高度设置为负值。删除负号修复了该问题。我不知道为什么它会导致作物歉收。我想如果高度为负数,我就看不见任何东西了,但它是有效的,所以我想我不能抱怨。再次感谢大家的帮助

我的印象是,在所有正常的调整大小处理发生之后,就调用了调整大小处理程序。就像回电话一样。不是这样吗?另外,我在尝试纠正你的建议后更新了我的帖子。不是。调整大小处理程序调整窗口大小。您已经用一个新的不进行大小调整的处理程序重新实现了原来的大小调整处理程序。我明白了。好吧,不管怎样,如果我删除了调整大小处理程序,如果它在其他地方刷新,它不应该工作吗?我的印象是,调整大小处理程序是在所有正常的调整大小处理发生后调用的。就像回电话一样。不是这样吗?另外,我在尝试纠正你的建议后更新了我的帖子。不是。调整大小处理程序调整窗口大小。您已经用一个新的不进行大小调整的处理程序重新实现了原来的大小调整处理程序。我明白了。好吧,不管怎样,如果我删除了resize处理程序,那么如果在其他地方刷新它,它不应该工作吗?