Trying tutorial43 in ogldev.org it builds and runs fine except for an error message I get when I close the window, this is shown in image 1.
As can be seen in the image I printed out the texture units used the sampler2d and samplerCube and they are indeed different. The top of the trace output is shown in image3.
The correct image is as in image 2 produced by the program.
However, there’s no proper GL state setup before this call to glValidateProgram() to put the context in a reasonable state to validate or render with this shader program. That’s likely the problem here.
Evidence to support this is the prefix on that error message you quoted above.
Invalid shader program: active samplers with a different type refer to the same texture image unit
That’s the same prefix used to log error validation errors after glValidateProgram() is called:
However, the font shader source code doesn’t make use of more than 1 sampler uniform. So it’s vindicated.
So the cause of the validation error seems to be the lack of proper GL state setup prior to calling glValidateProgram() for the tutorial43 LightingTechnique shader program making use of the lighting.fs fragment shader. Specifically, the sampler uniform values for gColorMap and gShaderMap likely need to be setup properly first (glGetUniformLocation() + glUniform1i()) so that their texture image unit indices are distinct.
Just adding layout ( binding = 0 ) and layout ( binding = 1 ) in the fragment shader before the uniforms of sampler2D and samplerCube got rid of the error message. Thanks a lot for your expertise. I know this is the easy way out, will try to trace and set up the state correctly before glValidateProgram get called…
Adding explicit layout qualifiers is generally preferred in modern OpenGL, and enables greater code robustness as a tradeoff vs flexibility you probably don’t need.
Another robustness “trick” I generally use is to always bind different texture types to different texture units. OpenGL has well-defined rules for how all this works if you use the same texture unit, but using different texture units means that one part of my code becomes less dependent on what might be going on in other parts of it.
Once again: it’s easy, it’s lazy, but my code is simpler, each module is more robust against unwanted side-effects, and I get to spend more time writing new code than I spend debugging existing code.