Hey!
I developed a piece of software that displays stuff with OpenGL. I originally made the thing using GLFW and using a OpenGL 3.0 context. To get a UI I swapped the GLFW library to Qt and changed to QOpenGLWidget. I am using shaders and doing pretty much everything in shaders so to prevent rewriting most of my OpenGL code I do not want to use Qts OpenGL 2.0 ES API.
I have everything working pretty nicely except I cannot figure out why the OpenGL scene is only drawn the first time and nothing happens on successive paintGL() calls.
I have a RenderWidget which inherits from QOpenGLWidget. In its constructor I set:
QSurfaceFormat format;
format.setVersion(3,0);
format.setSamples(4);
format.setProfile(QSurfaceFormat::NoProfile);
format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
setFormat(format);
QSurfaceFormat format;
format.setVersion(3,0);
format.setSamples(4);
format.setProfile(QSurfaceFormat::NoProfile);
format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
setFormat(format);
To copy to clipboard, switch view to plain text mode
Then in initializeGL() I do:
context_ = context();
funcs_ = context_->versionFunctions<QOpenGLFunctions_3_0>();
funcs_->initializeOpenGLFunctions();
renderer_.init(funcs_);
context_ = context();
funcs_ = context_->versionFunctions<QOpenGLFunctions_3_0>();
funcs_->initializeOpenGLFunctions();
renderer_.init(funcs_);
To copy to clipboard, switch view to plain text mode
Where renderer_ is of type Renderer which just calls OpenGL functions through the funcs_ pointer and sets up all the shaders and VBOs and buffers and so forth.
Then in paintGL() I basically just do:
renderer_.render();
renderer_.render();
To copy to clipboard, switch view to plain text mode
Where render() just calls glClearColor(), glClear() and then glDrawArrays(). This works when the window is created. Notice that I am NOT swapping the buffers anywhere in my code. With GLFW I called glfwSwapBuffers() at the end of render() and that worked.
However now when I try to reimplement zoom (that was working with GLFW) where I change a uniform variable in a shader the OpenGL scene does not change at all. After changing the projection matrix in a wheelEvent() function within RendererWidget I call update() (I also tried calling paintGL() directly) which then in turn schedules a call to paintGL(). I have verified that paintGL() gets called after each wheelEvent() but the scene does not change.
I tried doing:
context_->swapBuffers(context_->surface());
context_->swapBuffers(context_->surface());
To copy to clipboard, switch view to plain text mode
After renderer_.render() in paintGL() but this sounds... Somehow wrong (why give the contexts own QSurface back to it?) but this is the only function I could find that is related to swapping buffers.
What am I doing wrong? Who is supposed to swap the buffers after rendering in paintGL()? The docs say "Before invoking this function, the context and the framebuffer are bound, and the viewport is set up by a call to glViewport(). No other state is set and no clearing or drawing is performed by the framework." but then why does it draw the scene when the window is created? How do I swap the buffers with Qt? What else do I need to do to actually swap buffers and/or display changes after rendering in paintGL()? Thanks for the help!
Edit: Solved it, you do not need to explicitly call swapBuffers() or anything. The problem was that I was calling the glUniform() function from an event handler function where the OpenGL context is NOT set thus it had no effect. Changed it to be called in the paintGL() function and everything works now.
Bookmarks