From 2faee35680a3dd4649cd22ac85cca3b656cc1d4b Mon Sep 17 00:00:00 2001 From: Sven Balzer <4653051+Kyuusokuna@users.noreply.github.com> Date: Sat, 8 Aug 2026 17:18:59 +0200 Subject: [PATCH] add letter-/pillar- boxing for aspect ratios outside fo the defined min/max --- src/main.cpp | 25 ++++++++++++++++++++++--- src/renderer.h | 1 + src/renderer_sdlgpu.c | 4 ++++ src/renderer_wgpu.c | 4 ++++ 4 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index b51c21e..2725b36 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -37,6 +37,9 @@ using namespace glm; #define TILE_ATLAS_SIZE (512) #define PLACEABLE_ATLAS_SIZE (256) +#define ASPECT_RATIO_MIN ( 1.0f / 1.0f) +#define ASPECT_RATIO_MAX (16.0f / 9.0f) + static SDL_Window *window; static R_Texture framebuffer; @@ -59,6 +62,9 @@ static R_Buffer placeable_sizes_and_offsets_buffer; static i32vec2 window_size = { 1280, 720 }; +static vec2 viewport_position; +static vec2 viewport_size; + static MIX_Mixer *mixer; static MIX_Track *music_track; static MIX_Track *sfx_track; @@ -1947,13 +1953,25 @@ static void render_game() { { ZoneScopedN("per_frame"); - float aspect_ratio = ((float)window_size.x / (float)window_size.y); + viewport_position = vec2(0.0f, 0.0f); + viewport_size = vec2(window_size.x, window_size.y); + + float window_aspect_ratio = ((float)window_size.x / (float)window_size.y); + float viewport_aspect_ratio = clamp(window_aspect_ratio, ASPECT_RATIO_MIN, ASPECT_RATIO_MAX); + + if (window_aspect_ratio > viewport_aspect_ratio) { + viewport_size.x = viewport_size.y * viewport_aspect_ratio; + viewport_position.x = (window_size.x - viewport_size.x) * 0.5f; + } else { + viewport_size.y = viewport_size.x / viewport_aspect_ratio; + viewport_position.y = (window_size.y - viewport_size.y) * 0.5f; + } view_matrix = view (vec3(player.visual_position, 0), radians(camera_tilt), camera_distance); inverse_view_matrix = inverse_view(vec3(player.visual_position, 0), radians(camera_tilt), camera_distance); - projection_matrix = projection (radians(camera_fovy_degrees), aspect_ratio, NEAR_PLANE); - inverse_projection_matrix = inverse_projection(radians(camera_fovy_degrees), aspect_ratio, NEAR_PLANE); + projection_matrix = projection (radians(camera_fovy_degrees), viewport_aspect_ratio, NEAR_PLANE); + inverse_projection_matrix = inverse_projection(radians(camera_fovy_degrees), viewport_aspect_ratio, NEAR_PLANE); mat4x4 view_projection_matrix = view_matrix * projection_matrix; renderer_buffer_update(view_projection_matrix_buffer, 0, sizeof(view_projection_matrix), &view_projection_matrix); @@ -1990,6 +2008,7 @@ static void render_game() { } renderer_frame_set_target(framebuffer, R_surface, R_LOAD_OP_CLEAR, R_STORE_OP_STORE, { 0.01f, 0.01f, 0.01f, 0.01f }); + renderer_frame_set_viewport(viewport_position.x, viewport_position.y, viewport_size.x, viewport_size.y, 0.0f, 1.0f); { ZoneScopedN("Draw Map"); diff --git a/src/renderer.h b/src/renderer.h index 9578014..5afcd55 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -114,6 +114,7 @@ void renderer_frame_end(); void renderer_frame_set_target(R_Texture target, R_Texture resolve_target, R_Load_Op load_op, R_Store_Op store_op, R_Color clear_color); void renderer_frame_set_shader(R_Shader shader); +void renderer_frame_set_viewport(float x, float y, float width, float height, float min_depth, float max_depth); void renderer_frame_draw(R_Buffer vertex_buffer, R_Buffer index_buffer, R_Buffer instance_buffer, Uint32 num_indices, Uint32 num_instances, const R_Draw_Resources *resources); // Dear ImGui diff --git a/src/renderer_sdlgpu.c b/src/renderer_sdlgpu.c index bdc25ba..56719ac 100644 --- a/src/renderer_sdlgpu.c +++ b/src/renderer_sdlgpu.c @@ -331,6 +331,10 @@ void renderer_frame_set_shader(R_Shader shader) { SDL_BindGPUGraphicsPipeline(render_pass, shaders[shader]); } +void renderer_frame_set_viewport(float x, float y, float width, float height, float min_depth, float max_depth) { + SDL_SetGPUViewport(render_pass, &(SDL_GPUViewport){ .x = x, .y = y, .w = width, .h = height, .min_depth = min_depth, .max_depth = max_depth }); +} + void renderer_frame_draw(R_Buffer vertex_buffer, R_Buffer index_buffer, R_Buffer instance_buffer, Uint32 num_indices, Uint32 num_instances, const R_Draw_Resources *resources) { SDL_assert(render_pass); diff --git a/src/renderer_wgpu.c b/src/renderer_wgpu.c index 2ec5d0e..f1ae853 100644 --- a/src/renderer_wgpu.c +++ b/src/renderer_wgpu.c @@ -333,6 +333,10 @@ void renderer_frame_set_shader(R_Shader shader) { current_shader = shader; } +void renderer_frame_set_viewport(float x, float y, float width, float height, float min_depth, float max_depth) { + wgpuRenderPassEncoderSetViewport(pass_encoder, x, y, width, height, min_depth, max_depth); +} + void renderer_frame_draw(R_Buffer vertex_buffer, R_Buffer index_buffer, R_Buffer instance_buffer, Uint32 num_indices, Uint32 num_instances, const R_Draw_Resources *resources) { SDL_assert(pass_encoder);