0.00
60.0 fps

Moire Effect

An attempt at a demo effect

Log in to post a comment.

#version 300 es
precision highp float;

uniform float iTime;
uniform vec2  iResolution;
out vec4 fragColor;

// 2×2 rotation matrix
mat2 rot(float a) {
    float c = cos(a), s = sin(a);
    return mat2(c, -s, s, c);
}

// a smooth palette generator
vec3 palette(float t) {
    return vec3(
        0.5 + 0.5 * cos(6.2831 * (t + 0.0)),
        0.5 + 0.5 * cos(6.2831 * (t + 0.33)),
        0.5 + 0.5 * cos(6.2831 * (t + 0.67))
    );
}

// alternating concentric-ring pattern centered at `center`
float ringPattern(vec2 uv, vec2 center, float freq) {
    float d = length(uv - center);
    return step(0.5, fract(d * freq));
}

void main() {
    // normalize coords to [-1,+1], correct aspect ratio
    vec2 uv = (gl_FragCoord.xy / iResolution.xy) * 2.0 - 1.0;
    uv.x *= iResolution.x / iResolution.y;

    float t = iTime;

    // time-varying frequencies: oscillate around base values
    float f1 = 18.0 +  6.0 * sin(t * 0.7);
    float f2 = 22.0 +  4.0 * cos(t * 0.9);

    // moving centres
    vec2 c1 = rot( t * 0.6) * vec2(0.3, 0.0);
    vec2 c2 = rot(-t * 0.4) * vec2(0.4, 0.0);

    // build each ring pattern
    float p1 = ringPattern(uv, c1, f1);
    float p2 = ringPattern(uv, c2, f2);

    // XOR for moiré
    float m = abs(p1 - p2);

    // dynamic colours for each pattern
    vec3 col1 = mix(
        palette(fract(t * 0.1)),         // colour A
        palette(fract(t * 0.1 + 0.5)),   // colour B
        p1
    );
    vec3 col2 = mix(
        palette(fract(t * 0.15 + 0.25)),
        palette(fract(t * 0.15 + 0.75)),
        p2
    );

    // blend patterns: show both but highlight moiré
    vec3 color = mix(col1, col2, 0.5) * (0.5 + 0.5 * m);

    fragColor = vec4(color, 1.0);
}