这是我的片段着色器:
#version 120
uniform sampler2D sampler0;
uniform bool isf1;
vec4 f1(vec4 color) {
...
}
vec4 f2(vec4 color) {
...
}
void main()
{
gl_FragColor = texture2D( sampler2, gl_TexCoord[0].xy);
gl_FragColor = f1(gl_FragColor);
if(isf1) gl_FragColor = f2(gl_FragColor); //How to avoid it?
}
纹理分辨率1920x1080,所以“如果”调用2073600次,这是非常低效的。如何让'if'只为所有纹素发射一次?
答案 0 :(得分:2)
只需使用isf1
true
和false
渲染呈现的内容之间切换纹理即可。切换纹理 痛苦。
这绝对是过早优化的结果。
答案 1 :(得分:1)
正如其他人所说,避免着色器中if
的唯一方法是使用不同版本的程序。
您在评论中提到实际上可能需要调用六个函数(也许您可以将这些信息添加到您的问题中)。您可以将if
替换为#ifdef
并自动生成(64?)版本的程序(通过在代码前添加相应的#define
)。
这样做的缺点是,如果要绘制具有不同条件的许多不同对象,则必须在绘制之间切换着色器程序,这可能比着色器中的分支更昂贵。
有一点需要注意的是,如果相邻的片段采用相同的路径,则分支不会太昂贵(在最近的gpus上)。在您的情况下,所有片段都采用相同的路径,因此分支的价格尽可能便宜。
答案 2 :(得分:0)
编译两个程序,一个isf1
为true
,另一个为false
。
使用适当的程序设置isf1
制服。
答案 3 :(得分:0)
您正在根据传入的一些外部变量执行某些代码,即布尔值f1
。您应该使用子程序。在渲染之前,基于isf1
在OpenGL程序中设置子例程,然后渲染“f1”的所有内容。重复非f1的事情。这将在着色器之外选择适当的功能,而不是在每个片段上浪费时钟周期。
答案 4 :(得分:0)
也许这有点晚了,但我建议您查看Lighthouse3d here的subroutine
教程。
此外,对于更多基本分支,您还可以使用clamp
和mix
对其进行优化。 This tutorial给出了一个很好的例子。