Loading 3D model from DAE COLLADA using Qt 6. OpenGL lighting works incorrectly on Android and WebAssembly
-
Hello,
I wrote an example that loads 3D model from DAE COLLADA using Qt 6. Source code: load-3d-model-from-dae-opengl-window-qt6-cpp.zip
OpenGL lighting works correctly on Desktop but incorrectly on Android and WebAssembly:
Android:
WebAssembly:
Vertex shader:
attribute vec4 aPosition; attribute vec4 aNormal; attribute vec2 aTexCoord; uniform mat4 uMvpMatrix; uniform mat4 uModelMatrix; uniform mat4 uNormalMatrix; varying vec3 vPosition; varying vec3 vNormal; varying vec2 vTexCoord; void main() { gl_Position = uMvpMatrix * aPosition; vPosition = vec3(uModelMatrix * aPosition); vNormal = normalize(vec3(uNormalMatrix * aNormal)); vTexCoord = aTexCoord; }
Fragment shader:
#ifdef GL_ES precision mediump float; #endif const vec3 lightColor = vec3(0.8, 0.8, 0.8); const vec3 ambientLight = vec3(0.3, 0.3, 0.3); uniform sampler2D uSampler; uniform vec3 uLightPosition; varying vec3 vPosition; varying vec3 vNormal; varying vec2 vTexCoord; void main() { vec4 color = texture2D(uSampler, vTexCoord); vec3 normal = normalize(vNormal); vec3 lightDirection = normalize(uLightPosition - vPosition); float nDotL = max(dot(lightDirection, normal), 0.0); vec3 diffuse = lightColor * color.rgb * nDotL; vec3 ambient = ambientLight * color.rgb; gl_FragColor = vec4(diffuse + ambient, color.a); }
Cross-refs:
-
I tried to set a depth buffer size to 24:
OpenGLWindow::OpenGLWindow() { setTitle("OpenGL ES 2.0, Qt6, C++"); resize(350, 350); QSurfaceFormat surfaceFormat; surfaceFormat.setDepthBufferSize(24); setFormat(surfaceFormat); }
It works on WebAssembly at least from Windows 10, 64-bit: https://65d340535ef3fa042a6d1ce3--charming-malabi-d8d124.netlify.app/
And on Redmi 4X, Android 7:
-
I added this line of code
glEnable(GL_CULL_FACE);
toOpenGLWindow::initializeGL()
. The problem was solved for a cube on Android:and WebAssembly:
When I change a model with Mario it works on Desktop:
But it doesn't work for Android:
and WebAssembly:
Source code: load-3d-model-from-dae-opengl-window-qt6-cpp.zip
I created the bug report: https://bugreports.qt.io/browse/QTBUG-122145
-
I tried to set a depth buffer size to 24:
OpenGLWindow::OpenGLWindow() { setTitle("OpenGL ES 2.0, Qt6, C++"); resize(350, 350); QSurfaceFormat surfaceFormat; surfaceFormat.setDepthBufferSize(24); setFormat(surfaceFormat); }
It works on WebAssembly at least from Windows 10, 64-bit: https://65d340535ef3fa042a6d1ce3--charming-malabi-d8d124.netlify.app/
And on Redmi 4X, Android 7:
-
-
Pro tip,
always and I mean always be very specific with your Context attributes and with your OpenGL state.
With ES2/ES3 the context state is manageable it gets bigger with the desktop GL unfortunately but I really recommend to always be very explicit with your state setting in the beginning.
So for every draw you make, make sure you enable/disable set every state your current draw requires. that means your blending, your stencil, depth test, face culling etc.
When everything works and you've encoded all this in your rendering code then you can very carefully start omitting redundant state sets.
Incorrect state is a major source of OpenGL bugs.
And to make everything what I said above easier, if you're writing your own engine type of thing you really want to accumulate as much state as possible, associate all that with your draw so that your draw takes your geometry, program, state objects and then does as much as possible to make sure the state is exactly what you need and the state that isn't mentioned in your application state is set to a known OpenGL state. For example if your draw doesn't use depth testing then you really want to mention in your code that your depth testing is disabled instead of relying on any implied "default" state in the driver.
Example
https://github.com/ensisoft/detonator/blob/master/device/opengles.cpp#L732