[Interest] [Qt 5, OS X] Does OpenGL 3 Core Profile work (with Qt APIs)?

Till Oliver Knoll till.oliver.knoll at gmail.com
Thu Apr 18 09:09:28 CEST 2013


Hello,

I am having difficulties getting past the dreaded "black cube on black
background with no light and the camera turned 180 degrees"-scene while
trying to get back into OpenGL programming.

All with Qt 5.0.2 (binary distribution) on OS X 10.8.3 on an iMac 27"
2011, in short:

* QGLShaderProgram does not properly detect GL extensions
* Setting A 3.2 Core context with QGLFormat::setDefaultFormat does
  not work
* Setting a "Compatibility" 3.2 context does not work
* QOpenGLShaderProgram apparently fails to "setAttributeArray":
  -> GL_INVALID_OPERATION (?)
* My example code:

https://dl.dropboxusercontent.com/u/45335740/Link/valid_until_2013-06-01/coloring.zip



Here is the full story:

I tried to start with a simple "Colour Cube" example from the tutorial
found at [1] ((Btw: VERY nice tutorial! Thanks, Digia!).


So after unzipping the source [2] and compiling the "coloring" (we want
to go easy with an ol' OpenGL 1.2 veteran ;)) I got a disappointing

  QGLShader::compile(Vertex): ERROR: 0:1: '' :  version '130' is not
supported

message on the application output! But hold on: I am aware that my OS X
10.8.3 only supports OpenGL 3.2 (with some extensions which makes it
functionaly equivalent to about 3.3, or so I understand), but OpenGL 3.2
supports Shading Language version 1.50 (150)

(If you got initially confused like me about the mapping of Shading
Language and OpenGL version, here is the solution: from OpenGL 3.3
onwards the Shading Language version follows the OpenGL version - below
it had its own version numbering [3])


So reason was quickly fixed: if not specified otherwise an OpenGL 2.1
context is created by default (at least on a Mac), which only supports
Shading Language 1.20).


So my first fix:

  QGLFormat glFormat;
  glFormat.setVersion(3, 2);
  glFormat.setProfile(QGLFormat::CoreProfile);

  // Set the default GL format to OpenGL 3.2 Core
  QGLFormat::setDefaultFormat(glFormat);

  GlWidget w;
  w.show();

However that still failed: together with a debug line in
GLWidget::initializeGL:

  qDebug("OpenGL initialized: version: %s GLSL: %s",
glGetString(GL_VERSION), glGetString(GL_SHADING_LANGUAGE_VERSION));

I still get an old OpenGL 2.1 context:

  OpenGL initialized: version: 2.1 ATI-1.6.37 GLSL: 1.20


So my next attempt (it was actually my first attempt, but I figured out
QGLFormat::setDefaultFormat was less intrusive in the example code,
until I figured out that it doesn't work) was to pass along the
QGLFormat in the c'tor of QGLWidget, so that worked:

  OpenGL initialized: version: 3.2 ATI-1.6.37 GLSL: 1.50

However, trying to use the "Compatibility" profile with

  glFormat.setProfile(QGLFormat::CompatibilityProfile);

again failed and the resulting OpenGL context was an v2.1 again!


Anyway, with a valid OpenGL 3.2 Core context now available the example
now even crashed hard with an "EXC_BAD_ACCESS - Could not access memory"
at line

  shaderProgram.setUniformValue("mvpMatrix", pMatrix * vMatrix * mMatrix);

The application output quickly revealed the problem at hand:

  QGLShaderProgram: shader programs are not supported

A quick Google research came up with [4] which basically states that Qt
is using some deprecated glGetString(GL_EXTENSIONS) function call
(removed in OpenGL > 3.1 Core). I read somewhere that this had been
fixed in Qt 4.8 (can't find the reference anymore) and should hence also
be fixed in Qt 5. At least that does not seem to be true for
QGLShaderProgram!

Well then, QGLShaderProgram is deprecated in Qt 5, too (it should still
be fixed, IMHO). So next I tried with the new QOpenGLShaderProgram (from
module Qt GUI).

That brought me back to the "black cube on black background"-scene again
(no crash this time), but I still got

  QOpenGLShader::compile(Vertex): ERROR: 0:1: '' :  version '130' is not
supported
  ERROR: 0:2: '' :  #version required and missing.

  *** Problematic Vertex shader source code ***
  #version 130
  #define lowp
  #define mediump
  #define highp
  ...

Hmm, shouldn't OpenGL shader programs be backwards compatible? Anyway, I
simply bumped the #version to 150, re-ran the example code... and still
the black cube scene! But at least no errors or warnings on the
application output.

So I quickly borrowed the glCheckError() from [5] and added it after
several calls in paintGL(). And indeed:

  shaderProgram.bind();
  shaderProgram.setUniformValue("mvpMatrix", pMatrix * vMatrix * mMatrix);

still worked fine, but the next

  shaderProgram.setAttributeArray("vertex", vertices.constData());

triggered an GL_INVALID_OPERATION!

Investigating the shader program I found that the program expects 4
components for each vertex and colour:

  in vec4 vertex;
  in vec4 color;

however the passed data structure in 'vertices' is a QVector<QVector3D>,
that is 3 components only! I find this highly suspicious, but being an
OpenGL shader noob I am not sure whether either the Qt API will always
pass along 4 components (I don't see this documented anywhere, though!),
or whether the shader program itself magically figures out that it has
to fill the 4th missing component with some default value.

However looking at [5] and [6] they either expect a vec3 in the shader
and explicitly fill in the fourth component when passing the value to
the next shader stage ([5]) or they pass along the right amount of
vertex data from the very beginning ([6]).


So I tried the same approach as [5] by modifying my vertex shader:

  uniform mat4 mvpMatrix;

  in vec3 vertex;
  in vec3 color;

  out vec4 varyingColor;

  void main(void)
  {
    varyingColor = vec4(color, 1.0);
    gl_Position = mvpMatrix * vec4(vertex, 1.0);
  }


But still a black OpenGL scene and the GL_INVALID_OPERATION after
shaderProgram.setAttributeArray . This is as far as I got with that
example :(

For the interested, my application can be found here:


https://dl.dropboxusercontent.com/u/45335740/Link/valid_until_2013-06-01/coloring.zip

(I'll leave that link valid until at least 1st June 2013).

The *only* working example which makes use of an OpenGL 3.x Core context
so far is the one found in [5]! But interestingly the only "Qt OpenGL"
API being used seems to be the QGLWidget and QGLFormat, and nothing else
(coincidence?): so no Q(Open)GLShader or the like.


By the way, trying the Qt OpenGL examples:

  * Boxes - works (except that the transparent menu can't be initially
moved to the full extend of the initial window size - only after a
window resize - minor glitch)

  * Cube OpenGL ES 2.0 - works

  * Grabber - basically works, however "Render into Pixmap" does not
seem to have any effect (the right box is not updated with any pixmap)

  * Hello Qt - works

  * OpenGL Window Example - does not work: black screen, resizing the
window is *terribly* slow

  * Overpainting - works

  * Textures - works

None of the above examples uses shaders, I think, but for sure no OpenGL
3.2 Core context.


So is OpenGL 3.x Core actually supposed to work with Qt 5? Or is this
still work in progress?


Cheers,
  Oliver



[1]
http://releases.qt-project.org/learning/developerguides/qtopengltutorial/OpenGLTutorial.pdf

[2]
http://releases.qt-project.org/learning/developerguides/qtopengltutorial/opengl_src.zip

[3]
http://en.wikipedia.org/wiki/GLSL

[4]
http://qt-project.org/forums/viewthread/4856

[5]
http://blog.nobel-joergensen.com/2012/11/25/opengl-3-2-using-qt-4-8/

[6]
http://qt-project.org/wiki/How_to_use_OpenGL_Core_Profile_with_Qt



More information about the Interest mailing list