llevant el soport de opengl

This commit is contained in:
2026-03-21 17:11:26 +01:00
parent aa292dcd92
commit 43a6cc2d7a
10 changed files with 13 additions and 1220 deletions

View File

@@ -1,160 +0,0 @@
#version 330 core
// Configuración
#define SCANLINES
#define MULTISAMPLE
#define SCANLINE_WEIGHT 6.0
#define SCANLINE_GAP_BRIGHTNESS 0.12
#define BLOOM_FACTOR 3.5
// Inputs desde vertex shader
in vec2 vTexCoord;
in float vFilterWidth;
// Output
out vec4 FragColor;
// Uniforms existentes
uniform sampler2D Texture;
uniform vec2 TextureSize;
uniform float uVignette; // 0 = sin viñeta, 1 = máxima
uniform float uScanlines; // 0 = desactivadas, 1 = plenas
uniform float uChroma; // 0 = sin aberración, 1 = máxima
uniform float uOutputHeight; // altura del viewport en pixels de pantalla
// Nuevos uniforms
uniform float uMask; // 0 = sin máscara de fósforo, 1 = máxima
uniform float uGamma; // 0 = sin corrección gamma, 1 = gamma 2.4/2.2 plena
uniform float uCurvature; // 0 = plana, 1 = curvatura barrel máxima
uniform float uBleeding; // 0 = sin sangrado NTSC, 1 = máximo
// Conversores YCbCr para efecto NTSC
vec3 rgb_to_ycc(vec3 rgb) {
return vec3(
0.299*rgb.r + 0.587*rgb.g + 0.114*rgb.b,
-0.169*rgb.r - 0.331*rgb.g + 0.500*rgb.b + 0.5,
0.500*rgb.r - 0.419*rgb.g - 0.081*rgb.b + 0.5
);
}
vec3 ycc_to_rgb(vec3 ycc) {
float y = ycc.x;
float cb = ycc.y - 0.5;
float cr = ycc.z - 0.5;
return clamp(vec3(
y + 1.402*cr,
y - 0.344*cb - 0.714*cr,
y + 1.772*cb
), 0.0, 1.0);
}
float CalcScanLineWeight(float dist)
{
return max(1.0 - dist * dist * SCANLINE_WEIGHT, SCANLINE_GAP_BRIGHTNESS);
}
void main()
{
vec2 texcoord = vTexCoord;
// Curvatura barrel CRT (distorsión en UV antes de muestrear)
if (uCurvature > 0.0) {
vec2 c = texcoord - 0.5;
float rsq = dot(c, c);
vec2 dist = vec2(0.05, 0.1) * uCurvature;
vec2 barrelScale = 1.0 - 0.23 * dist;
c += c * (dist * rsq);
c *= barrelScale;
if (abs(c.x) >= 0.5 || abs(c.y) >= 0.5) {
FragColor = vec4(0.0);
return;
}
texcoord = c + 0.5;
}
vec2 texcoordInPixels = texcoord * TextureSize;
float tempY = floor(texcoordInPixels.y) + 0.5;
float yCoord = tempY / TextureSize.y;
// Scanline en espacio de pantalla (subpíxel)
float scaleY = uOutputHeight / TextureSize.y;
float screenY = texcoord.y * uOutputHeight;
float posInRow = mod(screenY, scaleY);
float scanLineDY = posInRow / scaleY - 0.5;
float localFilterWidth = 1.0 / scaleY;
float scanLineWeight = CalcScanLineWeight(scanLineDY);
scanLineWeight += CalcScanLineWeight(scanLineDY - localFilterWidth);
scanLineWeight += CalcScanLineWeight(scanLineDY + localFilterWidth);
scanLineWeight *= 0.3333333;
// Phosphor blur en espacio textura
float dy = texcoordInPixels.y - tempY;
float signY = sign(dy);
dy = dy * dy;
dy = dy * dy;
dy *= 8.0;
dy /= TextureSize.y;
dy *= signY;
vec2 tc = vec2(texcoord.x, yCoord + dy);
// Muestra base en centro
vec3 base = texture(Texture, tc).rgb;
// Sangrado NTSC — difuminado horizontal de crominancia
vec3 colour;
if (uBleeding > 0.0) {
float tw = TextureSize.x;
vec3 ycc = rgb_to_ycc(base);
vec3 ycc_l2 = rgb_to_ycc(texture(Texture, tc - vec2(2.0/tw, 0.0)).rgb);
vec3 ycc_l1 = rgb_to_ycc(texture(Texture, tc - vec2(1.0/tw, 0.0)).rgb);
vec3 ycc_r1 = rgb_to_ycc(texture(Texture, tc + vec2(1.0/tw, 0.0)).rgb);
vec3 ycc_r2 = rgb_to_ycc(texture(Texture, tc + vec2(2.0/tw, 0.0)).rgb);
ycc.yz = (ycc_l2.yz + ycc_l1.yz*2.0 + ycc.yz*2.0 + ycc_r1.yz*2.0 + ycc_r2.yz) / 8.0;
colour = mix(base, ycc_to_rgb(ycc), uBleeding);
} else {
colour = base;
}
// Aberración cromática
float ca = uChroma * 0.005;
colour.r = texture(Texture, tc + vec2(ca, 0.0)).r;
colour.b = texture(Texture, tc - vec2(ca, 0.0)).b;
// Corrección gamma (linealizar antes de scanlines, codificar después)
if (uGamma > 0.0) {
vec3 lin = pow(colour, vec3(2.4));
colour = mix(colour, lin, uGamma);
}
// Scanlines
scanLineWeight *= BLOOM_FACTOR;
colour *= mix(1.0, scanLineWeight, uScanlines);
if (uGamma > 0.0) {
vec3 enc = pow(colour, vec3(1.0 / 2.2));
colour = mix(colour, enc, uGamma);
}
// Viñeta
if (uVignette > 0.0) {
vec2 uv = texcoord - vec2(0.5);
float vig = 1.0 - dot(uv, uv) * uVignette * 4.0;
colour *= clamp(vig, 0.0, 1.0);
}
// Máscara de fósforo RGB
if (uMask > 0.0) {
float whichMask = fract(gl_FragCoord.x * 0.3333333);
vec3 mask = vec3(0.80);
if (whichMask < 0.3333333)
mask.x = 1.0;
else if (whichMask < 0.6666666)
mask.y = 1.0;
else
mask.z = 1.0;
colour = mix(colour, colour * mask, uMask);
}
FragColor = vec4(colour, 1.0);
}

