我已经开始学习GLSL和OpenGL了。现在我想看看GLSL子程序是如何工作的,所以我在这里有片段着色器:
#version 330 core
out vec4 color;
subroutine vec4 ColorFunc();
subroutine (ColorFunc) vec4 colorBlue() {
return vec4(0.0, 0.0, 1.0, 1.0);
}
subroutine (ColorFunc) vec4 colorGreen() {
return vec4(0.0, 1.0, 0.0, 1.0);
}
subroutine uniform ColorFunc ColorSelector;
void main() {
color = ColorSelector();
}
在应用程序的源代码中我加载,编译链接着色器并在开始时启动程序。创建一个三角形,顶点着色器不会做任何特殊操作。 显示功能(发送到glutDisplayFunc
的功能)如下所示:
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(TriangleVAO);
glDrawArrays(GL_TRIANGLES, 0, NumVertices);
GLint ColorSelectorLoc;
GLuint colorBlueIndex;
GLuint colorGreenIndex;
ColorSelectorLoc = glGetSubroutineUniformLocation(program, GL_FRAGMENT_SHADER, "ColorSelector");
if (ColorSelectorLoc < 0)
{
fprintf(stderr, "Error: ColorSelector is not an active subroutine uniform in the shader\n");
exit(EXIT_FAILURE);
}
colorBlueIndex = glGetSubroutineIndex(program, GL_FRAGMENT_SHADER, "colorBlue");
colorGreenIndex = glGetSubroutineIndex(program, GL_FRAGMENT_SHADER, "colorGreen");
GLsizei n;
glGetProgramStageiv(program, GL_FRAGMENT_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS, &n);
GLuint *indices = new GLuint[n];
cout << "colorGreen: " << colorBlueIndex;
indices[ColorSelectorLoc] = colorGreenIndex;
glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, n, indices);
delete [] indices;
glFlush();
}
我期望三角形是绿色但它们总是蓝色,无论ColorSelector
的值是否正确检索(其值为0)。 colorBlueIndex
为0,colorGreenIndex
为1.我不知道我错过了什么。
答案 0 :(得分:1)
glUniformSubroutinesuiv
调用期望n
等于活动子例程位置的数量
你可以通过以下方式获得:
glGetProgramStage(program, GL_FRAGMENT_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS, &n);
请参阅the wiki
答案 1 :(得分:0)
我发现了问题。子程序的代码必须在glDrawArrays:
之前void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
GLint ColorSelectorLoc;
GLuint colorBlueIndex;
GLuint colorGreenIndex;
ColorSelectorLoc = glGetSubroutineUniformLocation(program, GL_FRAGMENT_SHADER, "ColorSelector");
if (ColorSelectorLoc < 0)
{
fprintf(stderr, "Error: ColorSelector is not an active subroutine uniform in the shader\n");
exit(EXIT_FAILURE);
}
colorBlueIndex = glGetSubroutineIndex(program, GL_FRAGMENT_SHADER, "colorBlue");
colorGreenIndex = glGetSubroutineIndex(program, GL_FRAGMENT_SHADER, "colorGreen");
GLsizei n;
glGetProgramStageiv(program, GL_FRAGMENT_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS, &n);
GLuint *indices = new GLuint[n];
cout << "colorGreen: " << colorBlueIndex;
indices[ColorSelectorLoc] = colorGreenIndex;
glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, n, indices);
delete [] indices;
glBindVertexArray(TriangleVAO);
glDrawArrays(GL_TRIANGLES, 0, NumVertices);
glFlush();
}