关闭

着色器子程序示例

标签: subroutineOpenGL编程指南着色器子程序
367人阅读 评论(0) 收藏 举报
分类:

在早期的GLSL里面,要实现函数分支选择,一般是使用if-else分支选择,虽然简单但也显得有些粗暴。
从GL 4.0开始,内核支持着色器子程序(subroutine)功能,这个功能有点类似函数指针,需要先顶一一个函数类型,然后实现N个这个类型的函数对象,最后使用Uniform的方式让用户指定运行时调用的函数。

#version 430 core  
out vec4 fColor;  

subroutine vec4 userColor();

subroutine (userColor) vec4 Red()
{
    return vec4(1.0, 0.0, 0.0, 1.0);
}

subroutine (userColor) vec4 Green()
{
    return vec4(0.0, 1.0, 0.0, 1.0);
}

subroutine (userColor) vec4 Blue()
{
    return vec4(0.0, 0.0, 1.0, 1.0);
}

subroutine uniform userColor myColor;

void main()  
{  
    fColor = myColor();  
}

这是一个简单的shader示例,第三行定义了一个函数指针类型,紧接着的是三个实现,最后是一个uniform变量,由程序指定具体值。

    GLint myColorLoc = glGetSubroutineUniformLocation(program, GL_FRAGMENT_SHADER, "myColor");
    if (myColorLoc < 0)
    {
        exit(EXIT_FAILURE);
    }

    GLuint RedIndex;
    GLuint GreenIndex;
    GLuint BlueIndex;

    RedIndex = glGetSubroutineIndex(program, GL_FRAGMENT_SHADER, "Red");
    GreenIndex = glGetSubroutineIndex(program, GL_FRAGMENT_SHADER, "Green");
    BlueIndex = glGetSubroutineIndex(program, GL_FRAGMENT_SHADER, "Blue");

    if (RedIndex == GL_INVALID_INDEX || 
        GreenIndex == GL_INVALID_INDEX || 
        BlueIndex == GL_INVALID_INDEX)
    {
        exit(EXIT_FAILURE);
    }

    GLsizei n;
    glGetProgramStageiv(program, GL_FRAGMENT_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS, &n);

    GLuint *indices = new GLuint[n];
    indices[myColorLoc] = BlueIndex;

    glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, n, indices);

    delete [] indices;

首先使用glGetSubroutineUniformLocation函数获取子程序的Uniform的位置,之后使用glGetSubroutineIndex函数来获取子程序的索引号,两个都拿到之后,先查询一下现在激活的子程序的Uniform的个数,因为glUniformSubroutinesuiv函数的第二个传入参数就是它。glUniformSubroutinesuiv的第三个传入参数是一个GLuint的数组,数组长度由前一个参数n指定,第i个子程序Uniform的子程序对应于indices[i]的值。

subroutine

修改indices[myColorLoc]为不同的子程序索引,就能调用相应的函数。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:6554次
    • 积分:142
    • 等级:
    • 排名:千里之外
    • 原创:6篇
    • 转载:0篇
    • 译文:2篇
    • 评论:1条
    最新评论