WebGL Float modulus behaviour

我的梦境 提交于 2019-12-04 06:22:20

问题


I am experiencing strange behaviours for below fragment Shader:

varying vec3 worldSpaceCoords;

uniform float rows;

void main() {

    float testNumber = 7.0;
    vec4 outputColor =  vec4(0.0,0.0,0.0,1.0);

    if(rows == testNumber) {
        if(worldSpaceCoords.x < 0.5) {

            outputColor.x = mod(floor(testNumber * worldSpaceCoords.y), rows ) / rows;

        } else {

            outputColor.x = mod(floor(testNumber * worldSpaceCoords.y), testNumber ) / testNumber;

        }

   } else {

        outputColor  = vec4(1.0,1.0,1.0,1.0);

   }

   gl_FragColor  = outputColor;

}

The "testNumber" variable is just my control variable to check that the passed in uniform "rows" is actually what it should be.

Some numbers of the uniform "rows", gives a strange behaviour. Below is an example where it's set to 9.0 (with testNumber set accordingly).

This result is expected. However, setting rows to 7.0 (and testNumber accordingly), it looks like this:

Clearly something is not working as it should. Any ideas why? I have tried to set the precision to lowp, mediump and highp without any difference.

Thanks


回答1:


This is likely the result of imprecise floating-point math, which adheres to rules documented in the GLSL ES Specification. The highp qualifier guarantees that the inputs and outputs of the mod operator are 32-bit IEEE 754 floating point numbers, but the calculation itself is not guaranteed to produce the same high precision. In particular, the modulus operator is defined in Chapter 8.3 as

genType mod (genType x, genType y)

Modulus. Returns x – y * floor (x/y).

The division operator a/b in this expression is guaranteed to have a precision of no less than 2.5 ULP for b (see chapter 4.5.1) and is typically computed as a*(1/b) since reciprocals and multiplications are cheaper than divisions. In your case, 1/testNumber is a compile-time constant and is probably computed to a different (higher) precision than 1/rows, which needs to be computed at run-time.

You could try using integer math instead of floating point, as the integer modulus operator a%b doesn't suffer from such precision issues.



来源:https://stackoverflow.com/questions/47388074/webgl-float-modulus-behaviour

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!