Important: Please read the Qt Code of Conduct -

Weird OpenGL State Issues with QOpenGLWidget

  • I've got my QOpenGLWidget subclass, known as RenderWidget, setup. I've also got some simple stuff rendering to the screen with minimal effort. I'm using GLEW to obtain a modern OpenGL profile since Qt's provided alternative to GLEW is to also have RenderWidget derive from QOpenGLFunctions. This class provides functions, rather "methods" in the scope of my RenderWidget class only, and of course, I must call initializeGLFunctions(). I'm not if initializeGLFunctions() actually creates a new context, or somehow links the class implementation's gl* methods to the currently-bound an OpenGL context under the hood. Either way, it appears that if I want to use OpenGL outside of RenderWidget, I have to always create a class that inherits from QOpenGLFunctions. This means I can't have my boilerplate stuff residing in global scope. So, I'm using GLEW...

    Also, I've noticed that I can't make any state changes outside of the paintGL() method. For example, if my reimplemented keyboard or mouse events fire, it appears that I can create OpenGL resources, but I can't change OpenGL state, such as switching bound textures, buffers, etc. This led to hours of trying to solve this VAO issue I was having until I realized that I basically have to set flags (bools) inside my event methods that'd meet conditions in my paintGL() method to do whatever I need done OpenGL-wise. Is this due to using GLEW as opposed to QOpenGLFunctions, a Qt bug, or is this intended behavior?

    The next thing I've noticed is that my currently-bound texture unit unbinds itself or something whenever I resize my window. In other words, if I'm drawing stuff to the screen that uses a texture bound to GL_TEXTURE0, then whatever uses that texture becomes black once RenderWidget resizes. It's only the currently-bound texture because I'll have a normal mapped quad rendering to the screen, and the normal map won't affect the lighting anymore once I resize the window as it was the last texture to be bound when I initialized that test state.

    I've come to two workarounds:

    1. Call glActiveTexture() constantly every frame. This is slow, and there are many cases where glActiveTexture() can be optimized out from being called repeatedly where this resize issue isn't present (for example, a GLUT or GLFW application).

    2. Just call glActiveTexture(), and bind to an unused texture unit. Then, whatever happening under the hood when a resize event is fired will unbind the active texture unit's texture that never had any use to begin with.

    I went with solution 2, but has anyone ran into this before? Are there any other things I should watch out for?

Log in to reply