View File

@@ -1,163 +0,0 @@
#version 300 es
// OpenGL ES 3.0 - Compatible con Raspberry Pi 5
precision highp float;
// Configuración
#define SCANLINES
#define MULTISAMPLE
#define SCANLINE_WEIGHT 6.0
#define SCANLINE_GAP_BRIGHTNESS 0.12
#define BLOOM_FACTOR 3.5
// Inputs desde vertex shader
in vec2 vTexCoord;
in float vFilterWidth;
// Output
out vec4 FragColor;
// Uniforms existentes
uniform sampler2D Texture;
uniform vec2 TextureSize;
uniform float uVignette; // 0 = sin viñeta, 1 = máxima
uniform float uScanlines; // 0 = desactivadas, 1 = plenas
uniform float uChroma; // 0 = sin aberración, 1 = máxima
uniform float uOutputHeight; // altura del viewport en pixels de pantalla
// Nuevos uniforms
uniform float uMask; // 0 = sin máscara de fósforo, 1 = máxima
uniform float uGamma; // 0 = sin corrección gamma, 1 = gamma 2.4/2.2 plena
uniform float uCurvature; // 0 = plana, 1 = curvatura barrel máxima
uniform float uBleeding; // 0 = sin sangrado NTSC, 1 = máximo
// Conversores YCbCr para efecto NTSC
vec3 rgb_to_ycc(vec3 rgb) {
return vec3(
0.299*rgb.r + 0.587*rgb.g + 0.114*rgb.b,
-0.169*rgb.r - 0.331*rgb.g + 0.500*rgb.b + 0.5,
0.500*rgb.r - 0.419*rgb.g - 0.081*rgb.b + 0.5
);
}
vec3 ycc_to_rgb(vec3 ycc) {
float y = ycc.x;
float cb = ycc.y - 0.5;
float cr = ycc.z - 0.5;
return clamp(vec3(
y + 1.402*cr,
y - 0.344*cb - 0.714*cr,
y + 1.772*cb
), 0.0, 1.0);
}
float CalcScanLineWeight(float dist)
{
return max(1.0 - dist * dist * SCANLINE_WEIGHT, SCANLINE_GAP_BRIGHTNESS);
}
void main()
{
vec2 texcoord = vTexCoord;
// Curvatura barrel CRT (distorsión en UV antes de muestrear)
if (uCurvature > 0.0) {
vec2 c = texcoord - vec2(0.5);
float rsq = dot(c, c);
vec2 dist = vec2(0.05, 0.1) * uCurvature;
vec2 barrelScale = vec2(1.0) - 0.23 * dist;
c += c * (dist * rsq);
c *= barrelScale;
if (abs(c.x) >= 0.5 || abs(c.y) >= 0.5) {
FragColor = vec4(0.0);
return;
}
texcoord = c + vec2(0.5);
}
vec2 texcoordInPixels = texcoord * TextureSize;
float tempY = floor(texcoordInPixels.y) + 0.5;
float yCoord = tempY / TextureSize.y;
// Scanline en espacio de pantalla (subpíxel)
float scaleY = uOutputHeight / TextureSize.y;
float screenY = texcoord.y * uOutputHeight;
float posInRow = mod(screenY, scaleY);
float scanLineDY = posInRow / scaleY - 0.5;
float localFilterWidth = 1.0 / scaleY;
float scanLineWeight = CalcScanLineWeight(scanLineDY);
scanLineWeight += CalcScanLineWeight(scanLineDY - localFilterWidth);
scanLineWeight += CalcScanLineWeight(scanLineDY + localFilterWidth);
scanLineWeight *= 0.3333333;
// Phosphor blur en espacio textura
float dy = texcoordInPixels.y - tempY;
float signY = sign(dy);
dy = dy * dy;
dy = dy * dy;
dy *= 8.0;
dy /= TextureSize.y;
dy *= signY;
vec2 tc = vec2(texcoord.x, yCoord + dy);
// Muestra base en centro
vec3 base = texture(Texture, tc).rgb;
// Sangrado NTSC — difuminado horizontal de crominancia
vec3 colour;
if (uBleeding > 0.0) {
float tw = TextureSize.x;
vec3 ycc = rgb_to_ycc(base);
vec3 ycc_l2 = rgb_to_ycc(texture(Texture, tc - vec2(2.0/tw, 0.0)).rgb);
vec3 ycc_l1 = rgb_to_ycc(texture(Texture, tc - vec2(1.0/tw, 0.0)).rgb);
vec3 ycc_r1 = rgb_to_ycc(texture(Texture, tc + vec2(1.0/tw, 0.0)).rgb);
vec3 ycc_r2 = rgb_to_ycc(texture(Texture, tc + vec2(2.0/tw, 0.0)).rgb);
ycc.yz = (ycc_l2.yz + ycc_l1.yz*2.0 + ycc.yz*2.0 + ycc_r1.yz*2.0 + ycc_r2.yz) / 8.0;
colour = mix(base, ycc_to_rgb(ycc), uBleeding);
} else {
colour = base;
}
// Aberración cromática
float ca = uChroma * 0.005;
colour.r = texture(Texture, tc + vec2(ca, 0.0)).r;
colour.b = texture(Texture, tc - vec2(ca, 0.0)).b;
// Corrección gamma (linealizar antes de scanlines, codificar después)
if (uGamma > 0.0) {
vec3 lin = pow(colour, vec3(2.4));
colour = mix(colour, lin, uGamma);
}
// Scanlines
scanLineWeight *= BLOOM_FACTOR;
colour *= mix(1.0, scanLineWeight, uScanlines);
if (uGamma > 0.0) {
vec3 enc = pow(colour, vec3(1.0 / 2.2));
colour = mix(colour, enc, uGamma);
}
// Viñeta
if (uVignette > 0.0) {
vec2 uv = texcoord - vec2(0.5);
float vig = 1.0 - dot(uv, uv) * uVignette * 4.0;
colour *= clamp(vig, 0.0, 1.0);
}
// Máscara de fósforo RGB
if (uMask > 0.0) {
float whichMask = fract(gl_FragCoord.x * 0.3333333);
vec3 mask = vec3(0.80);
if (whichMask < 0.3333333)
mask.x = 1.0;
else if (whichMask < 0.6666666)
mask.y = 1.0;
else
mask.z = 1.0;
colour = mix(colour, colour * mask, uMask);
}
FragColor = vec4(colour, 1.0);
}

