基于均匀变量在多个着色器之间进行选择

时间:2016-04-05 10:12:56

标签: opengl textures fragment-shader

我想根据统一变量的值从2个片段着色器中进行选择。我想知道怎么做。

我有onSurfaceCreated函数,它编译并链接以创建该program1的program1和glGetAttribLocation

在我的onDrawFrame中,我执行glUseProgram(program1)。此功能适用于每一帧。

我的问题是,在函数onDrawFrame()中,我得到了我的统一变量的值。我必须在program1或program2之间进行选择。但是program1已经被编译链接了所有。这该怎么做?我将如何相应地更改我的程序并使用它,因为它已在onSurfaceCreated中完成。?

1 个答案:

答案 0 :(得分:0)

您似乎需要在onSurfaceCreated功能中准备两个程序。我将尝试使用示例代码来说明这一点。请在项目中以更准确的方式组织它:

// onSurfaceCreated function:
glCompileShader(/*shader1 for prog1*/);
glCompileShader(/*shader2 for prog1*/);
//...
glCompileShader(/*shadern for prog1*/);
glCompileShader(/*shader1 for prog2*/);
glCompileShader(/*shader2 for prog2*/);
//...
glCompileShader(/*shadern for prog2*/);
glLinkProgram(/*prog1*/);
glLinkProgram(/*prog2*/);
u1 = glGetUniformLocation(/*uniform in prog1*/);
u2 = glGetUniformLocation(/*uniform in prog2*/);

// onDrawFrame
if(I_need_prog1_condition) {
    glUseProgram(prog1);
    glUniform(/*set uniform using u1*/);
} else {
    glUseProgram(prog2);
    glUniform(/*set uniform using u2*/);
}

如果你想从不同的程序中使用同一套制服(比如上面的代码),那么存在一个更优雅和最新的解决方案:uniform buffer objects!例如,您可以使用任何着色器可能需要的所有变量创建缓冲区对象,但每个着色器程序只能使用它们的一部分。此外,您可以使用glGetActiveUniform确定不需要的(优化的)制服。

另请注意,您的问题标题有点误导。看起来您想要选择不在主机代码中的执行分支(即onDrawFrame功能),而是在着色器代码中。这种方法称为超级着色器技术。互联网上有很多关于它们的讨论,如:

http://www.gamedev.net/topic/659145-what-is-a-uber-shader/ http://www.shawnhargreaves.com/hlsl_fragments/hlsl_fragments.html

如果您决定这样做,请记住GPU并不擅长处理if语句和其他分支。