diff --git a/source/core/rendering/screen.cpp b/source/core/rendering/screen.cpp index 574d0ae..1f90e83 100644 --- a/source/core/rendering/screen.cpp +++ b/source/core/rendering/screen.cpp @@ -172,24 +172,27 @@ void Screen::present(Uint32* pixel_data) { shader_backend_->setActiveShader(prev_shader); } } else { - // Fallback SDL_Renderer + // Fallback SDL_Renderer. A mult=1, flux directe original: logical + // presentation (setada per applyFallbackPresentation) + scale mode de + // texture_ segons l'opció. A mult>1, la còpia intermèdia crea la + // font ampliada (NN via GPU), i es presenta via logical presentation + // a la mida de la font intermèdia. SDL_UpdateTexture(texture_, nullptr, pixel_data, GAME_WIDTH * sizeof(Uint32)); const int mult = Options::video.internal_resolution; if (mult > 1) { - // Resolució interna: còpia NN de texture_ → internal_texture_sdl_ - // (la fa SDL/GPU, no CPU). Tota la presentació downstream llegirà - // d'aquesta textura més gran — el filtre LINEAR final parteix d'una - // font més fina i l'estirament a finestra queda menys difús. ensureFallbackInternalTexture(); if (internal_texture_sdl_ != nullptr) { + // Còpia NN a la textura intermèdia (mult·game). Sampler NN + // per construcció: volem píxels grans i nets. SDL_SetTextureScaleMode(texture_, SDL_SCALEMODE_NEAREST); SDL_SetRenderTarget(renderer_, internal_texture_sdl_); SDL_RenderClear(renderer_); SDL_RenderTexture(renderer_, texture_, nullptr, nullptr); SDL_SetRenderTarget(renderer_, nullptr); - // El filtre global (LINEAR/NEAREST) s'aplica a l'estirament final - // cap a la finestra; per això l'aplicam a la textura intermèdia. + + // Filtre global al pas final → finestra (via logical presentation + // que applyFallbackPresentation ja configura amb mida game·mult). SDL_ScaleMode final_scale = (Options::video.texture_filter == Options::TextureFilter::LINEAR) ? SDL_SCALEMODE_LINEAR : SDL_SCALEMODE_NEAREST; @@ -199,8 +202,15 @@ void Screen::present(Uint32* pixel_data) { SDL_RenderPresent(renderer_); return; } - // Si la creació de la textura ha fallat, caiem al path normal. + // Si la creació de la textura intermèdia ha fallat, caiem al path normal. } + // mult=1 (o fallback-del-fallback): texture_ directament. El scale mode + // el manté applyFallbackPresentation — però el re-apliquem per si la + // ruta mult>1 el va sobreescriure anteriorment. + SDL_ScaleMode direct_scale = (Options::video.texture_filter == Options::TextureFilter::LINEAR) + ? SDL_SCALEMODE_LINEAR + : SDL_SCALEMODE_NEAREST; + SDL_SetTextureScaleMode(texture_, direct_scale); SDL_RenderClear(renderer_); SDL_RenderTexture(renderer_, texture_, nullptr, nullptr); SDL_RenderPresent(renderer_); @@ -502,9 +512,10 @@ void Screen::applyFallbackPresentation() { } void Screen::ensureFallbackInternalTexture() { + if (renderer_ == nullptr) return; const int mult = Options::video.internal_resolution; - if (mult <= 1 || renderer_ == nullptr) { - // No cal textura intermèdia. Si la teníem, la reciclem. + if (mult <= 1) { + // No cal textura intermèdia — recicla si la teníem. if (internal_texture_sdl_ != nullptr) { SDL_DestroyTexture(internal_texture_sdl_); internal_texture_sdl_ = nullptr; diff --git a/source/core/rendering/sdl3gpu/sdl3gpu_shader.cpp b/source/core/rendering/sdl3gpu/sdl3gpu_shader.cpp index 8482220..c1b1cae 100644 --- a/source/core/rendering/sdl3gpu/sdl3gpu_shader.cpp +++ b/source/core/rendering/sdl3gpu/sdl3gpu_shader.cpp @@ -977,9 +977,14 @@ namespace Rendering { SDL_GPUViewport vp = {.x = vx, .y = vy, .w = vw, .h = vh, .min_depth = 0.0F, .max_depth = 1.0F}; SDL_SetGPUViewport(pass, &vp); + // El shader CrtPi tradicionalment usa NEAREST per a fer el seu + // propi filtrat analític. Si l'usuari tria LINEAR explícitament, + // respectem la preferència (la mostra arribarà pre-suavitzada). SDL_GPUTextureSamplerBinding binding = {}; binding.texture = effective_scene; - binding.sampler = sampler_; // NEAREST: el shader CrtPi fa el seu propi filtrat analític + binding.sampler = (texture_filter_linear_ && linear_sampler_ != nullptr) + ? linear_sampler_ + : sampler_; SDL_BindGPUFragmentSamplers(pass, 0, &binding, 1); // Injectar texture_width/height abans del push @@ -1054,11 +1059,15 @@ namespace Rendering { SDL_GPUViewport vp = {.x = vx, .y = vy, .w = vw, .h = vh, .min_depth = 0.0F, .max_depth = 1.0F}; SDL_SetGPUViewport(pass, &vp); - // Amb SS: llegir de scaled_texture_ amb LINEAR; sense SS: effective_scene amb NEAREST. + // Font: amb SS scaled_texture_; sense SS, effective_scene (que ja + // és internal_texture_ si internal_res_>1, o scene_texture_ si no). + // Sampler: honora el filtre global que l'usuari tria al menú + // (texture_filter_linear_). Abans estava hardcoded a NEAREST + // quan SS era off — el menú no tenia efecte visible en aquest path. SDL_GPUTexture* input_texture = (oversample_ > 1 && scaled_texture_ != nullptr) ? scaled_texture_ : effective_scene; - SDL_GPUSampler* active_sampler = (oversample_ > 1 && linear_sampler_ != nullptr) + SDL_GPUSampler* active_sampler = (texture_filter_linear_ && linear_sampler_ != nullptr) ? linear_sampler_ : sampler_;