View File

@@ -1,48 +0,0 @@
#version 330 core
// Configuración
#define SCANLINES
#define MULTISAMPLE
#define GAMMA
//#define FAKE_GAMMA
//#define CURVATURE
//#define SHARPER
#define MASK_TYPE 2
#define CURVATURE_X 0.05
#define CURVATURE_Y 0.1
#define MASK_BRIGHTNESS 0.80
#define SCANLINE_WEIGHT 6.0
#define SCANLINE_GAP_BRIGHTNESS 0.12
#define BLOOM_FACTOR 3.5
#define INPUT_GAMMA 2.4
#define OUTPUT_GAMMA 2.2
// Inputs (desde VAO)
layout(location = 0) in vec2 aPosition;
layout(location = 1) in vec2 aTexCoord;
// Outputs al fragment shader
out vec2 vTexCoord;
out float vFilterWidth;
#if defined(CURVATURE)
out vec2 vScreenScale;
#endif
// Uniforms
uniform vec2 TextureSize;
void main()
{
#if defined(CURVATURE)
vScreenScale = vec2(1.0, 1.0);
#endif
// Calcula filterWidth dinámicamente basándose en la altura de la textura
vFilterWidth = (768.0 / TextureSize.y) / 3.0;
// Pasar coordenadas de textura (invertir Y para SDL)
vTexCoord = vec2(aTexCoord.x, 1.0 - aTexCoord.y) * 1.0001;
// Posición del vértice (ya en espacio de clip [-1, 1])
gl_Position = vec4(aPosition, 0.0, 1.0);
}

