Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QOpenGlWidget: usage of native opengl code and QPainter class

QOpenGlWidget: usage of native opengl code and QPainter class

Scheduled Pinned Locked Moved General and Desktop
qopenglwidgetqpainteropenglglshaders
2 Posts 1 Posters 2.6k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    D Offline
    dunaj
    wrote on 13 Apr 2015, 08:32 last edited by
    #1

    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!

    1 Reply Last reply
    0
    • D Offline
      D Offline
      dunaj
      wrote on 14 Apr 2015, 13:51 last edited by dunaj
      #2

      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

      1 Reply Last reply
      0

      2/2

      14 Apr 2015, 13:51

      • Login

      • Login or register to search.
      2 out of 2
      • First post
        2/2
        Last post
      0
      • Categories
      • Recent
      • Tags
      • Popular
      • Users
      • Groups
      • Search
      • Get Qt Extensions
      • Unsolved