zero_copy_video_player/build/shader.frag
2026-08-05 08:56:00 -03:00

80 lines
2.2 KiB
GLSL

#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);
}