Added screen
This commit is contained in:
@@ -9,6 +9,7 @@ target_sources(${DUSK_TARGET_NAME}
|
||||
display.c
|
||||
camera.c
|
||||
tileset.c
|
||||
screen.c
|
||||
)
|
||||
|
||||
# Subdirectories
|
||||
|
@@ -12,6 +12,7 @@
|
||||
#include "display/spritebatch/spritebatch.h"
|
||||
#include "display/ui/ui.h"
|
||||
#include "display/mesh/quad.h"
|
||||
#include "display/screen.h"
|
||||
|
||||
display_t DISPLAY;
|
||||
|
||||
@@ -68,6 +69,7 @@ errorret_t displayInit(void) {
|
||||
spriteBatchInit();
|
||||
errorChain(uiInit());
|
||||
errorChain(sceneManagerInit());
|
||||
screenInit();
|
||||
|
||||
errorOk();
|
||||
}
|
||||
@@ -85,24 +87,10 @@ errorret_t displayUpdate(void) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: move to framebuffer component
|
||||
int32_t windowWidth, windowHeight;
|
||||
#if PSP
|
||||
windowWidth = DISPLAY_WINDOW_WIDTH_DEFAULT;
|
||||
windowHeight = DISPLAY_WINDOW_HEIGHT_DEFAULT;
|
||||
#else
|
||||
SDL_GetWindowSize(DISPLAY.window, &windowWidth, &windowHeight);
|
||||
#endif
|
||||
glViewport(0, 0, windowWidth, windowHeight);
|
||||
#endif
|
||||
|
||||
spriteBatchClear();
|
||||
frameBufferBind(&FRAMEBUFFER_BACKBUFFER);
|
||||
frameBufferClear(
|
||||
FRAMEBUFFER_CLEAR_COLOR | FRAMEBUFFER_CLEAR_DEPTH,
|
||||
COLOR_CORNFLOWER_BLUE
|
||||
);
|
||||
screenBind();
|
||||
|
||||
sceneManagerUpdate();
|
||||
uiUpdate();
|
||||
@@ -110,6 +98,8 @@ errorret_t displayUpdate(void) {
|
||||
sceneManagerRender();
|
||||
uiRender();
|
||||
|
||||
screenUnbindAndRender();
|
||||
|
||||
#if DISPLAY_SDL2
|
||||
SDL_GL_SwapWindow(DISPLAY.window);
|
||||
#endif
|
||||
@@ -124,6 +114,7 @@ errorret_t displayUpdate(void) {
|
||||
}
|
||||
|
||||
errorret_t displayDispose(void) {
|
||||
screenDispose();
|
||||
sceneManagerDispose();
|
||||
uiDispose();
|
||||
spriteBatchDispose();
|
||||
|
@@ -6,37 +6,10 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "displaydefs.h"
|
||||
#include "error/error.h"
|
||||
|
||||
#if DISPLAY_SDL2
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glext.h>
|
||||
|
||||
#ifndef DISPLAY_SIZE_DYNAMIC
|
||||
#define DISPLAY_SIZE_DYNAMIC 1
|
||||
#endif
|
||||
#else
|
||||
#error "Need to specify display backend."
|
||||
#endif
|
||||
|
||||
#ifndef DISPLAY_WIDTH
|
||||
#define DISPLAY_WIDTH 320
|
||||
#endif
|
||||
#ifndef DISPLAY_HEIGHT
|
||||
#define DISPLAY_HEIGHT 240
|
||||
#endif
|
||||
|
||||
#ifndef DISPLAY_WINDOW_WIDTH_DEFAULT
|
||||
#define DISPLAY_WINDOW_WIDTH_DEFAULT DISPLAY_WIDTH
|
||||
#endif
|
||||
#ifndef DISPLAY_WINDOW_HEIGHT_DEFAULT
|
||||
#define DISPLAY_WINDOW_HEIGHT_DEFAULT DISPLAY_HEIGHT
|
||||
#endif
|
||||
|
||||
|
||||
#include "display/camera.h"
|
||||
#include "display/framebuffer/framebuffer.h"
|
||||
|
||||
typedef struct {
|
||||
#if DISPLAY_SDL2
|
||||
|
36
src/display/displaydefs.h
Normal file
36
src/display/displaydefs.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if DISPLAY_SDL2
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glext.h>
|
||||
|
||||
#ifndef DISPLAY_SIZE_DYNAMIC
|
||||
#define DISPLAY_SIZE_DYNAMIC 1
|
||||
#endif
|
||||
#else
|
||||
#error "Need to specify display backend."
|
||||
#endif
|
||||
|
||||
#ifndef DISPLAY_WIDTH
|
||||
#define DISPLAY_WIDTH 320
|
||||
#endif
|
||||
#ifndef DISPLAY_HEIGHT
|
||||
#define DISPLAY_HEIGHT 240
|
||||
#endif
|
||||
|
||||
#ifndef DISPLAY_WINDOW_WIDTH_DEFAULT
|
||||
#define DISPLAY_WINDOW_WIDTH_DEFAULT DISPLAY_WIDTH
|
||||
#endif
|
||||
#ifndef DISPLAY_WINDOW_HEIGHT_DEFAULT
|
||||
#define DISPLAY_WINDOW_HEIGHT_DEFAULT DISPLAY_HEIGHT
|
||||
#endif
|
@@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#include "framebuffer.h"
|
||||
#include "display/display.h"
|
||||
#include "assert/assert.h"
|
||||
#include "util/memory.h"
|
||||
|
||||
@@ -19,6 +20,41 @@ void frameBufferInitBackbuffer() {
|
||||
FRAMEBUFFER_BOUND = &FRAMEBUFFER_BACKBUFFER;
|
||||
}
|
||||
|
||||
#if DISPLAY_SIZE_DYNAMIC == 1
|
||||
void frameBufferInit(
|
||||
framebuffer_t *framebuffer,
|
||||
const uint32_t width,
|
||||
const uint32_t height
|
||||
) {
|
||||
#if DISPLAY_SDL2 == 1
|
||||
assertNotNull(framebuffer, "Framebuffer cannot be NULL");
|
||||
assertTrue(width > 0 && height > 0, "Width & height must be greater than 0");
|
||||
|
||||
memoryZero(framebuffer, sizeof(framebuffer_t));
|
||||
textureInit(&framebuffer->texture, width, height, GL_RGBA, (texturedata_t){
|
||||
.rgba = { .colors = NULL }
|
||||
});
|
||||
|
||||
glGenFramebuffersEXT(1, &framebuffer->id);
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer->id);
|
||||
|
||||
glFramebufferTexture2DEXT(
|
||||
GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
|
||||
GL_TEXTURE_2D, framebuffer->texture.id, 0
|
||||
);
|
||||
|
||||
if(
|
||||
glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) !=
|
||||
GL_FRAMEBUFFER_COMPLETE_EXT
|
||||
) {
|
||||
assertUnreachable("Framebuffer is not complete");
|
||||
}
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
int32_t frameBufferGetWidth(const framebuffer_t *framebuffer) {
|
||||
#if DISPLAY_SDL2
|
||||
if(framebuffer == &FRAMEBUFFER_BACKBUFFER) {
|
||||
@@ -31,8 +67,7 @@ int32_t frameBufferGetWidth(const framebuffer_t *framebuffer) {
|
||||
#endif
|
||||
}
|
||||
|
||||
assertUnreachable("Framebuffer width not implemented");
|
||||
return 0;
|
||||
return framebuffer->texture.width;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -48,8 +83,7 @@ int32_t frameBufferGetHeight(const framebuffer_t *framebuffer) {
|
||||
#endif
|
||||
}
|
||||
|
||||
assertUnreachable("Framebuffer height not implemented");
|
||||
return 0;
|
||||
return framebuffer->texture.height;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -78,6 +112,7 @@ void frameBufferBind(const framebuffer_t *framebuffer) {
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer->id);
|
||||
#endif
|
||||
}
|
||||
|
||||
glViewport(
|
||||
0, 0,
|
||||
frameBufferGetWidth(framebuffer), frameBufferGetHeight(framebuffer)
|
||||
@@ -109,11 +144,6 @@ void frameBufferClear(uint8_t flags, color_t color) {
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Disposes of the framebuffer using EXT methods.
|
||||
*
|
||||
* @param framebuffer The framebuffer to dispose of.
|
||||
*/
|
||||
void frameBufferDispose(framebuffer_t *framebuffer) {
|
||||
assertNotNull(framebuffer, "Framebuffer cannot be NULL");
|
||||
|
||||
@@ -125,56 +155,8 @@ void frameBufferDispose(framebuffer_t *framebuffer) {
|
||||
#if DISPLAY_SIZE_DYNAMIC == 0
|
||||
assertUnreachable("Dynamic size framebuffers not supported");
|
||||
#else
|
||||
textureDispose(&framebuffer->texture);
|
||||
glDeleteFramebuffersEXT(1, &framebuffer->id);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
// #if RENDER_USE_FRAMEBUFFER
|
||||
// void frameBufferInit(
|
||||
// framebuffer_t *framebuffer,
|
||||
// const uint32_t width,
|
||||
// const uint32_t height
|
||||
// ) {
|
||||
// assertNotNull(framebuffer, "Framebuffer cannot be NULL");
|
||||
// assertTrue(width > 0 && height > 0, "Width & height must be greater than 0");
|
||||
|
||||
// memoryZero(framebuffer, sizeof(framebuffer_t));
|
||||
// textureInit(&framebuffer->texture, width, height, GL_RGBA, NULL);
|
||||
|
||||
// // Generate the framebuffer object using EXT
|
||||
// glGenFramebuffersEXT(1, &framebuffer->id);
|
||||
// glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer->id);
|
||||
|
||||
// // Attach the texture to the framebuffer
|
||||
// glFramebufferTexture2DEXT(
|
||||
// GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
|
||||
// GL_TEXTURE_2D, framebuffer->texture.id, 0
|
||||
// );
|
||||
|
||||
// // Check if the framebuffer is complete
|
||||
// if(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) {
|
||||
// assertUnreachable("Framebuffer is not complete");
|
||||
// }
|
||||
|
||||
// // Unbind the framebuffer
|
||||
// glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
// }
|
||||
|
||||
// void frameBufferBind(const framebuffer_t *framebuffer) {
|
||||
// if(framebuffer == NULL) {
|
||||
// glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
// return;
|
||||
// }
|
||||
|
||||
// // Bind the framebuffer for rendering
|
||||
// glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer->id);
|
||||
// }
|
||||
|
||||
// void frameBufferDispose(framebuffer_t *framebuffer) {
|
||||
// assertNotNull(framebuffer, "Framebuffer cannot be NULL");
|
||||
|
||||
// glDeleteFramebuffersEXT(1, &framebuffer->id);
|
||||
// textureDispose(&framebuffer->texture);
|
||||
// }
|
||||
// #endif
|
||||
}
|
@@ -6,23 +6,43 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "display/display.h"
|
||||
#include "display/texture/texture.h"
|
||||
|
||||
#define FRAMEBUFFER_CLEAR_COLOR (1 << 0)
|
||||
#define FRAMEBUFFER_CLEAR_DEPTH (1 << 1)
|
||||
|
||||
typedef struct {
|
||||
#if DISPLAY_SDL2
|
||||
#if DISPLAY_SDL2 == 1
|
||||
// OpenGL Framebuffer Object ID
|
||||
GLuint id;
|
||||
texture_t texture;
|
||||
#else
|
||||
#error "Framebuffers not implemented on this platform."
|
||||
#endif
|
||||
} framebuffer_t;
|
||||
|
||||
extern framebuffer_t FRAMEBUFFER_BACKBUFFER;
|
||||
extern const framebuffer_t *FRAMEBUFFER_BOUND;
|
||||
|
||||
void frameBufferInitBackbuffer();
|
||||
/**
|
||||
* Initializes the backbuffer framebuffer.
|
||||
*/
|
||||
void frameBufferInitBackbuffer(void);
|
||||
|
||||
/**
|
||||
* Initializes a framebuffer.
|
||||
*
|
||||
* @param framebuffer The framebuffer to initialize.
|
||||
* @param width The width of the framebuffer.
|
||||
* @param height The height of the framebuffer.
|
||||
*/
|
||||
#if DISPLAY_SIZE_DYNAMIC == 1
|
||||
void frameBufferInit(
|
||||
framebuffer_t *framebuffer,
|
||||
const uint32_t width,
|
||||
const uint32_t height
|
||||
);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Gets the width of the framebuffer.
|
||||
|
112
src/display/screen.c
Normal file
112
src/display/screen.c
Normal file
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* 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);
|
||||
}
|
41
src/display/screen.h
Normal file
41
src/display/screen.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "display/camera.h"
|
||||
#include "display/framebuffer/framebuffer.h"
|
||||
|
||||
typedef struct {
|
||||
#if DISPLAY_SIZE_DYNAMIC == 1
|
||||
framebuffer_t frameBuffer;
|
||||
camera_t frameBufferCamera;
|
||||
#else
|
||||
void *empty;
|
||||
#endif
|
||||
} screen_t;
|
||||
|
||||
extern screen_t SCREEN;
|
||||
|
||||
/**
|
||||
* Initializes the screen.
|
||||
*/
|
||||
void screenInit(void);
|
||||
|
||||
/**
|
||||
* Binds the screen for rendering.
|
||||
*/
|
||||
void screenBind(void);
|
||||
|
||||
/**
|
||||
* Unbinds the screen and renders it.
|
||||
*/
|
||||
void screenUnbindAndRender(void);
|
||||
|
||||
/**
|
||||
* Disposes of the screen.
|
||||
*/
|
||||
void screenDispose(void);
|
@@ -44,7 +44,6 @@ void textureInit(
|
||||
|
||||
switch(format) {
|
||||
case TEXTURE_FORMAT_RGBA:
|
||||
assertNotNull(data.rgba.colors, "RGBA texture data cannot be NULL");
|
||||
glTexImage2D(
|
||||
GL_TEXTURE_2D, 0, format, width, height, 0,
|
||||
format, GL_UNSIGNED_BYTE, (void*)data.rgba.colors
|
||||
@@ -52,7 +51,6 @@ void textureInit(
|
||||
break;
|
||||
|
||||
case TEXTURE_FORMAT_ALPHA:
|
||||
assertNotNull(data.alpha.data, "Alpha texture data cannot be NULL");
|
||||
glTexImage2D(
|
||||
GL_TEXTURE_2D, 0, format, width, height, 0,
|
||||
format, GL_UNSIGNED_BYTE, (void*)data.alpha.data
|
||||
|
@@ -6,8 +6,8 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "display/display.h"
|
||||
#include "display/color.h"
|
||||
#include "display/displaydefs.h"
|
||||
|
||||
typedef enum {
|
||||
#if DISPLAY_SDL2
|
||||
|
Reference in New Issue
Block a user