2013-06-19 86 views
0

这是我的片段着色器:GLSL如何避免多次检查

#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次,这是非常低效的。如何让'如果'只有一次为所有纹理元素激发?

+2

一帧需要多长时间才能用那个'if'在那里渲染? 1毫秒? 1秒? 1分钟? – genpfault

回答

0

编译两个程序,一个是isf1true,另一个是false

使用适当的程序,您将设置isf1统一。

+0

不幸的是,我有6个功能,太多不同的组合http://stackoverflow.com/questions/17196639/qt-multiple-qglshaderprogram-for-one-texture – Dmitriy

+3

@Dmitriy:那么你应该问* *那种情况。 –

2

只需在渲染任何呈现内容之间切换纹理,即使用isf1truefalse之间的纹理。切换纹理不是痛苦。

这绝对反映了过早的优化。

0

您正在执行基于您传入的外部变量的一部分代码,即布尔型f1。你应该改用子程序。在渲染前根据isf1在OpenGL程序中设置子程序,然后渲染“f1”的所有东西。重复那些不是f1的事情。这将在着色器之外选择一次以上的正确功能,而不是浪费每个片段上的时钟周期。

1

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

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

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

需要注意的一件事是,如果相邻片段采用相同的路径,则分支不会太昂贵(在最近的gpus上)。在你的情况下,所有碎片都采用相同的路径,所以分支大约就像它们可以成本一样便宜。

0

也许这有点晚了,但我建议看看Lighthouse3d的subroutine教程here

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