Files
dusk/archive/rpg/screen.c
2025-10-06 19:14:52 -05:00

112 lines
3.1 KiB
C

/**
* Copyright (c) 2025 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "screen.h"
#include "assert/assert.h"
#include "display/spritebatch.h"
screen_t SCREEN;
void screenInit(void) {
// Virtual backbuffer for dynamic resolution scaling
#if DISPLAY_SIZE_DYNAMIC == 1
frameBufferInit(&SCREEN.frameBuffer, DISPLAY_WIDTH, DISPLAY_HEIGHT);
cameraInit(&SCREEN.frameBufferCamera);
SCREEN.frameBufferCamera.projType = CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC;
SCREEN.frameBufferCamera.viewType = CAMERA_VIEW_TYPE_MATRIX;
glm_lookat(
(vec3){0.0f, 0.0f, 1.0f},
(vec3){0.0f, 0.0f, 0.0f},
(vec3){0.0f, 1.0f, 0.0f},
SCREEN.frameBufferCamera.view
);
SCREEN.frameBufferCamera.nearClip = -1.0f;
SCREEN.frameBufferCamera.farClip = 1.0f;
#endif
}
void screenBind(void) {
#if DISPLAY_SIZE_DYNAMIC == 1
frameBufferBind(&SCREEN.frameBuffer);
#else
frameBufferBind(NULL);
#endif
frameBufferClear(
FRAMEBUFFER_CLEAR_COLOR | FRAMEBUFFER_CLEAR_DEPTH,
COLOR_CORNFLOWER_BLUE
);
}
void screenUnbindAndRender(void) {
assertTrue(SPRITEBATCH.spriteCount == 0, "Sprite batch not flushed");
// Render to real backbuffer
#if DISPLAY_SIZE_DYNAMIC == 1
frameBufferBind(NULL);
frameBufferClear(
FRAMEBUFFER_CLEAR_COLOR | FRAMEBUFFER_CLEAR_DEPTH,
COLOR_BLACK
);
SCREEN.frameBufferCamera.orthographic.left = 0;
SCREEN.frameBufferCamera.orthographic.right = frameBufferGetWidth(
FRAMEBUFFER_BOUND
);
SCREEN.frameBufferCamera.orthographic.bottom = frameBufferGetHeight(
FRAMEBUFFER_BOUND
);
SCREEN.frameBufferCamera.orthographic.top = 0;
cameraPushMatrix(&SCREEN.frameBufferCamera);
vec2 backbuffer = {
(float_t)frameBufferGetWidth(FRAMEBUFFER_BOUND),
(float_t)frameBufferGetHeight(FRAMEBUFFER_BOUND)
};
vec2 virtual = {
(float_t)frameBufferGetWidth(&SCREEN.frameBuffer),
(float_t)frameBufferGetHeight(&SCREEN.frameBuffer)
};
// Compare aspect ratios.
vec4 viewport;
float_t backbufferAspect = backbuffer[0] / backbuffer[1];
float_t virtualAspect = virtual[0] / virtual[1];
if (backbufferAspect > virtualAspect) {
// Backbuffer is wider: pillarbox
float_t scale = backbuffer[1] / virtual[1];
float_t width = virtual[0] * scale;
viewport[0] = (backbuffer[0] - width) * 0.5f;
viewport[1] = 0;
viewport[2] = width;
viewport[3] = backbuffer[1];
} else {
// Backbuffer is taller: letterbox
float_t scale = backbuffer[0] / virtual[0];
float_t height = virtual[1] * scale;
viewport[0] = 0;
viewport[1] = (backbuffer[1] - height) * 0.5f;
viewport[2] = backbuffer[0];
viewport[3] = height;
}
spriteBatchPush(
&SCREEN.frameBuffer.texture,
viewport[0], viewport[1],
viewport[0] + viewport[2], viewport[1] + viewport[3],
COLOR_WHITE,
0.0f, 1.0f, 1.0f, 0.0f
);
spriteBatchFlush();
cameraPopMatrix();
#endif
}
void screenDispose(void) {
frameBufferDispose(&SCREEN.frameBuffer);
}