Files
orni-attack/shaders/postfx.frag.glsl
T
JailDesigner a7aecbadd1 Fase 8c: postpro (bloom + flicker + background) en SDL_gpu
Renderiza la escena de líneas a una textura offscreen y aplica un pase
final de postpro que compone la imagen al swapchain. El shader del
postpro hace tres cosas:

- Bloom: kernel gaussiano 5×5 con high-pass por luminancia. Configurable
  vía intensity, threshold y radius_px.
- Flicker: multiplicador global de brillo modulado por sin(time*freq).
  Sustituye al antiguo ColorOscillator CPU; eliminados oscillator.{hpp,cpp}
  y Defaults::Color. SDLManager::updateColors queda como no-op para no
  tocar las escenas que lo invocaban.
- Background pulse: color de fondo aditivo entre color_min y color_max,
  pulsando en el tiempo.

Parámetros expuestos en data/config/postfx.yaml y cargados con fkYAML.
Si el archivo falta o falla, se usan defaults built-in. UV.y invertida
en el vertex shader del postpro para compensar la convención de
muestreo de SDL_gpu/Vulkan (el line shader sigue con su ndc.y flip).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 08:52:03 +02:00

83 lines
3.0 KiB
GLSL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#version 450
// Fragment shader del pase de postprocesado.
// Lee la textura offscreen (escena vectorial sobre fondo negro) y produce
// el fragmento final aplicando:
// 1. Bloom kernel 5×5 con high-pass (solo los brillos por encima de
// threshold contribuyen).
// 2. Flicker: multiplicador global de brillo modulado por tiempo
// (sustituye al oscilador CPU del legacy).
// 3. Background pulse: color de fondo que oscila entre min y max y se
// suma a la imagen (las líneas brillan por encima).
//
// Resource sets (SDL_gpu):
// set=2, binding=0 → sampler2D (escena offscreen)
// set=3, binding=0 → uniform buffer (parámetros del postpro)
layout(set = 2, binding = 0) uniform sampler2D scene;
layout(set = 3, binding = 0) uniform PostFxUBO {
float time;
float bloom_intensity;
float bloom_threshold;
float bloom_radius_px;
float flicker_amplitude;
float flicker_frequency_hz;
float background_pulse_freq_hz;
float _pad_a;
vec4 background_min; // RGB en [0..1], A=1
vec4 background_max; // RGB en [0..1], A=1
vec2 texel_size; // 1.0 / texture_size
vec2 _pad_b;
} ubo;
layout(location = 0) in vec2 v_uv;
layout(location = 0) out vec4 frag;
const float TAU = 6.28318530718;
void main() {
// === BLOOM ===
// Kernel 5×5 con muestreo radial y high-pass por luminancia (max RGB).
// Pesos gaussianos: w = exp(-(dx²+dy²) / 4).
vec3 src = texture(scene, v_uv).rgb;
vec3 bloom = vec3(0.0);
float total_weight = 0.0;
for (int dy = -2; dy <= 2; ++dy) {
for (int dx = -2; dx <= 2; ++dx) {
vec2 offset = vec2(float(dx), float(dy)) * ubo.texel_size * ubo.bloom_radius_px;
vec3 c = texture(scene, v_uv + offset).rgb;
float luma = max(c.r, max(c.g, c.b));
float high_pass = max(0.0, luma - ubo.bloom_threshold);
float w = exp(-(float(dx * dx + dy * dy)) / 4.0);
bloom += c * high_pass * w;
total_weight += w;
}
}
if (total_weight > 0.0) {
bloom /= total_weight;
}
bloom *= ubo.bloom_intensity;
// === FLICKER ===
// Multiplicador global de brillo. Oscila entre (1.0 - amplitude) y 1.0.
// amplitude=0 → sin flicker; amplitude=1 → pulsa entre apagado y máximo.
float pulse = (sin(ubo.time * ubo.flicker_frequency_hz * TAU) * 0.5) + 0.5;
float flicker = 1.0 - (ubo.flicker_amplitude * (1.0 - pulse));
// === BACKGROUND PULSE ===
// Suma de color de fondo oscilante. min..max se interpolan con sin(t).
float bg_pulse = (sin(ubo.time * ubo.background_pulse_freq_hz * TAU) * 0.5) + 0.5;
vec3 background = mix(ubo.background_min.rgb, ubo.background_max.rgb, bg_pulse);
// === COMPOSICIÓN ===
// El offscreen viene con clear=black, por lo que solo las líneas y el
// bloom aportan luz. Sumamos el fondo y luego multiplicamos por flicker
// para que el pulso afecte a todo (líneas + bloom + bg).
vec3 lines_and_glow = (src + bloom) * flicker;
frag = vec4(background + lines_and_glow, 1.0);
}