From 270cd1d487c0cab6bde1346744ac6ae5be6f2546 Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Mon, 23 Mar 2026 17:04:21 +0100 Subject: [PATCH] eliminades referencies a opengl --- config/assets.txt | 8 ----- data/lang/ba_BA.json | 4 ++- data/lang/en_UK.json | 4 ++- data/lang/es_ES.json | 4 ++- data/shaders/postfx.frag | 8 ++--- source/defaults.hpp | 3 +- source/global_events.cpp | 2 +- source/global_inputs.cpp | 21 +++++++----- source/input.hpp | 3 +- source/input_types.cpp | 6 ++-- source/input_types.hpp | 3 +- source/options.cpp | 38 ++++++++++++++++----- source/options.hpp | 5 ++- source/rendering/sdl3gpu/sdl3gpu_shader.cpp | 14 ++++---- source/rendering/sdl3gpu/sdl3gpu_shader.hpp | 2 +- source/rendering/shader_backend.hpp | 4 +-- source/screen.cpp | 35 ++++++++----------- source/screen.hpp | 4 +-- source/ui/service_menu.cpp | 16 +++++++-- 19 files changed, 104 insertions(+), 80 deletions(-) diff --git a/config/assets.txt b/config/assets.txt index 9e2025a..d4be10f 100644 --- a/config/assets.txt +++ b/config/assets.txt @@ -75,14 +75,6 @@ SOUND|/data/sound/voice_recover.wav SOUND|/data/sound/voice_thankyou.wav SOUND|/data/sound/walk.wav -# Shaders OpenGL Desktop 3.3 (Windows/Linux) -DATA|/data/shaders/crtpi_vertex.glsl -DATA|/data/shaders/crtpi_fragment.glsl - -# Shaders OpenGL ES 3.0 (Raspberry Pi) - opcionales -DATA|/data/shaders/crtpi_vertex_es.glsl|optional -DATA|/data/shaders/crtpi_fragment_es.glsl|optional - # Texturas - Balloons ANIMATION|/data/gfx/balloon/balloon0.ani ANIMATION|/data/gfx/balloon/balloon1.ani diff --git a/data/lang/ba_BA.json b/data/lang/ba_BA.json index 0427505..5387d43 100644 --- a/data/lang/ba_BA.json +++ b/data/lang/ba_BA.json @@ -79,7 +79,9 @@ "[SERVICE_MENU] SHUTDOWN": "Apagar el sistema", "[SERVICE_MENU] FULLSCREEN": "Pantalla completa", "[SERVICE_MENU] WINDOW_SIZE": "Tamany de la finestra", - "[SERVICE_MENU] SHADERS": "Filtre", + "[SERVICE_MENU] POSTFX": "PostFX", + "[SERVICE_MENU] POSTFX_PRESET": "Preset PostFX", + "[SERVICE_MENU] SUPERSAMPLING": "Supermostreig", "[SERVICE_MENU] VSYNC": "Sincronisme vertical", "[SERVICE_MENU] INTEGER_SCALE": "Escalat sencer", "[SERVICE_MENU] MAIN_VOLUME": "Volumen general", diff --git a/data/lang/en_UK.json b/data/lang/en_UK.json index 5b3363d..9d2d655 100644 --- a/data/lang/en_UK.json +++ b/data/lang/en_UK.json @@ -78,7 +78,9 @@ "[SERVICE_MENU] SHUTDOWN": "Shutdown System", "[SERVICE_MENU] FULLSCREEN": "Fullscreen", "[SERVICE_MENU] WINDOW_SIZE": "Window Zoom", - "[SERVICE_MENU] SHADERS": "Shaders", + "[SERVICE_MENU] POSTFX": "PostFX", + "[SERVICE_MENU] POSTFX_PRESET": "PostFX Preset", + "[SERVICE_MENU] SUPERSAMPLING": "Supersampling", "[SERVICE_MENU] VSYNC": "V-Sync", "[SERVICE_MENU] INTEGER_SCALE": "Integer Scale", "[SERVICE_MENU] MAIN_VOLUME": "Main Volume", diff --git a/data/lang/es_ES.json b/data/lang/es_ES.json index 4c88022..650ad45 100644 --- a/data/lang/es_ES.json +++ b/data/lang/es_ES.json @@ -78,7 +78,9 @@ "[SERVICE_MENU] SHUTDOWN": "Apagar el sistema", "[SERVICE_MENU] FULLSCREEN": "Pantalla completa", "[SERVICE_MENU] WINDOW_SIZE": "Zoom de ventana", - "[SERVICE_MENU] SHADERS": "Filtro grafico", + "[SERVICE_MENU] POSTFX": "PostFX", + "[SERVICE_MENU] POSTFX_PRESET": "Preset PostFX", + "[SERVICE_MENU] SUPERSAMPLING": "Supersampling", "[SERVICE_MENU] VSYNC": "Sincronismo vertical", "[SERVICE_MENU] INTEGER_SCALE": "Escalado proporcional", "[SERVICE_MENU] MAIN_VOLUME": "Volumen general", diff --git a/data/shaders/postfx.frag b/data/shaders/postfx.frag index 9a66a9f..238c7a7 100644 --- a/data/shaders/postfx.frag +++ b/data/shaders/postfx.frag @@ -97,16 +97,14 @@ void main() { } // 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). + // Modelo sustractivo: las filas de scanline se oscurecen, las demás no cambian. + // Esto evita el efecto de sobrebrillo en contenido con colores vivos. 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(3.5, 0.42, is_dark); + float scan = mix(1.0, 0.0, is_dark); colour *= mix(1.0, scan, u.scanline_strength); } diff --git a/source/defaults.hpp b/source/defaults.hpp index 47a4cf2..e5c90fb 100644 --- a/source/defaults.hpp +++ b/source/defaults.hpp @@ -220,9 +220,8 @@ namespace GameDefaults { constexpr bool VIDEO_FULLSCREEN = false; constexpr bool VIDEO_VSYNC = true; constexpr bool VIDEO_INTEGER_SCALE = true; - constexpr bool VIDEO_SHADERS = false; constexpr bool VIDEO_POSTFX = false; - constexpr bool VIDEO_SUPERSAMPLING = false; + constexpr int VIDEO_SUPERSAMPLING = 1; // 1 = off, 2 = 2×, 3 = 3× SS // Music constexpr bool MUSIC_ENABLED = true; diff --git a/source/global_events.cpp b/source/global_events.cpp index e35c0a1..f30b2d4 100644 --- a/source/global_events.cpp +++ b/source/global_events.cpp @@ -54,7 +54,7 @@ namespace GlobalEvents { break; case SDL_EVENT_WINDOW_RESIZED: - Screen::initShaders(); + Screen::initPostFX(); break; default: diff --git a/source/global_inputs.cpp b/source/global_inputs.cpp index ab0f310..c9e1357 100644 --- a/source/global_inputs.cpp +++ b/source/global_inputs.cpp @@ -78,7 +78,9 @@ namespace GlobalInputs { // Activa o desactiva el supersampling 3x void toggleSupersampling() { Screen::toggleSupersampling(); - Notifier::get()->show({"3x SS: " + boolToOnOff(Options::video.supersampling)}); + const int SS = Options::video.supersampling; + const std::string SS_LABEL = (SS <= 1) ? "OFF" : (std::to_string(SS) + "\xC3\x97"); + Notifier::get()->show({"SS: " + SS_LABEL}); } // Cambia al siguiente idioma @@ -199,15 +201,16 @@ namespace GlobalInputs { return true; } - // F4 con modificadores: Ctrl+F4 = supersampling, Shift+F4 = siguiente preset, F4 = toggle PostFX if (Input::get()->checkAction(Input::Action::TOGGLE_VIDEO_POSTFX, Input::DO_NOT_ALLOW_REPEAT, Input::CHECK_KEYBOARD)) { - if ((SDL_GetModState() & SDL_KMOD_CTRL) != 0U) { - toggleSupersampling(); - } else if (Options::video.postfx && ((SDL_GetModState() & SDL_KMOD_SHIFT) != 0U)) { - nextPostFXPreset(); - } else { - togglePostFX(); - } + togglePostFX(); + return true; + } + if (Input::get()->checkAction(Input::Action::NEXT_POSTFX_PRESET, Input::DO_NOT_ALLOW_REPEAT, Input::CHECK_KEYBOARD)) { + nextPostFXPreset(); + return true; + } + if (Input::get()->checkAction(Input::Action::TOGGLE_SUPERSAMPLING, Input::DO_NOT_ALLOW_REPEAT, Input::CHECK_KEYBOARD)) { + toggleSupersampling(); return true; } diff --git a/source/input.hpp b/source/input.hpp index fac9dfa..4c2fcb7 100644 --- a/source/input.hpp +++ b/source/input.hpp @@ -81,8 +81,9 @@ class Input { {Action::WINDOW_DEC_SIZE, KeyState(SDL_SCANCODE_F1)}, {Action::WINDOW_INC_SIZE, KeyState(SDL_SCANCODE_F2)}, {Action::WINDOW_FULLSCREEN, KeyState(SDL_SCANCODE_F3)}, - {Action::TOGGLE_VIDEO_SHADERS, KeyState(SDL_SCANCODE_F4)}, {Action::TOGGLE_VIDEO_POSTFX, KeyState(SDL_SCANCODE_F4)}, + {Action::NEXT_POSTFX_PRESET, KeyState(SDL_SCANCODE_9)}, + {Action::TOGGLE_SUPERSAMPLING, KeyState(SDL_SCANCODE_0)}, {Action::TOGGLE_VIDEO_INTEGER_SCALE, KeyState(SDL_SCANCODE_F5)}, {Action::TOGGLE_VIDEO_VSYNC, KeyState(SDL_SCANCODE_F6)}, diff --git a/source/input_types.cpp b/source/input_types.cpp index 8ac1832..06c646a 100644 --- a/source/input_types.cpp +++ b/source/input_types.cpp @@ -21,8 +21,9 @@ const std::unordered_map ACTION_TO_STRING = { {InputAction::WINDOW_FULLSCREEN, "WINDOW_FULLSCREEN"}, {InputAction::WINDOW_INC_SIZE, "WINDOW_INC_SIZE"}, {InputAction::WINDOW_DEC_SIZE, "WINDOW_DEC_SIZE"}, - {InputAction::TOGGLE_VIDEO_SHADERS, "TOGGLE_VIDEO_SHADERS"}, {InputAction::TOGGLE_VIDEO_POSTFX, "TOGGLE_VIDEO_POSTFX"}, + {InputAction::NEXT_POSTFX_PRESET, "NEXT_POSTFX_PRESET"}, + {InputAction::TOGGLE_SUPERSAMPLING, "TOGGLE_SUPERSAMPLING"}, {InputAction::TOGGLE_VIDEO_INTEGER_SCALE, "TOGGLE_VIDEO_INTEGER_SCALE"}, {InputAction::TOGGLE_VIDEO_VSYNC, "TOGGLE_VIDEO_VSYNC"}, {InputAction::RESET, "RESET"}, @@ -52,8 +53,9 @@ const std::unordered_map STRING_TO_ACTION = { {"WINDOW_FULLSCREEN", InputAction::WINDOW_FULLSCREEN}, {"WINDOW_INC_SIZE", InputAction::WINDOW_INC_SIZE}, {"WINDOW_DEC_SIZE", InputAction::WINDOW_DEC_SIZE}, - {"TOGGLE_VIDEO_SHADERS", InputAction::TOGGLE_VIDEO_SHADERS}, {"TOGGLE_VIDEO_POSTFX", InputAction::TOGGLE_VIDEO_POSTFX}, + {"NEXT_POSTFX_PRESET", InputAction::NEXT_POSTFX_PRESET}, + {"TOGGLE_SUPERSAMPLING", InputAction::TOGGLE_SUPERSAMPLING}, {"TOGGLE_VIDEO_INTEGER_SCALE", InputAction::TOGGLE_VIDEO_INTEGER_SCALE}, {"TOGGLE_VIDEO_VSYNC", InputAction::TOGGLE_VIDEO_VSYNC}, {"RESET", InputAction::RESET}, diff --git a/source/input_types.hpp b/source/input_types.hpp index d310f66..c4fe226 100644 --- a/source/input_types.hpp +++ b/source/input_types.hpp @@ -31,8 +31,9 @@ enum class InputAction : int { // Acciones de entrada posibles en el juego WINDOW_FULLSCREEN, WINDOW_INC_SIZE, WINDOW_DEC_SIZE, - TOGGLE_VIDEO_SHADERS, // backward compat alias TOGGLE_VIDEO_POSTFX, + NEXT_POSTFX_PRESET, + TOGGLE_SUPERSAMPLING, TOGGLE_VIDEO_INTEGER_SCALE, TOGGLE_VIDEO_VSYNC, RESET, diff --git a/source/options.cpp b/source/options.cpp index a946efc..6990a15 100644 --- a/source/options.cpp +++ b/source/options.cpp @@ -245,19 +245,41 @@ namespace Options { if (vid.contains("integer_scale")) { try { video.integer_scale = vid["integer_scale"].get_value(); } catch (...) {} } - if (vid.contains("shaders")) { - try { video.shaders = vid["shaders"].get_value(); } catch (...) {} - } if (vid.contains("postfx")) { try { video.postfx = vid["postfx"].get_value(); } catch (...) {} } - if (vid.contains("supersampling")) { - try { video.supersampling = vid["supersampling"].get_value(); } catch (...) {} + // Nuevo formato: supersampling (bool) + supersampling_amount (int) + // Backward compat: si solo existe supersampling como int, también funciona + { + bool ss_enabled = false; + int ss_amount = 3; + if (vid.contains("supersampling")) { + try { + const auto& node = vid["supersampling"]; + if (node.is_boolean()) { + ss_enabled = node.get_value(); + } else { + // Formato antiguo: int directamente + int factor = node.get_value(); + ss_enabled = factor >= 2; + ss_amount = (factor >= 2) ? factor : 3; + } + } catch (...) {} + } + if (vid.contains("supersampling_amount")) { + try { + int amount = vid["supersampling_amount"].get_value(); + if (amount >= 2) { ss_amount = amount; } + } catch (...) {} + } + video.supersampling = ss_enabled ? ss_amount : 1; } if (vid.contains("postfx_preset")) { try { int preset = vid["postfx_preset"].get_value(); - if (preset >= 0 && preset < static_cast(postfx_presets.size())) { + // No validamos contra postfx_presets.size() aquí porque postfx.yaml + // aún no se ha cargado. El clamp se hace en loadPostFXFromFile(). + if (preset >= 0) { current_postfx_preset = preset; } } catch (...) {} @@ -430,10 +452,10 @@ namespace Options { file << " scale_mode: " << static_cast(video.scale_mode) << " # " << static_cast(SDL_ScaleMode::SDL_SCALEMODE_NEAREST) << ": nearest, " << static_cast(SDL_ScaleMode::SDL_SCALEMODE_LINEAR) << ": linear\n"; file << " vsync: " << boolToString(video.vsync) << "\n"; file << " integer_scale: " << boolToString(video.integer_scale) << "\n"; - file << " shaders: " << boolToString(video.shaders) << "\n"; file << " postfx: " << boolToString(video.postfx) << "\n"; - file << " supersampling: " << boolToString(video.supersampling) << "\n"; file << " postfx_preset: " << current_postfx_preset << "\n"; + file << " supersampling: " << boolToString(video.supersampling > 1) << "\n"; + file << " supersampling_amount: " << std::max(2, video.supersampling) << "\n"; file << "\n"; // AUDIO diff --git a/source/options.hpp b/source/options.hpp index 08b7369..8b1ea90 100644 --- a/source/options.hpp +++ b/source/options.hpp @@ -13,7 +13,7 @@ #include // Para move #include // Para vector -#include "defaults.hpp" // for AUDIO_ENABLED, AUDIO_VOLUME, MUSIC_ENABLED, MUSIC_VOLUME, PARAMS_FILE, SETTINGS_AUTOFIRE, SETTINGS_SHUTDOWN_ENABLED, SOUND_ENABLED, SOUND_VOLUME, VIDEO_FULLSCREEN, VIDEO_INTEGER_SCALE, VIDEO_SCALE_MODE, VIDEO_SHADERS, VIDEO_VSYNC, WINDOW_CAPTION, WINDOW_MAX_ZOOM, WINDOW_ZOOM +#include "defaults.hpp" // for AUDIO_ENABLED, AUDIO_VOLUME, MUSIC_ENABLED, MUSIC_VOLUME, PARAMS_FILE, SETTINGS_AUTOFIRE, SETTINGS_SHUTDOWN_ENABLED, SOUND_ENABLED, SOUND_VOLUME, VIDEO_FULLSCREEN, VIDEO_INTEGER_SCALE, VIDEO_SCALE_MODE, VIDEO_VSYNC, WINDOW_CAPTION, WINDOW_MAX_ZOOM, WINDOW_ZOOM #include "difficulty.hpp" // for Code #include "input.hpp" // for Input #include "lang.hpp" // for Code @@ -47,9 +47,8 @@ namespace Options { bool fullscreen = GameDefaults::Options::VIDEO_FULLSCREEN; // Indica si se usa pantalla completa bool vsync = GameDefaults::Options::VIDEO_VSYNC; // Indica si se usa vsync bool integer_scale = GameDefaults::Options::VIDEO_INTEGER_SCALE; // Indica si se usa escalado entero - bool shaders = GameDefaults::Options::VIDEO_SHADERS; // Indica si se usan shaders para los filtros de vídeo (backward compat) bool postfx = GameDefaults::Options::VIDEO_POSTFX; // Indica si se usan efectos PostFX - bool supersampling = GameDefaults::Options::VIDEO_SUPERSAMPLING; // Indica si se usa supersampling 3x + int supersampling = GameDefaults::Options::VIDEO_SUPERSAMPLING; // Factor de supersampling: 1=off, 2=2×, 3=3× std::string info; // Información sobre el modo de vídeo }; diff --git a/source/rendering/sdl3gpu/sdl3gpu_shader.cpp b/source/rendering/sdl3gpu/sdl3gpu_shader.cpp index b4e0860..9ed8b5c 100644 --- a/source/rendering/sdl3gpu/sdl3gpu_shader.cpp +++ b/source/rendering/sdl3gpu/sdl3gpu_shader.cpp @@ -131,16 +131,14 @@ fragment float4 postfx_fs(PostVOut in [[stage_in]], } // 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). + // Modelo sustractivo: las filas de scanline se oscurecen, las demás no cambian. + // Esto evita el efecto de sobrebrillo en contenido con colores vivos. 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.0f, is_dark); colour *= mix(1.0f, scan, u.scanline_strength); } @@ -388,11 +386,11 @@ namespace Rendering { std::memcpy(mapped, pixels, static_cast(width * height * 4)); } else { // Path con supersampling: expande cada pixel a OS×OS, oscurece última fila. - // Replica la fórmula del shader: mix(3.5, 0.42, scanline_strength). + // Modelo sustractivo: filas normales sin cambio, fila de scanline oscurecida a 0. auto* out = static_cast(mapped); const int OS = oversample_; - const float BRIGHT_MUL = 1.0F + (baked_scanline_strength_ * 2.5F); // rows 0..OS-2 - const float DARK_MUL = 1.0F - (baked_scanline_strength_ * 0.58F); // row OS-1 + const float BRIGHT_MUL = 1.0F; // rows 0..OS-2: sin cambio + const float DARK_MUL = 1.0F - baked_scanline_strength_; // row OS-1: hasta negro for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { diff --git a/source/rendering/sdl3gpu/sdl3gpu_shader.hpp b/source/rendering/sdl3gpu/sdl3gpu_shader.hpp index 1fcef3c..c126bc1 100644 --- a/source/rendering/sdl3gpu/sdl3gpu_shader.hpp +++ b/source/rendering/sdl3gpu/sdl3gpu_shader.hpp @@ -28,7 +28,7 @@ namespace Rendering { /** * @brief Backend de shaders usando SDL3 GPU API (Metal en macOS, Vulkan/SPIR-V en Win/Linux) * - * Reemplaza el backend OpenGL para que los shaders PostFX funcionen en macOS. + * Backend de shaders PostFX para macOS (Metal) y Win/Linux (Vulkan/SPIR-V). * Pipeline: Surface pixels (CPU) → SDL_GPUTransferBuffer → SDL_GPUTexture (scene) * → PostFX render pass → swapchain → present */ diff --git a/source/rendering/shader_backend.hpp b/source/rendering/shader_backend.hpp index 8f99b6e..2bcfa2c 100644 --- a/source/rendering/shader_backend.hpp +++ b/source/rendering/shader_backend.hpp @@ -24,7 +24,7 @@ namespace Rendering { * @brief Interfaz abstracta para backends de renderizado con shaders * * Esta interfaz define el contrato que todos los backends de shaders - * deben cumplir (OpenGL, Metal, Vulkan, etc.) + * deben cumplir (Metal, Vulkan, etc.) */ class ShaderBackend { public: @@ -62,7 +62,7 @@ namespace Rendering { /** * @brief Verifica si el backend está usando aceleración por hardware - * @return true si usa aceleración (OpenGL/Metal/Vulkan) + * @return true si usa aceleración por hardware */ [[nodiscard]] virtual auto isHardwareAccelerated() const -> bool = 0; diff --git a/source/screen.cpp b/source/screen.cpp index 9072f01..059c47e 100644 --- a/source/screen.cpp +++ b/source/screen.cpp @@ -25,7 +25,7 @@ Screen* Screen::instance = nullptr; // Inicializa la instancia única del singleton void Screen::init() { Screen::instance = new Screen(); - Screen::initShaders(); // Llamar aquí para que Screen::get() ya devuelva la instancia + Screen::initPostFX(); // Llamar aquí para que Screen::get() ya devuelva la instancia } // Libera la instancia @@ -256,12 +256,12 @@ void Screen::renderInfo() const { } } #endif -// Inicializa los shaders (SDL3GPU) -void Screen::initShaders() { +// Inicializa PostFX (SDL3GPU) +void Screen::initPostFX() { #ifndef NO_SHADERS auto* self = Screen::get(); if (self == nullptr) { - SDL_Log("Screen::initShaders: instance is null, skipping"); + SDL_Log("Screen::initPostFX: instance is null, skipping"); return; } if (!self->shader_backend_) { @@ -269,9 +269,9 @@ void Screen::initShaders() { } if (!self->shader_backend_->isHardwareAccelerated()) { const bool ok = self->shader_backend_->init(self->window_, self->game_canvas_, "", ""); - SDL_Log("Screen::initShaders: SDL3GPUShader::init() = %s", ok ? "OK" : "FAILED"); + SDL_Log("Screen::initPostFX: SDL3GPUShader::init() = %s", ok ? "OK" : "FAILED"); } - SDL_Log("Screen::initShaders: presets=%d current=%d postfx=%s", + SDL_Log("Screen::initPostFX: presets=%d current=%d postfx=%s", static_cast(Options::postfx_presets.size()), Options::current_postfx_preset, Options::video.postfx ? "ON" : "OFF"); @@ -279,11 +279,6 @@ void Screen::initShaders() { #endif } -// Inicializa PostFX (alias de initShaders) -void Screen::initPostFX() { - initShaders(); -} - // Calcula el tamaño de la ventana void Screen::adjustWindowSize() { if (!Options::video.fullscreen) { @@ -443,11 +438,6 @@ void Screen::getDisplayInfo() { } } -// Alterna entre activar y desactivar los shaders (backward compat) -void Screen::toggleShaders() { - Screen::togglePostFX(); -} - // Alterna entre activar y desactivar los efectos PostFX void Screen::togglePostFX() { Options::video.postfx = !Options::video.postfx; @@ -469,16 +459,19 @@ void Screen::nextPostFXPreset() { // Alterna entre activar y desactivar el supersampling 3x void Screen::toggleSupersampling() { - Options::video.supersampling = !Options::video.supersampling; + Options::video.supersampling = (Options::video.supersampling % 3) + 1; auto* self = Screen::get(); - if (self != nullptr && self->shader_backend_) { - self->shader_backend_->setOversample(Options::video.supersampling ? 3 : 1); + if (self != nullptr && self->shader_backend_ && self->shader_backend_->isHardwareAccelerated()) { + self->applyCurrentPostFXPreset(); } } // Aplica el preset PostFX activo al backend void Screen::applyCurrentPostFXPreset() { if (!shader_backend_) { return; } + // setOversample PRIMERO: puede recrear texturas antes de que setPostFXParams + // decida si hornear scanlines en CPU o aplicarlas en GPU. + shader_backend_->setOversample(Options::video.supersampling); Rendering::PostFXParams p{}; if (Options::video.postfx && !Options::postfx_presets.empty()) { const auto& preset = Options::postfx_presets.at(static_cast(Options::current_postfx_preset)); @@ -490,8 +483,8 @@ void Screen::applyCurrentPostFXPreset() { p.curvature = preset.curvature; p.bleeding = preset.bleeding; p.flicker = preset.flicker; - SDL_Log("Screen::applyCurrentPostFXPreset: preset='%s' scan=%.2f vign=%.2f chroma=%.2f", - preset.name.c_str(), p.scanlines, p.vignette, p.chroma); + SDL_Log("Screen::applyCurrentPostFXPreset: preset='%s' scan=%.2f vign=%.2f chroma=%.2f ss=%d×", + preset.name.c_str(), p.scanlines, p.vignette, p.chroma, Options::video.supersampling); } else { SDL_Log("Screen::applyCurrentPostFXPreset: PostFX=%s presets=%d → passthrough", Options::video.postfx ? "ON" : "OFF", diff --git a/source/screen.hpp b/source/screen.hpp index bfe5e46..eb333c9 100644 --- a/source/screen.hpp +++ b/source/screen.hpp @@ -41,13 +41,11 @@ class Screen { auto decWindowSize() -> bool; // Reduce el tamaño de la ventana auto incWindowSize() -> bool; // Aumenta el tamaño de la ventana void applySettings(); // Aplica los valores de las opciones - static void initShaders(); // Inicializa los shaders (SDL3GPU) - static void initPostFX(); // Inicializa PostFX (alias de initShaders) + static void initPostFX(); // Inicializa PostFX (SDL3GPU) // --- Efectos visuales --- void shake(int desp = 2, float delay_s = 0.05F, float duration_s = 0.133F) { shake_effect_.enable(src_rect_, dst_rect_, desp, delay_s, duration_s); } // Agita la pantalla (tiempo en segundos) void flash(Color color, float duration_s = 0.167F, float delay_s = 0.0F) { flash_effect_ = FlashEffect(true, duration_s, delay_s, color); } // Pone la pantalla de color (tiempo en segundos) - static void toggleShaders(); // Alterna entre activar y desactivar los shaders (backward compat) static void togglePostFX(); // Alterna entre activar y desactivar los efectos PostFX static void nextPostFXPreset(); // Avanza al siguiente preset PostFX static void toggleSupersampling(); // Alterna entre activar y desactivar el supersampling 3x diff --git a/source/ui/service_menu.cpp b/source/ui/service_menu.cpp index d57da73..ee51c08 100644 --- a/source/ui/service_menu.cpp +++ b/source/ui/service_menu.cpp @@ -364,9 +364,21 @@ void ServiceMenu::initializeOptions() { 1)); options_.push_back(std::make_unique( - Lang::getText("[SERVICE_MENU] SHADERS"), + Lang::getText("[SERVICE_MENU] POSTFX"), SettingsGroup::VIDEO, - &Options::video.shaders)); + &Options::video.postfx)); + + options_.push_back(std::make_unique( + Lang::getText("[SERVICE_MENU] POSTFX_PRESET"), + SettingsGroup::VIDEO, + &Options::current_postfx_preset, + 0, static_cast(Options::postfx_presets.size()) - 1, 1)); + + options_.push_back(std::make_unique( + Lang::getText("[SERVICE_MENU] SUPERSAMPLING"), + SettingsGroup::VIDEO, + &Options::video.supersampling, + 1, 3, 1)); options_.push_back(std::make_unique( Lang::getText("[SERVICE_MENU] VSYNC"),