#version 300 es
precision mediump float;

uniform vec2 u_display_size;
uniform vec3 u_background_color;
uniform vec3 u_colorA;
uniform vec3 u_colorB;
uniform vec3 u_colorC;
uniform float u_time;
uniform float u_fractal_noise_x;
uniform float u_fractal_noise_y;
uniform float u_fractal_noise_z;
uniform float u_grain_noise_scale;
uniform float u_circle_mask_radius;
uniform float u_mix_point_start;
uniform float u_mix_point_background;
uniform float u_mix_point_backgroundA;
uniform float u_mix_point_AB;
uniform float u_mix_point_BC;
uniform float u_mix_point_end;

in vec2 v_uv;  // From vertex shader
out vec4 fragColor;

// Simple fractal noise function
float fractal_noise(vec2 uv, float time) {
    return fract(sin(dot(uv + time * 0.1, vec2(12.9898, 78.233))) * 43758.5453);
}

// Simple grain noise function
float grain_noise(vec2 uv) {
    return fract(sin(dot(uv, vec2(12.9898, 78.233))) * 43758.5453) * u_grain_noise_scale;
}

// Function to blend colors based on mix points
vec3 getBlendedColor(float mix_point) {
    if (mix_point < u_mix_point_background) {
        return u_background_color;
    } else if (mix_point < u_mix_point_backgroundA) {
        return mix(u_background_color, u_colorA, smoothstep(u_mix_point_background, u_mix_point_backgroundA, mix_point));
    } else if (mix_point < u_mix_point_AB) {
        return u_colorA;
    } else if (mix_point < u_mix_point_BC) {
        return mix(u_colorA, u_colorB, smoothstep(u_mix_point_AB, u_mix_point_BC, mix_point));
    } else if (mix_point < u_mix_point_end) {
        return mix(u_colorB, u_colorC, smoothstep(u_mix_point_BC, u_mix_point_end, mix_point));
    } else {
        return u_colorC;
    }
}

void main() {
    vec2 uv = v_uv;

    // Apply circular mask based on distance from the center
    float distFromCenter = distance(uv, vec2(0.5, 0.5));
    if (distFromCenter > u_circle_mask_radius) {
        fragColor = vec4(0.0, 0.0, 0.0, 1.0);  // Mask the area outside the circle
        return;
    }

    // Compute fractal noise for grainy texture
    float fractalNoise = fractal_noise(uv, u_time * u_fractal_noise_z);

    // Apply color transitions based on mix points
    float mix_point = fractalNoise;  // Fractal noise drives the blending
    vec3 color = getBlendedColor(mix_point);

    // Add grain noise for additional texture
    float grain = grain_noise(uv);
    color += grain;

    // Final color output
    fragColor = vec4(color, 1.0);
}
