112 lines
3.1 KiB
C
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/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);
|
|
} |