0

这是我的片段着色器:

#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,因此“if”调用了 2073600 次,这是非常低效的。如何让所有纹素只触发一次“if”?

4

5 回答 5

2

只需在渲染任何你用isf1 true和渲染的东西之间切换纹理false。切换纹理并不那么痛苦。

这绝对是过早优化的恶臭。

于 2013-06-19T18:09:07.407 回答
1

正如其他人所说,避免if在着色器中出现的唯一方法是拥有不同版本的程序。

您在评论中提到实际上可能需要调用六个函数(也许您可以将该信息添加到您的问题中)。您可以用ifs 替换您的#ifdefs 并自动生成(64?)程序版本(通过在您的代码前面加上适当#define的 s)。

这样做的缺点是,如果您在不同条件下绘制许多不同的对象,则必须在绘制之间切换着色器程序,这可能比着色器中的分支更昂贵。

需要注意的一件事是,如果相邻片段采用相同的路径,则分支不会太昂贵(在更新的 gpus 上)。在您的情况下,所有片段都采用相同的路径,因此分支尽可能便宜。

于 2013-06-20T09:19:35.150 回答
0

Compile two programs, one where isf1 is true and one where it's false.

Use the appropriate program where you would have set the isf1 uniform.

于 2013-06-19T18:02:53.273 回答
0

您正在根据传入的一些外部变量(即 boolean )执行部分代码f1。您应该改用子例程。在你渲染之前在你的OpenGL程序中设置子程序isf1,然后渲染所有“是f1”的东西。对非 f1 的内容重复此操作。这将在着色器之外选择适当的功能一次,而不是在每个片段上浪费时钟周期。

于 2013-06-19T20:52:44.137 回答
0

也许这有点晚了,但我建议在这里subroutine看一下Lighthouse3d 的教程。

此外,对于更基本的分支,您还可以使用clamp和对其进行优化mix本教程给出了一个很好的例子。

于 2014-07-18T20:29:23.487 回答