为什么glGetSubroutineIndex为不同的函数返回相同的值?

时间:2018-10-19 20:06:19

标签: c++ opengl glsl subroutine

我有一个片段着色器,应该可以操作两种颜色-红色和蓝色。

#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();
}

当我引用glGetSubroutineIndex(shaderProgram, GL_FRAGMENT_SHADER, "redColor");glGetSubroutineIndex(shaderProgram, GL_FRAGMENT_SHADER, "blueColor");

它们是相同的数字:4294967295

为什么它们是相同的数字?我做错了什么?

1 个答案:

答案 0 :(得分:2)

如果要检索有关子例程索引的信息,则必须使用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());

与子例程索引相对应的子例程的名称可以通过glGetActiveSubroutineName获取。

但是我建议使用布局限定符在着色器代码中指定子例程索引-请参见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;

请注意,必须使用glUniformSubroutinesuiv一次设置一个着色器阶段的所有子例程Unifrom的所有子例程。在您的情况下,这没什么大不了的,因为只有1个子例程统一。此操作适用于当前的着色器程序(glUsePrgram)。
您必须传递给glUniformSubroutinesuiv的索引数必须与GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS的数相匹配,但不能与GL_ACTIVE_SUBROUTINE_UNIFORM的数相匹配-请参见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() );