From 8d213e7b3e371f99e5c9597eb86efce881724efe Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Thu, 26 Mar 2026 07:46:11 +0100 Subject: [PATCH] afinant els shaders --- .../core/rendering/sdl3gpu/sdl3gpu_shader.cpp | 74 +++++++++++-------- .../core/rendering/sdl3gpu/sdl3gpu_shader.hpp | 12 +-- 2 files changed, 49 insertions(+), 37 deletions(-) diff --git a/source/core/rendering/sdl3gpu/sdl3gpu_shader.cpp b/source/core/rendering/sdl3gpu/sdl3gpu_shader.cpp index c102f66..2e7f02c 100644 --- a/source/core/rendering/sdl3gpu/sdl3gpu_shader.cpp +++ b/source/core/rendering/sdl3gpu/sdl3gpu_shader.cpp @@ -272,9 +272,8 @@ namespace Rendering { return false; } - // scaled_texture_ se creará en el primer render() una vez conocido el tamaño de ventana - scaled_w_ = 0; - scaled_h_ = 0; + // scaled_texture_ se creará en el primer render() una vez conocido el zoom de ventana + ss_factor_ = 0; // ---------------------------------------------------------------- // 4. Create upload transfer buffer (CPU → GPU, always game resolution) @@ -450,16 +449,17 @@ namespace Rendering { void SDL3GPUShader::render() { if (!is_initialized_) { return; } - // Paso 0: si SS activo, verificar si el tamaño de ventana cambió y recrear scaled_texture_ - if (oversample_ > 1) { + // Paso 0: si SS activo, calcular el factor necesario según el zoom actual y recrear si cambió. + // Factor = primer múltiplo de 3 >= zoom (mín 3). Se recrea solo en saltos de factor. + if (oversample_ > 1 && game_height_ > 0) { int win_w = 0; int win_h = 0; SDL_GetWindowSizeInPixels(window_, &win_w, &win_h); - const int NEED_W = win_w * oversample_; - const int NEED_H = win_h * oversample_; - if (NEED_W != scaled_w_ || NEED_H != scaled_h_) { + const float ZOOM = static_cast(win_h) / static_cast(game_height_); + const int NEED_FACTOR = calcSsFactor(ZOOM); + if (NEED_FACTOR != ss_factor_) { SDL_WaitForGPUIdle(device_); - recreateScaledTexture(NEED_W, NEED_H); + recreateScaledTexture(NEED_FACTOR); } } @@ -558,13 +558,15 @@ namespace Rendering { // pixel_scale: subpíxeles de textura por pixel lógico de juego. // Sin SS: vh/game_height (zoom de ventana). - // Con SS: scaled_h_/game_height (= win_h*oversample_/game_height), que indica - // cuántas subfilas de la textura intermedia corresponden a cada fila lógica. - uniforms_.pixel_scale = (oversample_ > 1 && game_height_ > 0) - ? (static_cast(scaled_h_) / static_cast(game_height_)) + // Con SS: ss_factor_ exacto (3, 6, 9...) — la textura scaled tiene exactamente + // ss_factor_ subfilas por fila lógica, múltiplo de 3 garantizado. + uniforms_.pixel_scale = (oversample_ > 1 && ss_factor_ > 0) + ? static_cast(ss_factor_) : ((game_height_ > 0) ? (vh / static_cast(game_height_)) : 1.0F); uniforms_.time = static_cast(SDL_GetTicks()) / 1000.0F; - uniforms_.oversample = static_cast(oversample_); + uniforms_.oversample = (oversample_ > 1 && ss_factor_ > 0) + ? static_cast(ss_factor_) + : 1.0F; // Con SS: leer de scaled_texture_ (ya ampliada); con LINEAR para suavizar // el escalado final a zooms no-múltiplo-de-OS. @@ -615,8 +617,7 @@ namespace Rendering { SDL_ReleaseGPUTexture(device_, scaled_texture_); scaled_texture_ = nullptr; } - scaled_w_ = 0; - scaled_h_ = 0; + ss_factor_ = 0; if (upload_buffer_ != nullptr) { SDL_ReleaseGPUTransferBuffer(device_, upload_buffer_); upload_buffer_ = nullptr; @@ -744,13 +745,12 @@ namespace Rendering { SDL_ReleaseGPUTexture(device_, scene_texture_); scene_texture_ = nullptr; } - // scaled_texture_ se libera aquí; se recreará en el primer render() con las dims de ventana + // scaled_texture_ se libera aquí; se recreará en el primer render() con el factor correcto if (scaled_texture_ != nullptr) { SDL_ReleaseGPUTexture(device_, scaled_texture_); scaled_texture_ = nullptr; } - scaled_w_ = 0; - scaled_h_ = 0; + ss_factor_ = 0; if (upload_buffer_ != nullptr) { SDL_ReleaseGPUTransferBuffer(device_, upload_buffer_); @@ -787,39 +787,51 @@ namespace Rendering { return false; } - SDL_Log("SDL3GPUShader: reinit — scene %dx%d, oversample %d (scaled se creará en render)", - game_width_, game_height_, oversample_); + SDL_Log("SDL3GPUShader: reinit — scene %dx%d, SS %s (scaled se creará en render)", + game_width_, game_height_, oversample_ > 1 ? "on" : "off"); return true; } // --------------------------------------------------------------------------- - // recreateScaledTexture — libera y recrea scaled_texture_ con nuevas dimensiones. + // calcSsFactor — primer múltiplo de 3 >= zoom, mínimo 3. + // Ejemplos: zoom 1,2,3 → 3; zoom 4,5,6 → 6; zoom 4.4 → 6; zoom 7,8,9 → 9. + // --------------------------------------------------------------------------- + auto SDL3GPUShader::calcSsFactor(float zoom) -> int { + const int MULTIPLE = 3; + const int n = static_cast(std::ceil(zoom / static_cast(MULTIPLE))); + return std::max(1, n) * MULTIPLE; + } + + // --------------------------------------------------------------------------- + // recreateScaledTexture — libera y recrea scaled_texture_ para el factor dado. // Llamar solo cuando device_ no esté ejecutando comandos (SDL_WaitForGPUIdle previo). // --------------------------------------------------------------------------- - auto SDL3GPUShader::recreateScaledTexture(int w, int h) -> bool { + auto SDL3GPUShader::recreateScaledTexture(int factor) -> bool { if (scaled_texture_ != nullptr) { SDL_ReleaseGPUTexture(device_, scaled_texture_); scaled_texture_ = nullptr; } - scaled_w_ = 0; - scaled_h_ = 0; + ss_factor_ = 0; + + const int W = game_width_ * factor; + const int H = game_height_ * factor; SDL_GPUTextureCreateInfo info = {}; info.type = SDL_GPU_TEXTURETYPE_2D; info.format = SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM; info.usage = SDL_GPU_TEXTUREUSAGE_SAMPLER | SDL_GPU_TEXTUREUSAGE_COLOR_TARGET; - info.width = static_cast(w); - info.height = static_cast(h); + info.width = static_cast(W); + info.height = static_cast(H); info.layer_count_or_depth = 1; info.num_levels = 1; scaled_texture_ = SDL_CreateGPUTexture(device_, &info); if (scaled_texture_ == nullptr) { - SDL_Log("SDL3GPUShader: failed to create scaled texture %dx%d: %s", w, h, SDL_GetError()); + SDL_Log("SDL3GPUShader: failed to create scaled texture %dx%d (factor %d): %s", + W, H, factor, SDL_GetError()); return false; } - scaled_w_ = w; - scaled_h_ = h; - SDL_Log("SDL3GPUShader: scaled texture %dx%d (oversample %d)", w, h, oversample_); + ss_factor_ = factor; + SDL_Log("SDL3GPUShader: scaled texture %dx%d (factor %d×)", W, H, factor); return true; } diff --git a/source/core/rendering/sdl3gpu/sdl3gpu_shader.hpp b/source/core/rendering/sdl3gpu/sdl3gpu_shader.hpp index e7d4302..0f1ea12 100644 --- a/source/core/rendering/sdl3gpu/sdl3gpu_shader.hpp +++ b/source/core/rendering/sdl3gpu/sdl3gpu_shader.hpp @@ -80,8 +80,9 @@ namespace Rendering { Uint32 num_uniform_buffers) -> SDL_GPUShader*; auto createPipeline() -> bool; - auto reinitTexturesAndBuffer() -> bool; // Recrea scene_texture_ y upload_buffer_ - auto recreateScaledTexture(int w, int h) -> bool; // Recrea scaled_texture_ con nuevas dims + auto reinitTexturesAndBuffer() -> bool; // Recrea scene_texture_ y upload_buffer_ + auto recreateScaledTexture(int factor) -> bool; // Recrea scaled_texture_ para factor dado + static auto calcSsFactor(float zoom) -> int; // Primer múltiplo de 3 >= zoom (mín 3) SDL_Window* window_ = nullptr; SDL_GPUDevice* device_ = nullptr; @@ -95,11 +96,10 @@ namespace Rendering { PostFXUniforms uniforms_{.vignette_strength = 0.6F, .chroma_strength = 0.15F, .scanline_strength = 0.7F, .screen_height = 192.0F, .pixel_scale = 1.0F, .oversample = 1.0F}; - int game_width_ = 0; // Dimensiones originales del canvas + int game_width_ = 0; // Dimensiones originales del canvas int game_height_ = 0; - int scaled_w_ = 0; // Dimensiones actuales de scaled_texture_ (win*SS) - int scaled_h_ = 0; - int oversample_ = 1; // Factor SS actual (1 o 3) + int ss_factor_ = 0; // Factor SS activo (3, 6, 9...) o 0 si SS desactivado + int oversample_ = 1; // SS on/off (1 = off, >1 = on) bool is_initialized_ = false; bool vsync_ = true; bool integer_scale_ = false;