diff --git a/data/language/en-GB.txt b/data/language/en-GB.txt index 356c75827e..cbac924418 100644 --- a/data/language/en-GB.txt +++ b/data/language/en-GB.txt @@ -4467,6 +4467,7 @@ STR_6155 :Neither KDialog nor Zenity are installed. Please install one, or co STR_6156 :Name is reserved STR_6157 :Console STR_6158 :Failed to load this file...{NEWLINE}Incompatible RCTC version: {COMMA16} +STR_6159 :Smooth Nearest Neighbor ############# # Scenarios # diff --git a/distribution/changelog.txt b/distribution/changelog.txt index d06c495afd..d1f2a3bdd7 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -18,6 +18,7 @@ - Feature: [#6414] Raise maximum launch speed of the Corkscrew RC back to 96 km/h (for RCT1 parity). - Feature: [#6433] Turn 'unlock all prices' into a regular (non-cheat, persistent) option. - Feature: [#6530] Land rights tool no longer blocks when a tile is not for purchase. +- Feature: [#6568] Add smooth nearest neighbor scaling. - Feature: Allow using object files from RCT Classic. - Feature: Title sequences now testable in-game. - Fix: [#816] In the map window, there are more peeps flickering than there are selected (original bug). diff --git a/src/openrct2-ui/UiContext.cpp b/src/openrct2-ui/UiContext.cpp index 595045870b..720ea5412e 100644 --- a/src/openrct2-ui/UiContext.cpp +++ b/src/openrct2-ui/UiContext.cpp @@ -497,6 +497,10 @@ public: { _scaleQuality = 0; } + if (_scaleQuality == 3) + { + _scaleQuality = 1; + } snprintf(scaleQualityBuffer, sizeof(scaleQualityBuffer), "%u", _scaleQuality); SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, scaleQualityBuffer); diff --git a/src/openrct2-ui/drawing/engines/HardwareDisplayDrawingEngine.cpp b/src/openrct2-ui/drawing/engines/HardwareDisplayDrawingEngine.cpp index 95749eb6fc..8c5441663a 100644 --- a/src/openrct2-ui/drawing/engines/HardwareDisplayDrawingEngine.cpp +++ b/src/openrct2-ui/drawing/engines/HardwareDisplayDrawingEngine.cpp @@ -40,6 +40,7 @@ private: SDL_Window * _window = nullptr; SDL_Renderer * _sdlRenderer = nullptr; SDL_Texture * _screenTexture = nullptr; + SDL_Texture * _scaledScreenTexture = nullptr; SDL_PixelFormat * _screenTextureFormat = nullptr; uint32 _paletteHWMapped[256] = { 0 }; #ifdef __ENABLE_LIGHTFX__ @@ -53,6 +54,8 @@ private: bool _pausedBeforeOverlay = false; std::vector _dirtyVisualsTime; + + bool smoothNN = false; public: explicit HardwareDisplayDrawingEngine(IUiContext * uiContext) @@ -98,7 +101,40 @@ public: } } - _screenTexture = SDL_CreateTexture(_sdlRenderer, pixelFormat, SDL_TEXTUREACCESS_STREAMING, width, height); + sint32 scaleQuality = gConfigGeneral.scale_quality; + if (gConfigGeneral.use_nn_at_integer_scales && + gConfigGeneral.window_scale == std::floor(gConfigGeneral.window_scale)) + { + scaleQuality = 0; + } + if (scaleQuality == 3) + { + scaleQuality = 1; + smoothNN = true; + } + else + { + smoothNN = false; + } + + if (smoothNN) + { + SDL_DestroyTexture(_scaledScreenTexture); + + char scaleQualityBuffer[4]; + snprintf(scaleQualityBuffer, sizeof(scaleQualityBuffer), "%u", scaleQuality); + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0"); + _screenTexture = SDL_CreateTexture(_sdlRenderer, pixelFormat, SDL_TEXTUREACCESS_STREAMING, width, height); + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, scaleQualityBuffer); + + uint32 scale = std::ceil(gConfigGeneral.window_scale); + _scaledScreenTexture = SDL_CreateTexture(_sdlRenderer, pixelFormat, SDL_TEXTUREACCESS_TARGET, + width * scale, height * scale); + } + else + { + _screenTexture = SDL_CreateTexture(_sdlRenderer, pixelFormat, SDL_TEXTUREACCESS_STREAMING,width, height); + } uint32 format; SDL_QueryTexture(_screenTexture, &format, 0, 0, 0); @@ -175,7 +211,18 @@ private: { CopyBitsToTexture(_screenTexture, _bits, (sint32)_width, (sint32)_height, _paletteHWMapped); } - SDL_RenderCopy(_sdlRenderer, _screenTexture, nullptr, nullptr); + if (smoothNN) + { + SDL_SetRenderTarget(_sdlRenderer, _scaledScreenTexture); + SDL_RenderCopy(_sdlRenderer, _screenTexture, nullptr, nullptr); + + SDL_SetRenderTarget(_sdlRenderer, nullptr); + SDL_RenderCopy(_sdlRenderer, _scaledScreenTexture, nullptr, nullptr); + } + else + { + SDL_RenderCopy(_sdlRenderer, _screenTexture, nullptr, nullptr); + } if (gShowDirtyVisuals) { diff --git a/src/openrct2-ui/windows/Options.cpp b/src/openrct2-ui/windows/Options.cpp index 96ebae817c..0b500f94bd 100644 --- a/src/openrct2-ui/windows/Options.cpp +++ b/src/openrct2-ui/windows/Options.cpp @@ -385,6 +385,7 @@ static const rct_string_id window_options_scale_quality_names[] = { STR_SCALING_QUALITY_NN, STR_SCALING_QUALITY_LINEAR, STR_SCALING_QUALITY_ANISOTROPIC, + STR_SCALING_QUALITY_SMOOTH_NN }; static const rct_string_id window_options_fullscreen_mode_names[] = { @@ -1022,11 +1023,13 @@ static void window_options_mousedown(rct_window *w, rct_widgetindex widgetIndex, gDropdownItemsFormat[0] = STR_DROPDOWN_MENU_LABEL; gDropdownItemsFormat[1] = STR_DROPDOWN_MENU_LABEL; gDropdownItemsFormat[2] = STR_DROPDOWN_MENU_LABEL; + gDropdownItemsFormat[3] = STR_DROPDOWN_MENU_LABEL; gDropdownItemsArgs[0] = STR_SCALING_QUALITY_NN; gDropdownItemsArgs[1] = STR_SCALING_QUALITY_LINEAR; gDropdownItemsArgs[2] = STR_SCALING_QUALITY_ANISOTROPIC; + gDropdownItemsArgs[3] = STR_SCALING_QUALITY_SMOOTH_NN; - window_options_show_dropdown(w, widget, 3); + window_options_show_dropdown(w, widget, 4); dropdown_set_checked(gConfigGeneral.scale_quality, true); break; diff --git a/src/openrct2/localisation/string_ids.h b/src/openrct2/localisation/string_ids.h index a1d235d7c7..c678ce7447 100644 --- a/src/openrct2/localisation/string_ids.h +++ b/src/openrct2/localisation/string_ids.h @@ -3814,6 +3814,8 @@ enum { STR_CONSOLE = 6157, STR_FAILED_TO_LOAD_IMCOMPATIBLE_RCTC_FLAG = 6158, + + STR_SCALING_QUALITY_SMOOTH_NN = 6159, // Have to include resource strings (from scenarios and objects) for the time being now that language is partially working STR_COUNT = 32768