The correspondence between sampler uniforms and texture units used by glActiveTexture
apparently can\'t be queried with opengl, and I can\'t find good documentation
Here is what I have been able to find:
- If there is only sampler uniform in a program, then it is mapped to
gl_TEXTURE0
- If there are multiple sampler uniforms in a single program stage, then they are mapped in the order they are declared in the shader.
- If the vertex and fragment shaders have disjoint sets of sampler uniforms, then the samplers in the vertex shader come first and are followed by the samplers in the fragment shader.
- This behavior appears to be defined by the specification.
None of this is true. OK, the first one is true, but only by accident.
All uniform values which are not initialized in the shader are initialized to the value 0. The spec makes this quite clear:
Any uniform sampler or image variable declared without a binding qualifier is initially bound to unit zero.
A sampler uniform's value is the integer index of the texture unit it represents. So a value of 0 corresponds to GL_TEXTURE0
. All uninitialized sampler uniforms should have a value of 0.
If the behavior you describe is happening, then that implementation is in violation of the OpenGL specification.
Unless you use the layout(binding = )
syntax to assign a uniform's texture unit, you must manually in your OpenGL code assign each sampler uniform a value for its texture unit. This is done by setting its uniform value, just like any other integer uniform: you call glUniform1i
with the location corresponding to that uniform. So if you want to associate it with texture image unit index 4, you call glUniform1i(..., 4)
, where ...
is the uniform location for that uniform.
You have to set the index of the texture unit to sampler uniform (similar as setting the value of a uniform variable of type int
). e.g. value 1 for GL_TEXTURE1
.
See OpenGL 4.6 API Compatibility Profile Specification; 7.10 Samplers; page 154:
Samplers are special uniforms used in the OpenGL Shading Language to identify the texture object used for each texture lookup. The value of a sampler indicates the texture image unit being accessed. Setting a sampler’s value to
i
selects texture image unit numberi
.
e.g.
layout (location = 11) uniform sampler2D color;
layout (location = 12) uniform sampler2D tex;
layout (location = 13) uniform sampler2D norm;
glUniform1i(11, 0); // 0: GL_TEXTURE0
glUniform1i(12, 1); // 1: GL_TEXTURE1
glUniform1i(13, 2); // 2: GL_TEXTURE2
Since GLSL version 4.2 this can be done in the fragment shader by specifying binding points - See OpenGL Shading Language 4.20 Specification - 4.4.4 Opaque-Uniform Layout Qualifiers; page 60:
#version 420
layout (binding = 0) uniform sampler2D color;
layout (binding = 1) uniform sampler2D tex;
layout (binding = 2) uniform sampler2D norm;