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 _______________________________________________ Interest mailing list [email protected] http://lists.qt-project.org/mailman/listinfo/interest
