Blending challenges mixing QOpenGLWidget and QPainter



  • Hey everyone. I've been having some trouble mixing native OpenGL rendering with QPainter. My current use case involves rendering QPainter text (and other primitives) after all OpenGL rendering has completed, but I could imagine wanting to mix the two in the future as well.

    My problem is that my OpenGL rendering no longer appears if I render any text with QPainter. I don't have issues with other QPainter primitives - just text.

    I've created a simple dummy example (with legacy OpenGL calls) below to illustrate my issue. It's supposed to draw a triangle with a few QPainter primitives on top, but I only see the QPainter primitives. The issue seems to be with blending. If I comment out the GL_BLEND enable (or set glBlendFunc to GL_ONE,GL_ZERO), then everything displays correctly.

    Any help would be appreciated - I've been pulling my hair out on this one. In my actual app, everything works correctly as long as the first frame I render includes QPainter calls. If I delayed QPainter rendering (eg. enabled via a toggle), then my GL render would disappear. Luckily, this dummy example fails more predictably.

    Lastly: Should I even bother with mixing the two? I could alternatively create a child widget spanning my viewport and let Qt do the composition. I've been assuming that approach could be a performance bottleneck, but perhaps I'm off base.

    Thanks!

    ////////////////////////////////////////////////////////////////////////////////
    
    class MyWidget : public QOpenGLWidget
    {
    public:
    
    	void initializeGL() override
    	{
    		Functions = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_2_Compatibility>();
    	}
    
    	void paintGL() override
    	{
    		QPainter painter(this);
    		painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
    		painter.beginNativePainting();
    
    		Functions->glPushAttrib(GL_ALL_ATTRIB_BITS);
    
    		Functions->glClearColor(0.5f, 0.5f, 0.5f, 0.0f);
    		Functions->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    		// Set render state
    		Functions->glEnable(GL_DEPTH_TEST);
    		Functions->glDisable(GL_CULL_FACE);
    		Functions->glEnable(GL_BLEND);
    		Functions->glEnable(GL_TEXTURE_2D);
    		Functions->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    
    		Functions->glBegin(GL_TRIANGLES);
    
    		Functions->glColor4ub(255, 255, 255, 128);
    		Functions->glVertex3f(-.25f, -.25f, 0.0f);
    		Functions->glColor4ub(255, 255, 255, 128);
    		Functions->glVertex3f(.25f, -.25f, 0.0f);
    		Functions->glColor4ub(255, 255, 255, 128);
    		Functions->glVertex3f(0.0f, .25f, 0.0f);
    
    		Functions->glEnd();
    
    		Functions->glPopAttrib();
    
    		painter.endNativePainting();
    
    		QFont font("Helvetica", 30, QFont::Bold, true);
    		painter.setPen(Qt::red);
    		painter.setFont(font);
    		painter.drawText(50, 50, "Text here.");
    		painter.setPen(QPen(Qt::green, 5, Qt::DashLine, Qt::RoundCap));
    		painter.drawEllipse(90, 90, 80, 80);
    		painter.end();
    
    		update();
    	}
    	
    private:
    	QOpenGLFunctions_3_2_Compatibility* Functions;
    };
    
    ////////////////////////////////////////////////////////////////////////////////
    
    int Main(int argc, char** argv) {
    	QSurfaceFormat defaultSurfaceFormat;
    	defaultSurfaceFormat.setVersion(3, 2);
    	defaultSurfaceFormat.setProfile(QSurfaceFormat::CompatibilityProfile);
    	defaultSurfaceFormat.setDepthBufferSize(24);
    	defaultSurfaceFormat.setStencilBufferSize(8);
    	defaultSurfaceFormat.setSamples(8);
    	QSurfaceFormat::setDefaultFormat(defaultSurfaceFormat);
    
    	QApplication app(argc, argv);
    
    	app.setAttribute(Qt::AA_ShareOpenGLContexts, true);
    
    	MyWidget widget;
    
    	widget.show();
    	return app.exec();
    }
    

Log in to reply
 

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