From c6d409c303583f11eec652abd1553523399b48b0 Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Wed, 25 Mar 2026 22:31:34 +0100 Subject: [PATCH] =?UTF-8?q?corregides=20scanlines=20per=20a=20treballar=20?= =?UTF-8?q?amb=20subpixels=20per=20proporci=C3=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- data/shaders/postfx.frag | 20 +- data/shaders/postfx.frag.spv | Bin 0 -> 11712 bytes .../core/rendering/sdl3gpu/postfx_frag_spv.h | 1470 +++++++++++------ .../core/rendering/sdl3gpu/sdl3gpu_shader.cpp | 17 +- 4 files changed, 983 insertions(+), 524 deletions(-) create mode 100644 data/shaders/postfx.frag.spv diff --git a/data/shaders/postfx.frag b/data/shaders/postfx.frag index e840fb0..2a9788d 100644 --- a/data/shaders/postfx.frag +++ b/data/shaders/postfx.frag @@ -96,18 +96,22 @@ void main() { colour = mix(colour, lin, u.gamma_strength); } - // Scanlines — 1 pixel físico oscuro por fila lógica. - // Usa uv.y (independiente del offset de letterbox) con pixel_scale para - // calcular la posición dentro de la fila en coordenadas físicas. - // 3x: 1 dark + 2 bright. 4x: 1 dark + 3 bright. - // bright=3.5×, dark floor=0.42 (mantiene aspecto CRT original). - // ** MOD ** bright=1.0×, dark floor=0.42 (mantiene aspecto CRT original). + // 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 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); - float is_dark = step(ps - 1.0, row_pos); - float scan = mix(1.0, 0.42, is_dark); + // 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); colour *= mix(1.0, scan, u.scanline_strength); } diff --git a/data/shaders/postfx.frag.spv b/data/shaders/postfx.frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..f3207c12acbdaeb24a67b634a5ff45cc160655d3 GIT binary patch literal 11712 zcmb7}dAyZnwZ~sM97MobQF8*(B*l4_7|i6DVc?9FZui+|bJ%eP+-C!t4G^NHWrJpE zWu{q(H*+8dQk*iV)U;H}G)u#<(eieiZgs!kcfV`%-2J)#-1oEB=lQMQTF-jcdZzvE zb2^4i*gVTN%SLBgW`Ei&%b#ttVK7-{dnoPbY(%bi%{*=9fkTa+0}nsqU>�I&5;= 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 3) + const float SCAN_DARK_FLOOR = 0.42f; // multiplicador de brillo de subfilas oscuras if (u.scanline_strength > 0.0f) { float ps = max(1.0f, round(u.pixel_scale)); float frac_in_row = fract(uv.y * u.screen_height); float row_pos = floor(frac_in_row * ps); - float is_dark = step(ps - 1.0f, row_pos); - //float scan = mix(3.5f, 0.42f, is_dark); - float scan = mix(1.0f, 0.42f, is_dark); + float bright_rows = (ps < 2.0f) ? ps : ((ps < 3.0f) ? 1.0f : floor(ps * (1.0f - SCAN_DARK_RATIO))); + float is_dark = step(bright_rows, row_pos); + float scan = mix(1.0f, SCAN_DARK_FLOOR, is_dark); colour *= mix(1.0f, scan, u.scanline_strength); }