View File

@@ -1,51 +0,0 @@
#version 300 es
// OpenGL ES 3.0 - Compatible con Raspberry Pi 5
precision highp float;
// Configuración
#define SCANLINES
#define MULTISAMPLE
#define GAMMA
//#define FAKE_GAMMA
//#define CURVATURE
//#define SHARPER
#define MASK_TYPE 2
#define CURVATURE_X 0.05
#define CURVATURE_Y 0.1
#define MASK_BRIGHTNESS 0.80
#define SCANLINE_WEIGHT 6.0
#define SCANLINE_GAP_BRIGHTNESS 0.12
#define BLOOM_FACTOR 3.5
#define INPUT_GAMMA 2.4
#define OUTPUT_GAMMA 2.2
// Inputs (desde VAO)
layout(location = 0) in vec2 aPosition;
layout(location = 1) in vec2 aTexCoord;
// Outputs al fragment shader
out vec2 vTexCoord;
out float vFilterWidth;
#if defined(CURVATURE)
out vec2 vScreenScale;
#endif
// Uniforms
uniform vec2 TextureSize;
void main()
{
#if defined(CURVATURE)
vScreenScale = vec2(1.0, 1.0);
#endif
// Calcula filterWidth dinámicamente basándose en la altura de la textura
vFilterWidth = (768.0 / TextureSize.y) / 3.0;
// Pasar coordenadas de textura (invertir Y para SDL)
vTexCoord = vec2(aTexCoord.x, 1.0 - aTexCoord.y) * 1.0001;
// Posición del vértice (ya en espacio de clip [-1, 1])
gl_Position = vec4(aPosition, 0.0, 1.0);
}