我正在屏幕上的每个像素上运行此片段着色器。我正在尝试使其尽可能高效。顺便说一句,我正在运行open gl es 2.0。下面的代码段只是代码中的一个示例,对Gaussian()的大约56个不同的调用分布在不同的函数中。我想知道用适当的结果浮点值替换对Gaussian()的调用是否有价值。或仅计算一次,因为gpu意识到所有片段的计算方法都是相同的。 br />
uniform float scalar;
varying float scalart;
float deviationScale = 1.2;
float finalScalar = 1.1;
float Gaussian(float x, float deviation)
{
    return (1.0 / sqrt(2.0 * 3.141592 * deviation)) * exp(-((x * x) / (2.0 * deviation)));
}
vec3 blurS5()
{
    vec3 blr = vec3(0.0);
    blr += texture2D(s_texture, (v_texcoord + vec2(2.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(2.0, 2.0 * deviationScale) ;
    blr += texture2D(s_texture, (v_texcoord + vec2(1.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(1.0, 2.0 * deviationScale) ;

    blr += texture2D(s_texture, (v_texcoord + vec2(0.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(0.0, 2.0 * deviationScale) ;

    blr += texture2D(s_texture, (v_texcoord + vec2(-1.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(-1.0, 2.0 * deviationScale) ;
    blr += texture2D(s_texture, (v_texcoord + vec2(-2.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(-2.0, 2.0 * deviationScale) ;
    return blr;

}

void main()
{
        if (scalar == 2.)
        {
            gl_FragColor = vec4(blurS5(), 1.0);
        }
        else if (scalar == 3.)
        {
            gl_FragColor = vec4(blurS9(), 1.0);
        }
        //There are waaayyy more of these
}


#1 楼

这取决于。在台式机上,如果始终使用相同的参数调用Gaussian函数,则着色器编译器可能会对其进行优化,因此仅执行一次评估。但是,在移动平台上,编译器执行优化的时间更少,可能会错过它。无论哪种方式,您都可以通过查看生成的程序集来确认。

请注意,Unity的ArasPranckevičius编写了GLSL优化程序来解决移动设备上次优编译器的问题:https://github.com / aras-p / glsl-optimizer

话虽如此,关于您的示例代码,我肯定至少要公开统一的(1.0 / sqrt(2.0 * 3.141592 * deviation))

#2 楼

着色器编译器很可能会执行公共子表达式合并,并对该函数进行一次计算,并在每次出现在着色器中时重新使用它。

您可能会认为,由于deviationScale和所有其他args是常量,因此有可能将其完全折叠为常数,并且从不在运行时执行。但这是不正确的,因为sqrt()和exp()不是编译时constexpr函数。编译器无法假定这些数学函数的任何特定实现(以及关联的数值属性),因此整个函数也不会得到优化,并且也不会在线程间重复使用,因为着色语言的编程排除了这种情况。模型。

最好的方法是预先计算整个表达式并将其存储在统一的范围内(如果重要的是要使其最佳)。