I have got a fragment shader that should operate 2 colors - red and blue.
#version 460 core
layout (location = 0) out vec4 outColor;
subroutine vec4 colorRedBlue();
subroutine (colorRedBlue)
vec4 redColor()
{
return vec4(1.0, 0.0, 0.0, 1.0);
}
subroutine (colorRedBlue)
vec4 blueColor()
{
return vec4(0.0, 0.0, 1.0, 1.0);
}
subroutine uniform colorRedBlue myRedBlueSelection;
void main()
{
outColor = myRedBlueSelection();
}
when I cout glGetSubroutineIndex(shaderProgram, GL_FRAGMENT_SHADER, "redColor");
and glGetSubroutineIndex(shaderProgram, GL_FRAGMENT_SHADER, "blueColor");
they are the same numbers: 4294967295
Why they are the same numbers? What did I do wrong?
If you want to retrieve information about the subroutine indices the you have to use glGetActiveSubroutineUniformiv
:
GLint no_of_subroutines;
glGetActiveSubroutineUniformiv(
shaderProgram, GL_FRAGMENT_SHADER,
0, // Index of the subroutine uniform, but NOT the location of the uniform variable
GL_NUM_COMPATIBLE_SUBROUTINES, &no_of_subroutines);
std::vector<GLint> sub_routines( no_of_subroutines );
glGetActiveSubroutineUniformiv(
shaderProgram, GL_FRAGMENT_SHADER,
0, // Index of the subroutine uniform, but NOT the location of the uniform variable
GL_COMPATIBLE_SUBROUTINES, sub_routines.data());
The name of a subroutine which corresponds to a subroutine index can be get by glGetActiveSubroutineName
.
But I recommend to use layout qualifier to specify the subroutine indices in the shader code - see Shader Subroutine - In-shader specification:
subroutine vec4 colorRedBlue();
layout(index = 1) subroutine (colorRedBlue)
vec4 redColor()
{
return vec4(1.0, 0.0, 0.0, 1.0);
}
layout(index = 2) subroutine (colorRedBlue)
vec4 blueColor()
{
return vec4(0.0, 0.0, 1.0, 1.0);
}
layout(location = 0) subroutine uniform colorRedBlue myRedBlueSelection;
Note, all the subroutines for all the subroutine unifroms of one shader stage have to be set at once, by glUniformSubroutinesuiv
. In your case, that's not a big thing, because there is only 1 subroutine uniform. This operation applies to the current shader program (glUsePrgram
).
The number of indices wich you have to pass to glUniformSubroutinesuiv
has to match the number of GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS
but not the number of GL_ACTIVE_SUBROUTINE_UNIFORM
- see glGetProgramStageiv
:
GLint nLocationCount = 0;
glGetProgramStageiv(
program, GL_FRAGMENT_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS, &nLocationCount );
std::vector<GLuint> sub_routines( nLocationCount, 0 );
Glint redBlueSelection_location = 0;
sub_routines[redBlueSelection_location] = 1; // index of 'redColor` or `blueColor`
glUniformSubroutinesuiv(
GL_FRAGMENT_SHADER, (GLsizei)sub_routines.size(), sub_routines.data() );