"Waves" shader is wrapping over

196 Views Asked by At

So I wrote this GLSL fragment shader for shadertoy:

const float INTENSITY = 0.5;
const float SPEED = 0.5;
const float SIZE = 0.2;

void mainImage(out vec4 fragColor, in vec2 fragCoord) {
    vec2 uv = gl_FragCoord.xy / iResolution.xy;
    vec4 color = texture(iChannel0, uv);

    vec2 ghostOffset = vec2(cos(uv.y * SPEED * sin(iTime)), sin(uv.x * SPEED));
    color += INTENSITY * texture(iChannel0, uv + ghostOffset * SIZE);

    fragColor = color;
}

https://www.shadertoy.com/view/dsjXD3

However, the resulting image seems to wrap over at the side. I know why this happens (UV is getting above {1., 1.} or below {0., 0.}), but I don't know how to fix it. Do you have any suggestions?

Thanks

Tuxifan

1

There are 1 best solutions below

0
On BEST ANSWER

the problem comes from the fact that when uv.y == 0, cos(uv.y * SPEED * sin(iTime)) == cos(0) == 1. So at the bottom of the image there is a constant offset which is equal to SIZE. To fix that you could just use a sin instead of the cos but then there would be no horizontal distortion at the bottom. You can also define ghostOffset as follows:

    vec2 ghostOffset = vec2(
    uv.x * (1. - uv.x) * sin(4.161 * uv.x + 3.981 * uv.y + 0.681 * iTime), 
    uv.y * (1. - uv.y) * sin(6.453 * uv.x + 7.753 * uv.y + 0.217 * iTime)
    );

With this, the distortion at the borders will always be parallel to them. It works because x * (1 - x) == 0 if x == 0 or x == 1 which is the case at the borders of the image. Note that you can put whatever you want inside the sin functions (you can even replace them by another function), the distortion at the borders of the image will always be parallel to the borders. I hope this helps. If it doesn't, tell me why.