postfx: scanlines analítiques amb smoothstep a l'estil crtpi, exposant forma per preset YAML
This commit is contained in:
1 parent
4dc2654a66
commit
c9e6261cf1
8 files changed
+1287
-901
No files matched your search
+22
-17
@@ -6,7 +6,9 @@
|
||||
// xxd -i postfx.frag.spv > ../../source/core/rendering/sdl3gpu/postfx_frag_spv.h
|
||||
//
|
||||
// PostFXUniforms must match exactly the C++ struct in sdl3gpu_shader.hpp
|
||||
// (8 floats, 32 bytes, std140/scalar layout).
|
||||
// (16 floats = 4 × vec4 = 64 bytes, std140/scalar layout).
|
||||
// IMPORTANT: Qualsevol canvi ací cal replicar-lo a mà a
|
||||
// source/core/rendering/sdl3gpu/msl/postfx_frag.msl.h (no hi ha generador).
|
||||
|
||||
layout(location = 0) in vec2 v_uv;
|
||||
layout(location = 0) out vec4 out_color;
|
||||
@@ -25,7 +27,12 @@ layout(set = 3, binding = 0) uniform PostFXUniforms {
|
||||
float pixel_scale; // physical pixels per logical pixel (vh / tex_height_)
|
||||
float time; // seconds since SDL init
|
||||
float oversample; // supersampling factor (1.0 = off, 3.0 = 3×SS)
|
||||
float flicker; // 0 = off, 1 = phosphor flicker ~50 Hz — 48 bytes total (3 × 16)
|
||||
float flicker; // 0 = off, 1 = phosphor flicker ~50 Hz
|
||||
// vec4 #3 — paràmetres de scanlines (exposats per preset YAML)
|
||||
float scan_dark_ratio; // fracció de subfila fosca per fila lògica (1/3 ≈ 0.333)
|
||||
float scan_dark_floor; // multiplicador de brillantor de la subfila fosca
|
||||
float scan_edge_soft; // 0 = step dur; 1 = suavitzat d'1 píxel físic (estil crtpi)
|
||||
float pad3; // padding per tancar a 64 bytes (4 × vec4)
|
||||
} u;
|
||||
|
||||
// YCbCr helpers for NTSC bleeding
|
||||
@@ -96,22 +103,20 @@ void main() {
|
||||
colour = mix(colour, lin, u.gamma_strength);
|
||||
}
|
||||
|
||||
// Scanlines — proporción 2/3 brillantes + 1/3 oscuras por fila lógica.
|
||||
// Casos especiales: 1 subfila → sin efecto; 2 subfilas → 1+1 (50/50).
|
||||
// Constantes ajustables:
|
||||
const float SCAN_DARK_RATIO = 0.333; // fracción de subfilas oscuras (ps >= 3)
|
||||
const float SCAN_DARK_FLOOR = 0.42; // multiplicador de brillo de subfilas oscuras
|
||||
// Scanlines — tècnica dels 3 subpíxels verticals per píxel lògic (aee/projecte_2026):
|
||||
// franja fosca ocupant `scan_dark_ratio` al final de cada fila lògica. La transició es
|
||||
// suavitza amb smoothstep d'ample ≈ 1 píxel físic (estil crtpi: filtratge analític
|
||||
// continu), controlat per `scan_edge_soft`. A 0 és equivalent al step dur antic.
|
||||
if (u.scanline_strength > 0.0) {
|
||||
float ps = max(1.0, round(u.pixel_scale));
|
||||
float frac_in_row = fract(uv.y * u.screen_height);
|
||||
float row_pos = floor(frac_in_row * ps);
|
||||
// bright_rows: cuántas subfilas son brillantes
|
||||
// ps==1 → ps (todo brillante → is_dark nunca se activa)
|
||||
// ps==2 → 1 brillante + 1 oscura
|
||||
// ps>=3 → floor(ps * (1 - DARK_RATIO)) brillantes
|
||||
float bright_rows = (ps < 2.0) ? ps : ((ps < 3.0) ? 1.0 : floor(ps * (1.0 - SCAN_DARK_RATIO)));
|
||||
float is_dark = step(bright_rows, row_pos);
|
||||
float scan = mix(1.0, SCAN_DARK_FLOOR, is_dark);
|
||||
float ps = max(u.pixel_scale, 1.0);
|
||||
float sub = fract(uv.y * u.screen_height); // [0,1) dins la fila lògica
|
||||
float dark_center = 1.0 - u.scan_dark_ratio * 0.5; // centre de la franja fosca
|
||||
float d = abs(sub - dark_center);
|
||||
d = min(d, 1.0 - d); // wrap a la fila següent
|
||||
float half_width = u.scan_dark_ratio * 0.5;
|
||||
float softness = u.scan_edge_soft * 0.5 / ps; // mig píxel físic a cada costat
|
||||
float band = 1.0 - smoothstep(half_width - softness, half_width + softness, d);
|
||||
float scan = mix(1.0, u.scan_dark_floor, band);
|
||||
colour *= mix(1.0, scan, u.scanline_strength);
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user