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>
This commit is contained in:
2026-05-20 08:52:03 +02:00
parent 6d7060ceb5
commit a7aecbadd1
19 changed files with 731 additions and 198 deletions
+14 -8
View File
@@ -9,6 +9,7 @@
#include <format>
#include <iostream>
#include "core/config/postfx_config.hpp"
#include "core/defaults.hpp"
#include "core/input/mouse.hpp"
#include "core/rendering/coordinate_transform.hpp"
@@ -48,6 +49,12 @@ auto initWindowAndGpu(SDL_Window** out_window,
}
gpu_renderer.setVSync(Options::rendering.vsync != 0);
// Cargar parámetros del postpro desde el resource pack. Si el YAML falta
// o falla, el loader devuelve los defaults built-in (bloom suave + flicker
// sutil + background verde tenue).
gpu_renderer.setPostFx(Config::PostFx::load("config/postfx.yaml"));
*out_window = window;
return true;
}
@@ -314,15 +321,13 @@ auto SDLManager::handleWindowEvent(const SDL_Event& event) -> bool {
}
void SDLManager::clear(uint8_t r, uint8_t g, uint8_t b) {
// Usar el color oscilatorio de fondo (sustituye los parámetros pasados,
// que solo existían por compatibilidad con la API anterior).
// El fondo lo dibuja ahora el shader de postpro (background pulse). El
// offscreen se limpia en negro dentro de beginFrame. Los argumentos r/g/b
// se mantienen por compatibilidad de API.
(void)r;
(void)g;
(void)b;
SDL_Color bg = color_oscillator_.getCurrentBackgroundColor();
gpu_renderer_.beginFrame(static_cast<float>(bg.r) / 255.0F,
static_cast<float>(bg.g) / 255.0F,
static_cast<float>(bg.b) / 255.0F);
gpu_renderer_.beginFrame(0.0F, 0.0F, 0.0F);
}
void SDLManager::present() {
@@ -330,8 +335,9 @@ void SDLManager::present() {
}
void SDLManager::updateColors(float delta_time) {
color_oscillator_.update(delta_time);
Rendering::setLineColor(color_oscillator_.getCurrentLineColor());
// No-op desde la migración a postpro. La oscilación de brillo y el pulso
// de fondo los aplica shaders/postfx.frag.glsl directamente sobre wall-clock.
(void)delta_time;
}
void SDLManager::updateFPS(float delta_time) {