QPainter changes the rendering of OpenGLWidget
-
wrote on 18 Nov 2015, 11:09 last edited by
Hello everyone! I have encountered a strange problem with a QOpenGLWidget when trying to paint some rectangle box with text over it with QPainter. I have the following code to draw the opengl geometry:
void GLWidgetGeometry::initializeGL()
{initializeOpenGLFunctions(); glClearColor(0.0, 0.0, 0.0, 1.0); // connect shader to the source files if (!shaderProgram_.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/vshader.glsl")) close(); if (!shaderProgram_.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/fshader.glsl")) close(); if (!shaderProgram_.link()) close(); glEnable(GL_DEPTH_TEST); // important to keep for realistic output of rays on the foreground of the texture //glDisable(GL_DEPTH_TEST); // to see transparent back faces glDisable(GL_CULL_FACE); //glShadeModel(GL_SMOOTH); // not available in windows qt version //glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // transparency glEnable(GL_BLEND); // blending of alpha-colors of surfaces in the system with the background glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //glBlendFunc(GL_ONE, GL_ONE); // initial position rotation_ = QQuaternion::fromAxisAndAngle(QVector3D(1, 0, 0), -90) * rotation_; rotation_ = QQuaternion::fromAxisAndAngle(QVector3D(0, 1, 0), 30) * rotation_;
}
void GLWidgetGeometry::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Calculate model view transformation (camera moves, but not object itself)QMatrix4x4 matrix, viewMatrix; viewMatrix.lookAt(QVector3D(0, 0, 1.0), QVector3D(0, 0, 0), QVector3D(0, 1, 0)); viewMatrix.translate(translation_); viewMatrix.rotate(rotation_); // in the future use scaling factor provided by ray tracer viewMatrix(2, 3) -= 5.0f * exp(distanceExp_ / 1200.0f); // scaling the view //double scaling = rayTracer_->scalingFactor(); viewMatrix.scale(rayTracer_->scalingFactor()); shaderProgram_.bind(); // Set modelview-projection matrix shaderProgram_.setUniformValue("mvp_matrix", projection_*viewMatrix*matrix); shaderProgram_.setUniformValue("mv_matrix", viewMatrix*matrix); shaderProgram_.setUniformValue("normal_matrix", (viewMatrix*matrix).normalMatrix()); shaderProgram_.setUniformValue("lightPosition", QMatrix4x4((viewMatrix*matrix).normalMatrix())*QVector3D(1.0, 1.0, 1.0).normalized()); shaderProgram_.setUniformValue("lightIntensity", QVector3D(5.0, 5.0, 5.0)); rayTracer_->draw(shaderProgram_); shaderProgram_.release(); drawLegend(title_) ; // without this everything works perfect!
}
So when I am just draw geometry with opengl and shader call everything looks great, once I call drawLegend function with QPainter everything becomes ugly.
void GLWidgetGeometry::drawLegend(const QString& text)
{
QPainter painter; // to draw a legendpainter.begin(this); painter.setRenderHint(QPainter::TextAntialiasing); QFont font = painter.font(); // enlarged the text font.setPixelSize(14); font.setBold(true); painter.setFont(font); QFontMetrics metrics = QFontMetrics(font); int border = qMax(4, metrics.leading()); QRect rect = metrics.boundingRect(0, 0, width() - 2*border, height()/4, Qt::AlignLeft | Qt::TextWordWrap, text); painter.setRenderHint(QPainter::TextAntialiasing); QPen pen = painter.pen(); pen.setWidth(2); pen.setColor(QColor(255, 255, 255, 200)); painter.setPen(pen); QRect rectText(0, 0, rect.width() + 4*border, rect.height() + 4*border); painter.setBrush(QColor(38, 181, 242, 120)); painter.drawRect(rectText); painter.drawText(rectText.x() + 2*border, rectText.y(), rectText.width(), rectText.height(), Qt::AlignLeft | Qt::AlignVCenter | Qt::TextWordWrap, text); painter.end();
}
Picture before adding QPainter draw
Picture after adding QPainter draw -
wrote on 20 Nov 2015, 13:19 last edited by
The solution of the problem was, that after using QPainter the OPenGL state was lost, so all the glEnable() were ignored and therefore the depth test as well, so I put again all the glEnable calls after QPainter call and it works well.
-
Hi and welcome to devnet,
IIRC when you want to mix both, you need to enclose your OpenGL primitives call between
painter-> beginNativePainting()
andpainter->endNativePainting()
Hope it helps
3/3