#version 150 in vec2 v_texCoord; out vec4 fragColor; uniform sampler2D u_texY; uniform sampler2D u_texUV; uniform bool u_crtEnabled; uniform float u_curvature; uniform float u_scanlineDensity; uniform float u_scanlineOpacity; uniform float u_aberration; uniform float u_vignette; uniform float u_brightness; uniform float u_time; // Función para distorsión de barril (curvatura CRT) vec2 curve(vec2 uv) { if (u_curvature <= 0.0) return uv; uv = (uv - 0.5) * 2.0; uv.x *= 1.0 + (uv.y * uv.y) * (u_curvature * 0.05); uv.y *= 1.0 + (uv.x * uv.x) * (u_curvature * 0.05); uv = (uv / 2.0) + 0.5; return uv; } // Conversión NV12 (Y + UV entrelazados) a RGB vec3 getNv12Color(vec2 uv) { float y = texture(u_texY, uv).r; vec2 uvVal = texture(u_texUV, uv).rg; float u = uvVal.r - 0.5; float v = uvVal.g - 0.5; float r = y + 1.402 * v; float g = y - 0.344136 * u - 0.714136 * v; float b = y + 1.772 * u; return vec3(r, g, b); } void main() { vec2 uv = v_texCoord; if (u_crtEnabled) { uv = curve(uv); } // Verificar límites para recortar esquinas curvas if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) { fragColor = vec4(0.0, 0.0, 0.0, 1.0); return; } vec3 color; if (u_crtEnabled && u_aberration > 0.0) { // Aberración Cromática (RGB split) utilizando muestreos desfasados de NV12 float r = getNv12Color(vec2(uv.x - u_aberration, uv.y)).r; float g = getNv12Color(uv).g; float b = getNv12Color(vec2(uv.x + u_aberration, uv.y)).b; color = vec3(r, g, b); } else { color = getNv12Color(uv); } // Aplicar Brillo color *= u_brightness; if (u_crtEnabled) { // 1. Efecto Scanlines (Líneas de Barrido) float scanline = sin(uv.y * u_scanlineDensity * 3.14159265); scanline = mix(1.0, (scanline + 1.0) * 0.5, u_scanlineOpacity); color *= scanline; // 2. Efecto Viñeteado (Esquinas oscuras) float vignette = uv.x * uv.y * (1.0 - uv.x) * (1.0 - uv.y); vignette = clamp(pow(16.0 * vignette, u_vignette), 0.0, 1.0); color *= vignette; } fragColor = vec4(color, 1.0); }