GLSL分区与乘法

时间:2017-05-18 01:35:34

标签: glsl webgl

说我有类似的东西:

float foo;

float bar = baz / foo;
float qux = quux / foo;

当我执行以下操作时会发生什么:

foo = 1./foo;
float bar = baz * foo;    //can i expect roughly the same number as with division?
floar qux = quux * foo;   //is it always going to be faster?

鉴于webgl可以运行的硬件范围很广,我是否可以预期在编译时会发生这样的事情,或者像这样写它会更安全吗?

也很好奇

uniform float invFoo;
...
bar = baz * invFoo;
//instead of:
uniform float foo;
...
bar = baz / foo;

我不太明白this

// A stupid compiler might use these as written: a divide, then add.
vec4 result1 = (value / 2.0) + 1.0;
vec4 result2 = (value / 2.0) - 1.0;
vec4 result3 = (value / -2.0) + 1.0;

// There are most likely converted to a single MAD operation (per line).
vec4 result1 = (value * 0.5) + 1.0;
vec4 result2 = (value * 0.5) - 1.0;
vec4 result3 = (value * -0.5) + 1.0;

我不明白愚蠢的编译器在这种情况下做了什么。是否缺少这可以作为单个MAD指令完成,或者是否缺少该除法可以表示为乘法(同时缺少MAD)。

此外,如何对这样的事情进行分组,但要转移内容:

vec2 foo,bar;
float baz;

baz = 1./baz;
vec2 temp = vec2( foo.x , bar.x ) * baz; //move but do one mult?
foo.x = temp.x;
bar.x = temp.y;

1 个答案:

答案 0 :(得分:3)

  

我可以期待与分部大致相同的数字吗?

严格来说,不是:

$ cat a.cc
#include <iostream>

int main() {
    const float a = 1.40129846e-45f;
    const float b = a;

    std::cout << "b / a:       " << (b / a) << std::endl;
    std::cout << "b * (1 / a): " <<(b * (1.f / a)) << std::endl;

    return 0;
}
$ clang++ a.cc && ./a.out
b / a:       1
b * (1 / a): inf
$

然而,在或多或少的现实生活中,乘法和除法可以给出接近的结果。任何其他依赖于你将使用结果的计算的稳定性。如果那些计算是不稳定的(即,如果其任何参数甚至稍微改变,这种计算的结果会显着改变),那么结果可能存在差异。因此,您需要了解您使用的值,尤其是您所获得的精度。 GLSL浮点数并不总是32位IEEE浮点数,它们可能不太精确。

  

是否缺少这可以作为单个MAD指令完成,或者是   它错过了除法可以表示为乘法(at   同时错过了MAD)。

取决于特定编译器的特定怪癖,但可能是第二件事。