treballant en poder incloure diferents shaders
This commit is contained in:
152
data/shaders/crtpi_frag.glsl
Normal file
152
data/shaders/crtpi_frag.glsl
Normal file
@@ -0,0 +1,152 @@
|
||||
#version 450
|
||||
|
||||
// Vulkan GLSL fragment shader — CRT-Pi PostFX
|
||||
// Algoritmo de scanlines continuas con pesos gaussianos, bloom y máscara de fósforo.
|
||||
// Basado en el shader CRT-Pi original (GLSL 3.3), portado a GLSL 4.50 con parámetros uniformes.
|
||||
//
|
||||
// Compile: glslc -fshader-stage=frag --target-env=vulkan1.0 crtpi_frag.glsl -o crtpi_frag.spv
|
||||
// xxd -i crtpi_frag.spv > ../../source/core/rendering/sdl3gpu/crtpi_frag_spv.h
|
||||
|
||||
layout(location = 0) in vec2 v_uv;
|
||||
layout(location = 0) out vec4 out_color;
|
||||
|
||||
layout(set = 2, binding = 0) uniform sampler2D Texture;
|
||||
|
||||
layout(set = 3, binding = 0) uniform CrtPiBlock {
|
||||
// vec4 #0
|
||||
float scanline_weight; // Ajuste gaussiano de scanlines (default 6.0)
|
||||
float scanline_gap_brightness; // Brillo mínimo entre scanlines (default 0.12)
|
||||
float bloom_factor; // Factor de brillo en zonas iluminadas (default 3.5)
|
||||
float input_gamma; // Gamma de entrada — linealización (default 2.4)
|
||||
// vec4 #1
|
||||
float output_gamma; // Gamma de salida — codificación (default 2.2)
|
||||
float mask_brightness; // Brillo sub-píxeles de la máscara (default 0.80)
|
||||
float curvature_x; // Distorsión barrel eje X (default 0.05)
|
||||
float curvature_y; // Distorsión barrel eje Y (default 0.10)
|
||||
// vec4 #2
|
||||
int mask_type; // 0=ninguna, 1=verde/magenta, 2=RGB fósforo
|
||||
int enable_scanlines; // 0 = off, 1 = on
|
||||
int enable_multisample; // 0 = off, 1 = on (antialiasing analítico de scanlines)
|
||||
int enable_gamma; // 0 = off, 1 = on
|
||||
// vec4 #3
|
||||
int enable_curvature; // 0 = off, 1 = on
|
||||
int enable_sharper; // 0 = off, 1 = on
|
||||
float texture_width; // Ancho del canvas lógico en píxeles
|
||||
float texture_height; // Alto del canvas lógico en píxeles
|
||||
} u;
|
||||
|
||||
// Distorsión barrel CRT
|
||||
vec2 distort(vec2 coord, vec2 screen_scale) {
|
||||
vec2 curvature = vec2(u.curvature_x, u.curvature_y);
|
||||
vec2 barrel_scale = 1.0 - (0.23 * curvature);
|
||||
coord *= screen_scale;
|
||||
coord -= vec2(0.5);
|
||||
float rsq = coord.x * coord.x + coord.y * coord.y;
|
||||
coord += coord * (curvature * rsq);
|
||||
coord *= barrel_scale;
|
||||
if (abs(coord.x) >= 0.5 || abs(coord.y) >= 0.5) {
|
||||
return vec2(-1.0); // fuera de pantalla
|
||||
}
|
||||
coord += vec2(0.5);
|
||||
coord /= screen_scale;
|
||||
return coord;
|
||||
}
|
||||
|
||||
float calcScanLineWeight(float dist) {
|
||||
return max(1.0 - dist * dist * u.scanline_weight, u.scanline_gap_brightness);
|
||||
}
|
||||
|
||||
float calcScanLine(float dy, float filter_width) {
|
||||
float weight = calcScanLineWeight(dy);
|
||||
if (u.enable_multisample != 0) {
|
||||
weight += calcScanLineWeight(dy - filter_width);
|
||||
weight += calcScanLineWeight(dy + filter_width);
|
||||
weight *= 0.3333333;
|
||||
}
|
||||
return weight;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 tex_size = vec2(u.texture_width, u.texture_height);
|
||||
|
||||
// filterWidth: equivalente al original (768.0 / TextureSize.y) / 3.0
|
||||
float filter_width = (768.0 / u.texture_height) / 3.0;
|
||||
|
||||
vec2 texcoord = v_uv;
|
||||
|
||||
// Curvatura barrel opcional
|
||||
if (u.enable_curvature != 0) {
|
||||
texcoord = distort(texcoord, vec2(1.0, 1.0));
|
||||
if (texcoord.x < 0.0) {
|
||||
out_color = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
vec2 texcoord_in_pixels = texcoord * tex_size;
|
||||
vec2 tc;
|
||||
float scan_line_weight;
|
||||
|
||||
if (u.enable_sharper != 0) {
|
||||
// Modo SHARPER: filtrado bicúbico-like con subpixel sharpen
|
||||
vec2 temp_coord = floor(texcoord_in_pixels) + 0.5;
|
||||
tc = temp_coord / tex_size;
|
||||
vec2 deltas = texcoord_in_pixels - temp_coord;
|
||||
scan_line_weight = calcScanLine(deltas.y, filter_width);
|
||||
vec2 signs = sign(deltas);
|
||||
deltas.x *= 2.0;
|
||||
deltas = deltas * deltas;
|
||||
deltas.y = deltas.y * deltas.y;
|
||||
deltas.x *= 0.5;
|
||||
deltas.y *= 8.0;
|
||||
deltas /= tex_size;
|
||||
deltas *= signs;
|
||||
tc = tc + deltas;
|
||||
} else {
|
||||
// Modo estándar
|
||||
float temp_y = floor(texcoord_in_pixels.y) + 0.5;
|
||||
float y_coord = temp_y / tex_size.y;
|
||||
float dy = texcoord_in_pixels.y - temp_y;
|
||||
scan_line_weight = calcScanLine(dy, filter_width);
|
||||
float sign_y = sign(dy);
|
||||
dy = dy * dy;
|
||||
dy = dy * dy;
|
||||
dy *= 8.0;
|
||||
dy /= tex_size.y;
|
||||
dy *= sign_y;
|
||||
tc = vec2(texcoord.x, y_coord + dy);
|
||||
}
|
||||
|
||||
vec3 colour = texture(Texture, tc).rgb;
|
||||
|
||||
if (u.enable_scanlines != 0) {
|
||||
if (u.enable_gamma != 0) {
|
||||
colour = pow(colour, vec3(u.input_gamma));
|
||||
}
|
||||
colour *= scan_line_weight * u.bloom_factor;
|
||||
if (u.enable_gamma != 0) {
|
||||
colour = pow(colour, vec3(1.0 / u.output_gamma));
|
||||
}
|
||||
}
|
||||
|
||||
// Máscara de fósforo
|
||||
if (u.mask_type == 1) {
|
||||
float which_mask = fract(gl_FragCoord.x * 0.5);
|
||||
vec3 mask = (which_mask < 0.5)
|
||||
? vec3(u.mask_brightness, 1.0, u.mask_brightness)
|
||||
: vec3(1.0, u.mask_brightness, 1.0);
|
||||
colour *= mask;
|
||||
} else if (u.mask_type == 2) {
|
||||
float which_mask = fract(gl_FragCoord.x * 0.3333333);
|
||||
vec3 mask = vec3(u.mask_brightness);
|
||||
if (which_mask < 0.3333333)
|
||||
mask.x = 1.0;
|
||||
else if (which_mask < 0.6666666)
|
||||
mask.y = 1.0;
|
||||
else
|
||||
mask.z = 1.0;
|
||||
colour *= mask;
|
||||
}
|
||||
|
||||
out_color = vec4(colour, 1.0);
|
||||
}
|
||||
Reference in New Issue
Block a user