GLSL子程序没有改变

时间:2014-04-30 14:48:36

标签: c++ opengl glsl subroutine fragment-shader

我已经开始学习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.我不知道我错过了什么。

2 个答案:

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