[Solved] Qt5: mixing OpenGL and QML
-
Hello!
Note before reading the post: the last time I've written OpenGL code was about 10years ago so my knowledge is minimal at best.
I'm modifying Qt5's "openglunderqml" demo and as soon as I do not use the shader program but simply want to draw a quad using good old glBegin(GL_QUADS)... stuff, nothing renders. By "nothing renders" I mean that the native QML contents are there as expected, but the OpenGL stuff I'd expect to be seen underneath is not visible.
It seems I can try whatever I can imagine - rendering a QGLTeapot, a glutTeapot, glTranslating like crazy... glEnabling/Disabling stuff, nothing works...
Since the example works just fine and my code does not, I expect some OpenGL state to be wrong, I just have no idea what to set. Here's my non-working code:
@
void Squircle::paintQuad()
{//[1] taken from Qt's sources, makes no difference if this is there
#if defined(QT_OPENGL_ES)
glClearDepthf(1);
#else
glClearDepth(1);
#endif
glDepthMask(GL_TRUE);
#if defined(QT_OPENGL_ES)
glDepthRangef(0.0f, 1.0f);
#else
glDepthRange(0.0f, 1.0f);
#endif
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);
//[1]//[2] wooden-hammer, yep, I'm desperate. Again: makes no difference
glShadeModel(GL_SMOOTH);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_MULTISAMPLE);
static GLfloat lightPosition[4] = { 0.5, 5.0, 7.0, 1.0 };
glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
//[2]glViewport(0, 0, window()->width(), window()->height()); glLoadIdentity(); //the z-coordinate in this transform varies between -10.0 and 10-0 glTranslatef(0.0,0.0,10.0-m_t*20.0); glClearColor(0, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT); GLfloat faceColor[4]={0.5,0.0,1.0,1.0}; glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, faceColor); glBegin(GL_QUADS); glVertex2f(-1.0, -1.0); glVertex2f(1.0, -1.0); glVertex2f(1.0, 1.0); glVertex2f(-1.0, 1.0); glEnd();
}
@...and yes, I've also tried with disabling GL_CULL_FACE. Variations of this code also included disabling GL_DEPTH_TEST, using glVertex3f and playing with the z-coordinate.
I also tried rendering a teapot using mostly Qt-only stuff:
@
void Squircle::paintTeapot()
{glViewport(0, 0, window()->width(), window()->height()); QGLPainter painter; painter.begin();
#if defined(QT_OPENGL_ES)
glClearDepthf(1);
#else
glClearDepth(1);
#endif
glDepthMask(GL_TRUE);
#if defined(QT_OPENGL_ES)
glDepthRangef(0.0f, 1.0f);
#else
glDepthRange(0.0f, 1.0f);
#endif
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);QColor clearColor(Qt::black); painter.setClearColor(clearColor); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); QGLBuilder builder; builder<<QGLTeapot(); QGLSceneNode* teapot=builder.finalizedSceneNode(); painter.modelViewMatrix().scale(m_t); teapot->draw(&painter);
}
@where m_t varies between 0.0 and 1.0 and the same comments about the glClearDepth-stuff apply as in the paintQuad() function.
Both functions were connected to QQuickWindow's beforeRendering() slot, NOT at the same time, of course - either the one or the other.
Any hint on how/whether I need to change OpenGL's state to make this simple example work would be appreciated.
edit Additional notes: yes, the slots are called, as checked with gdb. And the scene is cleared to the color configured in the functions. And nothing in the openglunderqml example has been modified, just these slots added and the call to connect these slots of course.
Thanks!
-
Just for info if someone hits the same problem:
The solution is to call QOpenGLFunctions::glUseProgram(0), i.e.:
@
//somewhere, only once:
QOpenGLFunctions *m_oglFunctions=new QOpenGLFunctions(QOpenGLContext::currentContext());
m_oglFunctions->initializeOpenGLFunctions();//everytime before doing anything OpenGL:
m_oglFunctions->glUseProgram(0);@prior to doing anything OpenGL. I have no idea why and whether this is a bug in Qt5 or not, but it works :)
-
The glUseProgram(0) call tells OpenGL to bind the built-in vertex/fragement shader combo that implements the old fixed function pipeline (the glLight and glMaterial calls you're making). Nowdays people usually write their own shaders so I guess Qt is assuming that you would simply bind your own shader program before rendering.