Reputation: 69
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
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
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