QOpenGlWidget: usage of native opengl code and QPainter class



  • Hello everyone!
    I am preparing a desktop application to draw some 2D plots. I am using C++: Qt 5 and visual studio 2013. I created a simple GUI and put myQOpenGLWidget in it. I am already drawing the plots, axes and ticks using my own openGl shaders. Everything works fine and now I want to add the description to my axes and ticks to make the graph possible to analysis. As in OpenGL itself there is no dedicated functions to render text, I came up with using QPainter object just to add the desired description to already created plot. And here are problems starting...

    Here is my functions of my QopenGLWidget implementation:

    void GLWidget::initializeGL() {
    	initializeOpenGLFunctions();
    	glEnable(GL_POINT_SPRITE);
    	glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
    	glEnable(GL_BLEND);
    	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    
    	vertexShad = new QOpenGLShader(QOpenGLShader::Vertex);
    	fragmentShad = new QOpenGLShader(QOpenGLShader::Fragment);
    
    	bool flag = vertexShad->compileSourceFile(QString("vs.glsl"));
    	if (flag) printf("compiled vertex Shader\n");
    	flag = fragmentShad->compileSourceFile(QString("fs.glsl"));
    	if (flag) printf("compiled fragment Shader\n");
    	flag = program.addShader(vertexShad);
    	if (flag) printf("linked vertex Shader\n");
    	flag = false;
    	flag =program.addShader(fragmentShad);
    	if (flag) printf("linked fragment Shader\n");
    
    	program.link();
    	program.bind();
    }
    

    paintGL:

    void GLWidget::paintGL() {
    	glViewport(0, 0, this->width(), this->height());
    	glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
    	glClear(GL_COLOR_BUFFER_BIT);
    	drawAxes();
    	glViewport(MARGIN, MARGIN, this->width() - MARGIN * 2, this->height() - MARGIN * 2);
    	glScissor(MARGIN, MARGIN, this->width() - MARGIN * 2, this->height() - MARGIN * 2);
    	glEnable(GL_SCISSOR_TEST);
    	// functions that uses openGL native code
           // ....
    //
    // labels description:
    	QPainter painter(this);
    	char * maxText = new char[4];
    	sprintf(maxText, "%d", maxY);
    	char * minText = new char[4];
    	sprintf(minText, "%d", minY);
    	painter.drawText(0, MARGIN, QString(maxText));
    	painter.drawText(0, height() - MARGIN, QString(minText));
    	painter.drawText(MARGIN, height() - MARGIN + 20, QString("0"));
    	painter.drawText(width() - MARGIN, height() - MARGIN + 20, QString(100));
    	update();
    	painter.end();
    }
    

    Unfortunately, when I run the code, with uncommented QPainter part, the axis and plots are cleared, only the numbers I paint with QPainter are shown. Any suggestions how I can add the text with QPainter to my plot instead of clearing it?

    Thank you for any comments!



  • I finally managed to get things work.

    First of all, I had to change and set the format (you have to change it before widget is shown), for example in main function , before my app was shown:
    main:

    int main(int argc, char *argv[])
    {
    	QApplication a(argc, argv);
    
    	SymmGaitModels w;
           // GLWidget is my implemantation of QOpenGLWidget
    	GLWidget* gl = w.findChild<GLWidget*>("OpenGLWidget");
    	QSurfaceFormat  format;
    	//format.setSamples(4);
    	//format.setDepthBufferSize(24);
    	//format.setStencilBufferSize(8);
    	format.setProfile(QSurfaceFormat::OpenGLContextProfile::CompatibilityProfile);
    	QSurfaceFormat::setDefaultFormat(format);
    	
    	gl->setFormat(format);
    	w.show();
    	return a.exec();
    }
    

    Moreover, I had to move all (even enabling and disabling things like blend, point_sprite etc, which caused my problems) of my openGL functions between

    QPainter-> beginNativePainting()
    ...
    QPainter->endNativePainting();
    

    And I had to implement paintEvent function. I just put paintGL() expression there.
    Now my functions look like that:

    void GLWidget::initializeGL() {
    	printf("autoFILL: %d\n",this->autoFillBackground());
    	initializeOpenGLFunctions(); // this function has to stay in initializeGL
    	// commented functions below has to be removed and put after beginNativePainting
            //glEnable(GL_POINT_SPRITE);
    	//glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
    	//glEnable(GL_BLEND);
    	//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
           
           // shaders may be compiled and added here, but program has to be linked and built after beginNativePainting()
    	vertexShad = new QOpenGLShader(QOpenGLShader::Vertex);
    	fragmentShad = new QOpenGLShader(QOpenGLShader::Fragment);
    
    	bool flag = vertexShad->compileSourceFile(QString("vs.glsl"));
    	//bool flag = vertexShad->compileSourceCode(vertexShadSrc);
    	if (flag) printf("compiled vertex Shader\n");
    	flag = fragmentShad->compileSourceFile(QString("fs.glsl"));
    	//flag = fragmentShad->compileSourceCode(fragmentShadSrc);
    	if (flag) printf("compiled fragment Shader\n");
    	flag = program.addShader(vertexShad);
    	if (flag) printf("linked vertex Shader\n");
    	flag = false;
    	flag =program.addShader(fragmentShad);
    	if (flag) printf("linked fragment Shader\n");
    }
    
    void GLWidget::paintEvent(QPaintEvent *e) {
    	paintGL(); // still this, widget has to be now refreshed by widget->update()
    }
    
    void GLWidget::paintGL() {
    	painter = new QPainter(this);
    	painter->beginNativePainting();
    	//
    	glEnable(GL_POINT_SPRITE);
    	glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
    	glEnable(GL_BLEND);
    	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    
    	program.link();
    	program.bind();
    	//
    	glViewport(0, 0, this->width(), this->height());
    	glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
    	glClear(GL_COLOR_BUFFER_BIT);
    	drawAxes();
    	glViewport(MARGIN, MARGIN, this->width() - MARGIN * 2, this->height() - MARGIN * 2);
    	glScissor(MARGIN, MARGIN, this->width() - MARGIN * 2, this->height() - MARGIN * 2);
    	glEnable(GL_SCISSOR_TEST);
    	// functions using native openGL functions here
            //  .....
            //
    	glDisable(GL_SCISSOR_TEST);
    	glDisable(GL_POINT_SPRITE);
    	glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
    	glDisable(GL_BLEND);
    	program.disconnect();
    	painter->endNativePainting();
    	drawTicksValues();
    	painter->end();
    }
    

    After adding paintEvent implementation, the openGL widget has to be now refreshed using widget->update().

    Hope it will be helpful for other people who are struggling with using both QPainter and native openGL functions, as Qt doc seems to be a little shallow on this topic.

    Thanks!
    Adam



Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.