From a51072db32d4d064582cf81f98323e712b9cad32 Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Fri, 20 Mar 2026 09:06:24 +0100 Subject: [PATCH] feat(postfx): redisseny sistema PostFX (X/F5/F6, --postfx CLI) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - X cicla 4 efectes (Vinyeta/Scanlines/Cromàtica/Complet), sempre activa PostFX - F5 fa toggle PostFX on/off mantenint l'efecte seleccionat - F6 hereta el toggle d'integer scaling (abans F5) - Arrencada per defecte sense postprocés (tot a 0) - --postfx per activar des de CLI Co-Authored-By: Claude Sonnet 4.6 --- source/engine.cpp | 51 ++++++++++++++++++++++++++-------- source/engine.hpp | 8 +++++- source/input/input_handler.cpp | 7 ++++- source/main.cpp | 24 ++++++++++++++++ 4 files changed, 77 insertions(+), 13 deletions(-) diff --git a/source/engine.cpp b/source/engine.cpp index aa3605c..7f0d082 100644 --- a/source/engine.cpp +++ b/source/engine.cpp @@ -1013,23 +1013,52 @@ void Engine::toggleRealFullscreen() { } } +void Engine::applyPostFXPreset(int mode) { + static constexpr float presets[4][3] = { + {1.5f, 0.0f, 0.0f}, // 0: Vinyeta + {1.5f, 0.0f, 0.8f}, // 1: Scanlines + {1.5f, 1.0f, 0.0f}, // 2: Cromàtica + {1.5f, 1.0f, 0.8f}, // 3: Complet + }; + postfx_uniforms_.vignette_strength = presets[mode][0]; + postfx_uniforms_.chroma_strength = presets[mode][1]; + postfx_uniforms_.scanline_strength = presets[mode][2]; +} + void Engine::handlePostFXCycle() { - static constexpr float presets[5][3] = { - {1.5f, 0.0f, 0.0f}, {1.5f, 0.0f, 0.8f}, - {1.5f, 1.0f, 0.0f}, {1.5f, 1.0f, 0.8f}, - {0.0f, 0.0f, 0.0f} - }; - static constexpr const char* names[5] = { + static constexpr const char* names[4] = { "PostFX: Vinyeta", "PostFX: Scanlines", - "PostFX: Cromàtica", "PostFX: Complet", "PostFX: Desactivat" + "PostFX: Cromàtica", "PostFX: Complet" }; - postfx_effect_mode_ = (postfx_effect_mode_ + 1) % 5; - postfx_uniforms_.vignette_strength = presets[postfx_effect_mode_][0]; - postfx_uniforms_.chroma_strength = presets[postfx_effect_mode_][1]; - postfx_uniforms_.scanline_strength = presets[postfx_effect_mode_][2]; + postfx_effect_mode_ = (postfx_effect_mode_ + 1) % 4; + postfx_enabled_ = true; + applyPostFXPreset(postfx_effect_mode_); showNotificationForAction(names[postfx_effect_mode_]); } +void Engine::handlePostFXToggle() { + static constexpr const char* names[4] = { + "PostFX: Vinyeta", "PostFX: Scanlines", + "PostFX: Cromàtica", "PostFX: Complet" + }; + postfx_enabled_ = !postfx_enabled_; + if (postfx_enabled_) { + applyPostFXPreset(postfx_effect_mode_); + showNotificationForAction(names[postfx_effect_mode_]); + } else { + postfx_uniforms_.vignette_strength = 0.0f; + postfx_uniforms_.chroma_strength = 0.0f; + postfx_uniforms_.scanline_strength = 0.0f; + showNotificationForAction("PostFX: Desactivat"); + } +} + +void Engine::setInitialPostFX(int mode) { + postfx_effect_mode_ = mode; + postfx_enabled_ = true; + applyPostFXPreset(mode); +} + void Engine::toggleIntegerScaling() { // Solo permitir cambio si estamos en modo fullscreen normal (F3) if (!fullscreen_enabled_) { diff --git a/source/engine.hpp b/source/engine.hpp index 1ef68e9..a232da0 100644 --- a/source/engine.hpp +++ b/source/engine.hpp @@ -78,6 +78,8 @@ class Engine { // PostFX presets void handlePostFXCycle(); + void handlePostFXToggle(); + void setInitialPostFX(int mode); // Modo kiosko void setKioskMode(bool enabled) { kiosk_mode_ = enabled; } @@ -170,8 +172,9 @@ class Engine { float delta_time_ = 0.0f; // PostFX uniforms (passed to GPU each frame) - PostFXUniforms postfx_uniforms_ = {1.5f, 0.0f, 0.0f, 0.0f}; + PostFXUniforms postfx_uniforms_ = {0.0f, 0.0f, 0.0f, 0.0f}; int postfx_effect_mode_ = 0; + bool postfx_enabled_ = false; // Sistema de zoom dinámico int current_window_zoom_ = DEFAULT_WINDOW_ZOOM; @@ -244,6 +247,9 @@ class Engine { void updateShape(); void generateShape(); + // PostFX helper + void applyPostFXPreset(int mode); + // GPU helpers bool loadGpuSpriteTexture(size_t index); // Upload one sprite texture to GPU void recreateOffscreenTexture(); // Recreate when resolution changes diff --git a/source/input/input_handler.cpp b/source/input/input_handler.cpp index 6730651..936353e 100644 --- a/source/input/input_handler.cpp +++ b/source/input/input_handler.cpp @@ -254,8 +254,13 @@ bool InputHandler::processEvents(Engine& engine) { else engine.toggleRealFullscreen(); break; - // Toggle escalado entero/estirado (solo en fullscreen F3) + // Toggle PostFX activo/inactivo case SDLK_F5: + engine.handlePostFXToggle(); + break; + + // Toggle escalado entero/estirado (solo en fullscreen F3) + case SDLK_F6: engine.toggleIntegerScaling(); break; diff --git a/source/main.cpp b/source/main.cpp index 7957c14..880e08d 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -21,6 +21,7 @@ void printHelp() { std::cout << " --custom-balls Activa escenario custom (tecla 9) con N pelotas\n"; std::cout << " --skip-benchmark Salta el benchmark y usa el máximo de bolas (50000)\n"; std::cout << " --max-balls Limita el máximo de bolas en modos DEMO/DEMO_LITE\n"; + std::cout << " --postfx Arrancar con PostFX activo: vinyeta, scanlines, cromatica, complet\n"; std::cout << " --help Mostrar esta ayuda\n\n"; std::cout << "Ejemplos:\n"; std::cout << " vibe3_physics # 320x240 zoom 3 (ventana 960x720)\n"; @@ -45,6 +46,7 @@ int main(int argc, char* argv[]) { bool kiosk_mode = false; bool skip_benchmark = false; int max_balls_override = 0; + int initial_postfx = -1; AppMode initial_mode = AppMode::SANDBOX; // Modo inicial (default: SANDBOX) // Parsear argumentos @@ -124,6 +126,25 @@ int main(int argc, char* argv[]) { } } else if (strcmp(argv[i], "--skip-benchmark") == 0) { skip_benchmark = true; + } else if (strcmp(argv[i], "--postfx") == 0) { + if (i + 1 < argc) { + std::string fx = argv[++i]; + if (fx == "vinyeta") { + initial_postfx = 0; + } else if (fx == "scanlines") { + initial_postfx = 1; + } else if (fx == "cromatica") { + initial_postfx = 2; + } else if (fx == "complet") { + initial_postfx = 3; + } else { + std::cerr << "Error: --postfx '" << fx << "' no válido. Usa: vinyeta, scanlines, cromatica, complet\n"; + return -1; + } + } else { + std::cerr << "Error: --postfx requiere un valor\n"; + return -1; + } } else if (strcmp(argv[i], "--max-balls") == 0) { if (i + 1 < argc) { int n = atoi(argv[++i]); @@ -158,6 +179,9 @@ int main(int argc, char* argv[]) { else if (skip_benchmark) engine.setSkipBenchmark(); + if (initial_postfx >= 0) + engine.setInitialPostFX(initial_postfx); + if (!engine.initialize(width, height, zoom, fullscreen, initial_mode)) { std::cout << "¡Error al inicializar el engine!" << std::endl; return -1;