0

When inheriting from QOpenGLWidget and QOpenGLFunctions_4_5_Core, if I call glActiveTexture(GL_TEXTURE1) (or any other non-zero number) before calling update() textures appear completely black on the screen.

Relevant code snippets:

void OpenGLWidget::paintGL() {
    if (fp) {
        // First paint seems to always happen before the first update
        qDebug() << "First Paint";
        fp = false;
    }
    glClear(GL_COLOR_BUFFER_BIT);

    unsigned int tex;
    glGenTextures(1, &tex);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, tex);

    QImage img = QImage("textures/awesomeface.png").convertToFormat(QImage::Format_RGBA8888).mirrored();
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.width(), img.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());

    glTextureParameteri(tex, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTextureParameteri(tex, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTextureParameteri(tex, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTextureParameteri(tex, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

    glUseProgram(frame_shader.get_id());

    glBindVertexArray(frame_vao);
    glDrawArrays(GL_TRIANGLES, 0, 6);

    // Clean up
    glDeleteTextures(1, &tex);
    glBindTexture(GL_TEXTURE_2D, 0);
    glBindVertexArray(0);

    // This doesn't cause the textures to be black
    glActiveTexture(GL_TEXTURE1);
}

And the mainloop function:

void OpenGLWidget::main_loop() {
    if (fu) {
        qDebug() << "First Update";
        fu = false;
    }

    // This causes the textures to completely black
    // Change GL_TEXTURE1 to GL_TEXTURE0 (or get rid of it glActiveTexture
    // completely) and textures will work once again
    glActiveTexture(GL_TEXTURE1);
    update();
}

The shaders can still draw to the screen; if I set a solid color in the fragment shader, the color will properly display to the screen. It seems only user-made textures are turning completely black.

I'm not getting any OpenGL Errors.

The full MRE can be found at: https://github.com/Luminic/MRE_QOpenGLWidget_glActiveTexture_GL_TEXTURE1_before_update

Does anyone know what is causing this odd behavior?

Lucas
  • 55
  • 1
  • 5
  • 1
    what you do is undefined behavior here, quoting the doc for QtOpenGLWidget: "Your widget's OpenGL rendering context is made current when `paintGL()`, `resizeGL()`, or `initializeGL()` is called. If you need to call the standard OpenGL API functions from other places (e.g. in your widget's constructor or in your own paint functions), you must call `makeCurrent()` first." Not sure how this would create the effect observed here, but keep in minfd that QT keeps a render-to-texture mechanism under the hood for rendering to the window, and you might screw up some things there. – derhass Jul 19 '20 at 16:56

1 Answers1

0

Why is this supposed to be weird behaviour? It is completely reasonable that telling OpenGL to use the Texture Unit 1 of your hardware only draws black content, because in your code you do not have a texture attached to that unit. The glActiveTexture(GL_TEXTURE1) command sets the active texture unit to 1. Before you created the texture, you bound unit 0, so the texture lives there. Not setting this parameter at all is the same as setting it to 0, as this is the default unit. Calling glBindTexture after the glActiveTexture would resolve your problem too!

DKolter
  • 21
  • 3
  • In paintGL I'm setting `glActiveTexture(GL_TEXTURE0)` and in the framebuffer I'm drawing the texture at binding point 0 so `glActiveTexture(GL_TEXTURE1)` shouldn't have an effect. Additionally, if I bind the image to `GL_TEXTURE1` and draw the texture at binding point 1 in the framebuffer the texture still comes up as black. – Lucas Jul 18 '20 at 19:24
  • Is this paintGL function only called once or are you reloading the texture every frame? It would also be useful to check the value of tex, to see if it is valid. – DKolter Jul 18 '20 at 19:54
  • `update` indirectly calls `paintGL` through Qt. I can't directly call `paintGL` or the framebuffer won't be bound. `main_loop()` is being called every frame so `paintGL` is too. The texture is a valid texture when i check the id. I know creating and then deleting a texture every frame isn't the best idea, but its just to show the odd behavior. If i created the texture in initializeGL and just drew it every frame this same behavior happens. – Lucas Jul 18 '20 at 20:02