precision mediump float;

uniform float u_time;
uniform vec2 u_resolution;
uniform sampler2D u_charTexture;
uniform vec2 u_charPos; // Normalized 0-1 (Bottom-Left)
uniform vec2 u_charSize; // Normalized 0-1 (Width, Height)

varying vec2 vUv;

// reliable pseudo-random hash
float random(vec2 p) {
    vec3 p3  = fract(vec3(p.xyx) * .1031);
    p3 += dot(p3, p3.yzx + 33.33);
    return fract((p3.x + p3.y) * p3.z);
}

void main() {
    // Correct UV for aspect ratio if needed, but here we work in screen space mostly
    
    // Background Noise
    // Use floor to ensure we are sampling integer grid, making it purely pixel-noise
    vec2 gridPos = floor(gl_FragCoord.xy);
    float bgNoise = random(gridPos);
    float val = step(0.5, bgNoise); 
    
    // Character Composition
    vec2 charEnd = u_charPos + u_charSize;
    bool inBox = (vUv.x >= u_charPos.x && vUv.x <= charEnd.x &&
                  vUv.y >= u_charPos.y && vUv.y <= charEnd.y);
                  
    if (inBox) {
        vec2 texUv = (vUv - u_charPos) / u_charSize;
        texUv.y = 1.0 - texUv.y; 
        
        vec4 texColor = texture2D(u_charTexture, texUv);
        
        // Hard threshold to avoid any smooth edges revealing the shape
        if (texColor.a > 0.5) {
            // Inner Character Noise - Scrolls Down
            float scrollSpeed = 200.0;
            // Calculate scrolled position
            vec2 scrollCoords = gl_FragCoord.xy;
            scrollCoords.y += u_time * scrollSpeed;
            
            // IMPORTANT: Floor the scrolled coordinates! 
            // This ensures the noise "pixels" look exactly like the background "pixels" in size and sharpness.
            // If we don't floor, we get sub-pixel sampling which might look different (smooth/shimmering).
            vec2 charGridPos = floor(scrollCoords);
            
            // Use different seed offset to distinguish content, but same distribution
            float charNoise = random(charGridPos + vec2(42.0, 99.0)); 
            val = step(0.5, charNoise);
        }
    }
    
    gl_FragColor = vec4(vec3(1.0 - val), 1.0);
}
