基于统一变量在多个着色器之间进行选择
Choosing between multiple shaders based on uniform variable
我想根据统一变量的值从 2 个片段着色器中进行选择。我想知道怎么做。
我有编译的 onSurfaceCreated 函数,link 创建程序 1 和程序 1 的 glGetAttribLocation
在我的 onDrawFrame 中,我执行 glUseProgram(program1)。此函数针对每一帧运行。
我的问题是,在函数 onDrawFrame() 中,我获取了统一变量的值。我必须在 program1 或 program2 之间做出选择。但是 program1 已经编译 linked 和所有。这该怎么做?我将如何相应地更改我的程序并使用它,因为它已经在 onSurfaceCreated 中完成了。?
看来您需要在 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*/);
}
如果你想在不同的程序中使用同一套制服(如上面的代码),有一个更优雅 up-to-date 的解决方案:uniform buffer objects!例如,您可以使用任何着色器可能需要的所有变量创建缓冲区 object,但每个着色器程序只能使用其中的一个子集。此外,您可以使用 glGetActiveUniform
.
确定不需要的 (optimized-out) 制服
另请注意,您的问题标题有点误导。看起来您想选择一个执行分支而不是在您的主机代码中(即 onDrawFrame
函数),而是在您的着色器代码中。这种方法被称为 uber-shader 技术。互联网上有很多关于它们的讨论,例如:
http://www.gamedev.net/topic/659145-what-is-a-uber-shader/
http://www.shawnhargreaves.com/hlsl_fragments/hlsl_fragments.html
如果您决定这样做,请记住 GPU 并不擅长处理 if
语句和其他分支。
我想根据统一变量的值从 2 个片段着色器中进行选择。我想知道怎么做。
我有编译的 onSurfaceCreated 函数,link 创建程序 1 和程序 1 的 glGetAttribLocation
在我的 onDrawFrame 中,我执行 glUseProgram(program1)。此函数针对每一帧运行。
我的问题是,在函数 onDrawFrame() 中,我获取了统一变量的值。我必须在 program1 或 program2 之间做出选择。但是 program1 已经编译 linked 和所有。这该怎么做?我将如何相应地更改我的程序并使用它,因为它已经在 onSurfaceCreated 中完成了。?
看来您需要在 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*/);
}
如果你想在不同的程序中使用同一套制服(如上面的代码),有一个更优雅 up-to-date 的解决方案:uniform buffer objects!例如,您可以使用任何着色器可能需要的所有变量创建缓冲区 object,但每个着色器程序只能使用其中的一个子集。此外,您可以使用 glGetActiveUniform
.
另请注意,您的问题标题有点误导。看起来您想选择一个执行分支而不是在您的主机代码中(即 onDrawFrame
函数),而是在您的着色器代码中。这种方法被称为 uber-shader 技术。互联网上有很多关于它们的讨论,例如:
http://www.gamedev.net/topic/659145-what-is-a-uber-shader/ http://www.shawnhargreaves.com/hlsl_fragments/hlsl_fragments.html
如果您决定这样做,请记住 GPU 并不擅长处理 if
语句和其他分支。