stego
stego

Reputation: 69

How do you deal with decimal precision of increasing float values in GLSL?

I'm writing a shader where I need to calculate y-value based on an increasing x offset.

The problem is that the increasing x value will eventually lose its decimal precision causing the output of the y function to return increasingly fragmented values.

I've tried to illustrate the problem in this example.

You can increase or decrease the largeTimeOffset variable to see the effect it has on the detail of the sine wave. Is there a common way to tackle this problem?

Fragment shader for reference:

float calculateY(float x, float y) {
    return  y + sin(x);
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec3 bgColor = vec3(0.0);
    vec3 lineColor = vec3(0.0);
    float lineWidth = 0.001;

    vec2 uv = fragCoord/iResolution.xy;

    uv  = -1.0 + 2.0 * uv;
    uv.y += 0.1;

    float largeTimeOffset = 1000000.0;
    float x = (uv.x + (iTime + largeTimeOffset));

    float y = calculateY(x, uv.y);
    lineWidth = abs(1.0 / (300.0 * y));     
    lineColor += vec3(lineWidth, lineWidth, lineWidth);


    fragColor = vec4(bgColor+lineColor,1.0);
}

Upvotes: 3

Views: 2052

Answers (2)

Rabbid76
Rabbid76

Reputation: 211268

First of all note, that the data type double is supported since "desktop" OpenGL 4.0 (GLSL 4.00), respectively by the extension ARB_gpu_shader_fp64.
See Data Type (GLSL)


Since sin is a periodic function, the issue can be solved by calculation the offset within a period by mod. The period is 2*PI respectively 2.0*acos(-1.0):
(mod is available in all GLSL respectively GLSL ES versions)

float x = uv.x + mod(iTime + largeTimeOffset, 2.0*acos(-1.0));

Of course this is a special solution for the trigonometric functions sin and cos

Upvotes: 2

Quadslab
Quadslab

Reputation: 294

@Rabbid76 mentioned that the fp64 extension works on OpenGL ES 3.2, but in the specs it says that the minimum supported version is OpenGL 3.2 which is not equivalent to OpenGL ES 3.2.
To actually use double-precision floating point numbers in OpenGL ES, you have to emulate it. For the trigonometric functions, you can use the taylor series expansions of those functions.

Upvotes: 0

Related Questions