ref: 7bc028f5d8949cb206eb8fa1f5e7b27ef47e764b
parent: aa3cd55b432649bb2e61a5176c3ee53ae345c2f1
author: Clownacy <Clownacy@users.noreply.github.com>
date: Sun Sep 13 13:56:28 EDT 2020
Enable window-resizing in the SDLTexture renderer Previously, the window was a fixed size just like the original. This change highlights a weird issue in CSE2: this doesn't exactly match the behaviour of the original game, so why did I change it? Simple: monitors had much lower pixel-densities back in the early 2000s, meaning that 320x240 and 640x480 weren't as laughably small as they are today. I like to think of CSE2's portable branch as Cave Story's equivalent to Chocolate Doom: the point isn't to replicate the game's behaviour 100% - that's the accurate branch's job - no, the point of the portable branch is to replicate the *experience* of the game, as it was back in 2004. This means no commically-small windows. This is the same reason font anti-aliasing is disabled, even in versions of Windows later than XP. Sidenote: the OpenGL3/OpenGLES2 renderers already had this feature, but they used linear-filtering, causing the screen to be extremely blurry in 320x240 mode. This renderer uses a better method, which does apply slight blurring at the edges of pixels at resolutions that aren't an exact multiple of 320x240/640x480, but otherwise it resembles nearest-neighbour. This is way nicer to look at, and fits the game's aesthetic. This feature will be ported to the other renderers soon.
--- a/src/Backends/Rendering/SDLTexture.cpp
+++ b/src/Backends/Rendering/SDLTexture.cpp
@@ -12,6 +12,9 @@
#include "../Misc.h"
#include "../Shared/SDL2.h"
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+
typedef struct RenderBackend_Surface
{
SDL_Texture *texture;
@@ -34,7 +37,10 @@
static SDL_Renderer *renderer;
static RenderBackend_Surface framebuffer;
+static RenderBackend_Surface upscaled_framebuffer;
+static SDL_Rect upscaled_framebuffer_rect;
+
static RenderBackend_Surface *surface_list_head;
static void RectToSDLRect(const RenderBackend_Rect *rect, SDL_Rect *sdl_rect)
@@ -64,7 +70,7 @@
Backend_PrintInfo("%s", info.name);
}
- window = SDL_CreateWindow(window_title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, screen_width, screen_height, 0);
+ window = SDL_CreateWindow(window_title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, screen_width, screen_height, SDL_WINDOW_RESIZABLE);
if (window != NULL)
{
@@ -93,6 +99,8 @@
framebuffer.width = screen_width;
framebuffer.height = screen_height;
+ RenderBackend_HandleWindowResize(screen_width, screen_height);
+
Backend_PostWindowCreation();
return &framebuffer;
@@ -132,12 +140,23 @@
void RenderBackend_DrawScreen(void)
{
+ if (SDL_SetRenderTarget(renderer, upscaled_framebuffer.texture) < 0)
+ Backend_PrintError("Couldn't set upscaled framebuffer as the current rendering target: %s", SDL_GetError());
+
+ if (SDL_RenderCopy(renderer, framebuffer.texture, NULL, NULL) < 0)
+ Backend_PrintError("Failed to copy framebuffer texture to upscaled framebuffer: %s", SDL_GetError());
+
if (SDL_SetRenderTarget(renderer, NULL) < 0)
Backend_PrintError("Couldn't set default render target as the current rendering target: %s", SDL_GetError());
- if (SDL_RenderCopy(renderer, framebuffer.texture, NULL, NULL) < 0)
- Backend_PrintError("Failed to copy framebuffer texture to default render target: %s", SDL_GetError());
+ if (SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0xFF) < 0)
+ Backend_PrintError("Couldn't set color for drawing operations: %s", SDL_GetError());
+ SDL_RenderClear(renderer);
+
+ if (SDL_RenderCopy(renderer, upscaled_framebuffer.texture, NULL, &upscaled_framebuffer_rect) < 0)
+ Backend_PrintError("Failed to copy upscaled framebuffer texture to default render target: %s", SDL_GetError());
+
SDL_RenderPresent(renderer);
}
@@ -418,8 +437,36 @@
void RenderBackend_HandleWindowResize(size_t width, size_t height)
{
- (void)width;
- (void)height;
+ size_t upscale_factor = MAX(1, MIN((width + framebuffer.width / 2) / framebuffer.width, (height + framebuffer.height / 2) / framebuffer.height));
- // No problem for us
+ upscaled_framebuffer.width = framebuffer.width * upscale_factor;
+ upscaled_framebuffer.height = framebuffer.height * upscale_factor;
+
+ if (upscaled_framebuffer.texture != NULL)
+ SDL_DestroyTexture(upscaled_framebuffer.texture);
+
+ SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
+ upscaled_framebuffer.texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_TARGET, upscaled_framebuffer.width, upscaled_framebuffer.height * upscale_factor);
+ SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest");
+
+ if (upscaled_framebuffer.texture == NULL)
+ Backend_PrintError("Couldn't regenerate upscaled framebuffer");
+
+ // Create rect that forces 4:3 no matter what size the window is
+ float window_ratio = (float)width / height;
+ float framebuffer_ratio = (float)upscaled_framebuffer.width / upscaled_framebuffer.height;
+
+ if (window_ratio >= framebuffer_ratio)
+ {
+ upscaled_framebuffer_rect.w = height * framebuffer_ratio;
+ upscaled_framebuffer_rect.h = height;
+ }
+ else
+ {
+ upscaled_framebuffer_rect.w = width;
+ upscaled_framebuffer_rect.h = width / framebuffer_ratio;
+ }
+
+ upscaled_framebuffer_rect.x = (width - upscaled_framebuffer_rect.w) / 2;
+ upscaled_framebuffer_rect.y = (height - upscaled_framebuffer_rect.h) / 2;
}