export const screenVertexShader = ` varying vec2 vUv; void main() { vUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); } `; export const screenFragmentShader = ` varying vec2 vUv; uniform sampler2D videoTexture; uniform float u_effect_type; // 0: none, 1: warmup, 2: powerdown uniform float u_effect_strength; // 0.0 to 1.0 void main() { vec2 centeredUv = vUv - 0.5; vec4 finalColor; if (u_effect_type < 0.5) { // No effect finalColor = texture2D(videoTexture, vUv); } else if (u_effect_type < 1.5) { // Warm-up effect // A bright dot expands to reveal the screen content float effectRadius = u_effect_strength * 0.75; // Max radius of 0.75 (sqrt(0.5*0.5 + 0.5*0.5)) float distanceToCenter = length(centeredUv); // Smoothly transition the edge of the circle float vignette = smoothstep(effectRadius, effectRadius - 0.1, distanceToCenter); vec4 videoColor = texture2D(videoTexture, vUv); finalColor = videoColor * vignette * u_effect_strength; // Fade in brightness } else { // Power-down effect // The image collapses into a bright horizontal line and fades float collapseFactor = 1.0 - u_effect_strength; // Squeeze the UVs vertically vec2 squeezedUv = vec2(vUv.x, 0.5 + (vUv.y - 0.5) * collapseFactor); vec4 videoColor = texture2D(videoTexture, squeezedUv); // Create a bright glow where the line is float lineGlow = pow(1.0 - abs(centeredUv.y) / (0.5 * collapseFactor + 0.01), 20.0); finalColor = videoColor * collapseFactor + vec4(0.8, 0.9, 1.0, 1.0) * lineGlow * u_effect_strength; } gl_FragColor = finalColor; } `;