qtopenglqpainterqopenglwidget

Objects are transparent when using QPainter


So I've tried to put labels on my objects. I tried out a test example to just put one simple label there. When I ran the program, however, all the objects were somewhat transparent.

paintGL:

void mainWidget::paintGL(){
    QPainter painter(this);
    painter.beginNativePainting();
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

    glViewport(0, 0, width(), height());

    projection = camera->getProjectionMatrix(60.0f, width(), height(), 0.1f, 100.0f);
    vec3 cameraPos(camera->getPosition());
    view = camera->getViewMatrix();

    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
    if (isLine)
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    shaderProgram->bind();
    shaderProgram->setUniformValue("Light.ambient", 0.1f);
    shaderProgram->setUniformValue("Light.position", QVector3D(ld[0], ld[1], ld[2]));
    model = mat4(1.0f);
    model = glm::translate(model, modelOrigin + cubePosModel);
    setRotModel(cubeRotModel);
    setMatrices(shaderProgram, true);
    shaderProgram->setUniformValue("viewPosition", QVector3D(cameraPos[0], cameraPos[1], cameraPos[2]));

    if (showCube) 
        cubeMesh->render(shaderProgram);
    shaderProgram->release();
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    if (isLine)
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    view = camera->getViewMatrix();
    model = mat4(1.0f);
    model = glm::translate(model, modelOrigin + planePosModel);

    setRotModel(planeRotModel);
    shaderProgram->bind();
    setMatrices(shaderProgram, true);
    shaderProgram->setUniformValue("viewPosition", QVector3D(cameraPos[0], cameraPos[1], cameraPos[2]));
    if (showPlane)
        planeMesh->render(shaderProgram);
    shaderProgram->release();
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    if (isLine)
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    model = glm::mat4(1.0f);
    model = glm::translate(model, modelOrigin + teapotPosModel);
    setRotModel(teapotRotModel);

    shaderProgram->bind();
    setMatrices(shaderProgram, true);
    if (showTeapot)
        teapotMesh->render(shaderProgram);
    shaderProgram->release();
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

    model = glm::mat4(1.0f);
    model = glm::translate(model, modelOrigin + cubeLightPosModel);
    model = glm::scale(model, glm::vec3(0.3f));
    setRotModel(cubeLightRotModel);

    lightCubeProgram->bind();
    setMatrices(lightCubeProgram, false);
    if (showCubeLight)
        cubeMesh->render(lightCubeProgram);
    lightCubeProgram->release();
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

    axis_vao->bind();
    model = mat4(1.0f);
    model = glm::translate(model, modelOrigin);
    model = glm::scale(model, vec3(5.0f));
    model = glm::rotate(model, glm::radians(2.0f), vec3(1, 1, 0));
    drawAxisProgram->bind();
    glm::mat4 pvm = projection * view * model;
    drawAxisProgram->setUniformValue("mvpMatrix", QMatrix4x4(glm::value_ptr(pvm)).transposed());
    if (showGrid)
        glDrawArrays(GL_LINES, 0,  axisSize);
    axis_vao->release();
    drawAxisProgram->release();
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

    if (isLine)
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    model = mat4(1.0f);
    model = glm::translate(model, modelOrigin + vec3(0, 2, -1));
    shaderProgram->bind();
    setMatrices(shaderProgram, true);
    if (showSphere)
        sphereMesh->render(shaderProgram);
    shaderProgram->release();
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

    painter.endNativePainting();
    painter.setPen(Qt::yellow);
    painter.setFont(QFont("Helvetica", 8));
    painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
    painter.drawText(200, 400, "Scene Maker"); // z = pointT4.z + distOverOp / 4
    painter.end();
}

I don't know why, but it was the only object that was transparent. Also, the addition of the QPainter messesd something up with the lid of the teapot. Perhaps it's related to the glPolygonMode messy stuff going on?

In case it was QPainter sneakily disabling GL_DEPTH_TEST, which seemed to be the case, I re-enabled it afterwards, but it still didn't work.

mainWidget is a QOpenGLWidget.

So, what is the problem? Pic:

enter image description here

(As you can see, the grid lines show through the teapot, but the cube doesn't, making it not fully transparent. )

Edit: I found out that all the other objects were transparent too.


Solution

  • Your depth test is disabled or your context doesn't have a depth buffer. First make sure that you set a pixel format with depth buffer during initialization. QOpenGLWidget documentation has an example of that:

    QOpenGLWidget *widget = new QOpenGLWidget(parent);
    QSurfaceFormat format;
    format.setDepthBufferSize(24); // <--- this is what you need
    format.setStencilBufferSize(8);
    format.setVersion(3, 2);
    format.setProfile(QSurfaceFormat::CoreProfile);
    widget->setFormat(format); // must be called before the widget or its parent window gets shown
    

    Next enable depth test in your drawing code with:

    glEnable(GL_DEPTH_TEST);