afinant els shaders

This commit is contained in:
2026-03-26 07:46:11 +01:00
parent c6d409c303
commit 8d213e7b3e
2 changed files with 49 additions and 37 deletions

View File

@@ -272,9 +272,8 @@ namespace Rendering {
return false; return false;
} }
// scaled_texture_ se creará en el primer render() una vez conocido el tamaño de ventana // scaled_texture_ se creará en el primer render() una vez conocido el zoom de ventana
scaled_w_ = 0; ss_factor_ = 0;
scaled_h_ = 0;
// ---------------------------------------------------------------- // ----------------------------------------------------------------
// 4. Create upload transfer buffer (CPU → GPU, always game resolution) // 4. Create upload transfer buffer (CPU → GPU, always game resolution)
@@ -450,16 +449,17 @@ namespace Rendering {
void SDL3GPUShader::render() { void SDL3GPUShader::render() {
if (!is_initialized_) { return; } if (!is_initialized_) { return; }
// Paso 0: si SS activo, verificar si el tamaño de ventana cambió y recrear scaled_texture_ // Paso 0: si SS activo, calcular el factor necesario según el zoom actual y recrear si cambió.
if (oversample_ > 1) { // 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_w = 0;
int win_h = 0; int win_h = 0;
SDL_GetWindowSizeInPixels(window_, &win_w, &win_h); SDL_GetWindowSizeInPixels(window_, &win_w, &win_h);
const int NEED_W = win_w * oversample_; const float ZOOM = static_cast<float>(win_h) / static_cast<float>(game_height_);
const int NEED_H = win_h * oversample_; const int NEED_FACTOR = calcSsFactor(ZOOM);
if (NEED_W != scaled_w_ || NEED_H != scaled_h_) { if (NEED_FACTOR != ss_factor_) {
SDL_WaitForGPUIdle(device_); 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. // pixel_scale: subpíxeles de textura por pixel lógico de juego.
// Sin SS: vh/game_height (zoom de ventana). // Sin SS: vh/game_height (zoom de ventana).
// Con SS: scaled_h_/game_height (= win_h*oversample_/game_height), que indica // Con SS: ss_factor_ exacto (3, 6, 9...) — la textura scaled tiene exactamente
// cuántas subfilas de la textura intermedia corresponden a cada fila lógica. // ss_factor_ subfilas por fila lógica, múltiplo de 3 garantizado.
uniforms_.pixel_scale = (oversample_ > 1 && game_height_ > 0) uniforms_.pixel_scale = (oversample_ > 1 && ss_factor_ > 0)
? (static_cast<float>(scaled_h_) / static_cast<float>(game_height_)) ? static_cast<float>(ss_factor_)
: ((game_height_ > 0) ? (vh / static_cast<float>(game_height_)) : 1.0F); : ((game_height_ > 0) ? (vh / static_cast<float>(game_height_)) : 1.0F);
uniforms_.time = static_cast<float>(SDL_GetTicks()) / 1000.0F; uniforms_.time = static_cast<float>(SDL_GetTicks()) / 1000.0F;
uniforms_.oversample = static_cast<float>(oversample_); uniforms_.oversample = (oversample_ > 1 && ss_factor_ > 0)
? static_cast<float>(ss_factor_)
: 1.0F;
// Con SS: leer de scaled_texture_ (ya ampliada); con LINEAR para suavizar // Con SS: leer de scaled_texture_ (ya ampliada); con LINEAR para suavizar
// el escalado final a zooms no-múltiplo-de-OS. // el escalado final a zooms no-múltiplo-de-OS.
@@ -615,8 +617,7 @@ namespace Rendering {
SDL_ReleaseGPUTexture(device_, scaled_texture_); SDL_ReleaseGPUTexture(device_, scaled_texture_);
scaled_texture_ = nullptr; scaled_texture_ = nullptr;
} }
scaled_w_ = 0; ss_factor_ = 0;
scaled_h_ = 0;
if (upload_buffer_ != nullptr) { if (upload_buffer_ != nullptr) {
SDL_ReleaseGPUTransferBuffer(device_, upload_buffer_); SDL_ReleaseGPUTransferBuffer(device_, upload_buffer_);
upload_buffer_ = nullptr; upload_buffer_ = nullptr;
@@ -744,13 +745,12 @@ namespace Rendering {
SDL_ReleaseGPUTexture(device_, scene_texture_); SDL_ReleaseGPUTexture(device_, scene_texture_);
scene_texture_ = nullptr; 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) { if (scaled_texture_ != nullptr) {
SDL_ReleaseGPUTexture(device_, scaled_texture_); SDL_ReleaseGPUTexture(device_, scaled_texture_);
scaled_texture_ = nullptr; scaled_texture_ = nullptr;
} }
scaled_w_ = 0; ss_factor_ = 0;
scaled_h_ = 0;
if (upload_buffer_ != nullptr) { if (upload_buffer_ != nullptr) {
SDL_ReleaseGPUTransferBuffer(device_, upload_buffer_); SDL_ReleaseGPUTransferBuffer(device_, upload_buffer_);
@@ -787,39 +787,51 @@ namespace Rendering {
return false; return false;
} }
SDL_Log("SDL3GPUShader: reinit — scene %dx%d, oversample %d (scaled se creará en render)", SDL_Log("SDL3GPUShader: reinit — scene %dx%d, SS %s (scaled se creará en render)",
game_width_, game_height_, oversample_); game_width_, game_height_, oversample_ > 1 ? "on" : "off");
return true; 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<int>(std::ceil(zoom / static_cast<float>(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). // 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) { if (scaled_texture_ != nullptr) {
SDL_ReleaseGPUTexture(device_, scaled_texture_); SDL_ReleaseGPUTexture(device_, scaled_texture_);
scaled_texture_ = nullptr; scaled_texture_ = nullptr;
} }
scaled_w_ = 0; ss_factor_ = 0;
scaled_h_ = 0;
const int W = game_width_ * factor;
const int H = game_height_ * factor;
SDL_GPUTextureCreateInfo info = {}; SDL_GPUTextureCreateInfo info = {};
info.type = SDL_GPU_TEXTURETYPE_2D; info.type = SDL_GPU_TEXTURETYPE_2D;
info.format = SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM; info.format = SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM;
info.usage = SDL_GPU_TEXTUREUSAGE_SAMPLER | SDL_GPU_TEXTUREUSAGE_COLOR_TARGET; info.usage = SDL_GPU_TEXTUREUSAGE_SAMPLER | SDL_GPU_TEXTUREUSAGE_COLOR_TARGET;
info.width = static_cast<Uint32>(w); info.width = static_cast<Uint32>(W);
info.height = static_cast<Uint32>(h); info.height = static_cast<Uint32>(H);
info.layer_count_or_depth = 1; info.layer_count_or_depth = 1;
info.num_levels = 1; info.num_levels = 1;
scaled_texture_ = SDL_CreateGPUTexture(device_, &info); scaled_texture_ = SDL_CreateGPUTexture(device_, &info);
if (scaled_texture_ == nullptr) { 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; return false;
} }
scaled_w_ = w; ss_factor_ = factor;
scaled_h_ = h; SDL_Log("SDL3GPUShader: scaled texture %dx%d (factor %d×)", W, H, factor);
SDL_Log("SDL3GPUShader: scaled texture %dx%d (oversample %d)", w, h, oversample_);
return true; return true;
} }

View File

@@ -80,8 +80,9 @@ namespace Rendering {
Uint32 num_uniform_buffers) -> SDL_GPUShader*; Uint32 num_uniform_buffers) -> SDL_GPUShader*;
auto createPipeline() -> bool; auto createPipeline() -> bool;
auto reinitTexturesAndBuffer() -> bool; // Recrea scene_texture_ y upload_buffer_ auto reinitTexturesAndBuffer() -> bool; // Recrea scene_texture_ y upload_buffer_
auto recreateScaledTexture(int w, int h) -> bool; // Recrea scaled_texture_ con nuevas dims 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_Window* window_ = nullptr;
SDL_GPUDevice* device_ = 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}; 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 game_height_ = 0;
int scaled_w_ = 0; // Dimensiones actuales de scaled_texture_ (win*SS) int ss_factor_ = 0; // Factor SS activo (3, 6, 9...) o 0 si SS desactivado
int scaled_h_ = 0; int oversample_ = 1; // SS on/off (1 = off, >1 = on)
int oversample_ = 1; // Factor SS actual (1 o 3)
bool is_initialized_ = false; bool is_initialized_ = false;
bool vsync_ = true; bool vsync_ = true;
bool integer_scale_ = false; bool integer_scale_ = false;