diff --git a/assets/textures/bolder-8x8.png b/assets/textures/bolder-8x8.png new file mode 100644 index 0000000..7c28d4a Binary files /dev/null and b/assets/textures/bolder-8x8.png differ diff --git a/src/dusk/display/CMakeLists.txt b/src/dusk/display/CMakeLists.txt index 7b444ad..4f9d20f 100644 --- a/src/dusk/display/CMakeLists.txt +++ b/src/dusk/display/CMakeLists.txt @@ -7,6 +7,7 @@ target_sources(${DUSK_TARGET_NAME} PRIVATE scene.c + tileset.c ) # Subdirs \ No newline at end of file diff --git a/src/dusk/display/tileset.c b/src/dusk/display/tileset.c new file mode 100644 index 0000000..2c51748 --- /dev/null +++ b/src/dusk/display/tileset.c @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "tileset.h" + +tileset_t TILESETS[TILESET_COUNT] = { + // TILESET_NULL + { 0, 0 }, + // TILESET_FONT + { 4, 4 } +}; + +tilesetid_t TILESET_SLOTS[TILESET_SLOT_COUNT] = { + TILESET_NULL, + TILESET_NULL, + TILESET_NULL, + TILESET_NULL +}; + +uint8_t tilesetGetSlot(const tilesetid_t id) { + uint8_t i = 0; + do { + if(TILESET_SLOTS[i] == id) return i; + } while(++i < TILESET_SLOT_COUNT); + return 0xFF; +} + +bool_t tilesetIsBound(const tilesetid_t id) { + return tilesetGetSlot(id) != 0xFF; +} \ No newline at end of file diff --git a/src/dusk/display/tileset.h b/src/dusk/display/tileset.h new file mode 100644 index 0000000..0cfbe5f --- /dev/null +++ b/src/dusk/display/tileset.h @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" +#include "tilesetdefs.h" + +typedef enum { + TILESET_NULL, + TILESET_FONT +} tilesetid_t; + +#define TILESET_COUNT 2 + +typedef struct { + uint8_t columns; + uint8_t rows; +} tileset_t; + +extern tileset_t TILESETS[]; +extern tilesetid_t TILESET_SLOTS[]; + +/** + * Binds a tileset to a slot. The host can also use this to say load a texture, + * or upload to VRAM. + * + * This does not guarantee anything on the game side, rendering is responsible + * for handling anything visual. + * + * @param id The tileset to bind. + * @param slot The slot to bind the tileset to. + */ +void tilesetBind(const tilesetid_t id, const uint8_t slot); + +/** + * Gets the slot that a tileset is bound to, or 0xFF if not bound. + * + * @param id The tileset to check. + * @return The slot the tileset is bound to, or 0xFF if not bound. + */ +uint8_t tilesetGetSlot(const tilesetid_t id); + +/** + * Checks if a tileset is bound to a slot. + * + * @param id The tileset to check. + * @return TRUE if the tileset is bound, FALSE otherwise. + */ +bool_t tilesetIsBound(const tilesetid_t id); \ No newline at end of file diff --git a/src/dusk/display/tilesetdefs.h b/src/dusk/display/tilesetdefs.h new file mode 100644 index 0000000..27e7aa9 --- /dev/null +++ b/src/dusk/display/tilesetdefs.h @@ -0,0 +1,16 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#define TILESET_SLOT_0 0 +#define TILESET_SLOT_1 1 +#define TILESET_SLOT_2 2 +#define TILESET_SLOT_3 3 + +#define TILESET_SLOT_ENTITIES TILESET_SLOT_0 +#define TILESET_SLOT_MAP TILESET_SLOT_1 + +#define TILESET_SLOT_COUNT 4 \ No newline at end of file diff --git a/src/dusk/overworld/overworld.c b/src/dusk/overworld/overworld.c index 7bb5bb0..eb81fe9 100644 --- a/src/dusk/overworld/overworld.c +++ b/src/dusk/overworld/overworld.c @@ -8,6 +8,7 @@ #include "overworld.h" #include "util/memory.h" #include "assert/assert.h" +#include "display/tileset.h" overworld_t OVERWORLD; @@ -24,7 +25,7 @@ void overworldInit() { } void overworldSceneInit() { - + tilesetBind(TILESET_FONT, TILESET_SLOT_ENTITIES); } void overworldSceneDeinit() { diff --git a/src/duskgl/CMakeLists.txt b/src/duskgl/CMakeLists.txt index c7f89d6..91cd86d 100644 --- a/src/duskgl/CMakeLists.txt +++ b/src/duskgl/CMakeLists.txt @@ -27,4 +27,7 @@ target_sources(${DUSK_TARGET_NAME} # Subdirs add_subdirectory(assert) add_subdirectory(display) -add_subdirectory(overworld) \ No newline at end of file +add_subdirectory(overworld) + +# Assets +copytool("textures/bolder-8x8.png") \ No newline at end of file diff --git a/src/duskgl/display/CMakeLists.txt b/src/duskgl/display/CMakeLists.txt index 931142d..87c8a01 100644 --- a/src/duskgl/display/CMakeLists.txt +++ b/src/duskgl/display/CMakeLists.txt @@ -9,6 +9,7 @@ target_sources(${DUSK_TARGET_NAME} render.c quad.c texture.c + tilesetgl.c ) # Subdirs diff --git a/src/duskgl/display/render.c b/src/duskgl/display/render.c index 39531e3..b7c39c7 100644 --- a/src/duskgl/display/render.c +++ b/src/duskgl/display/render.c @@ -12,6 +12,7 @@ #include "display/shader/shadermanager.h" #include "display/quad.h" #include "display/window.h" +#include "display/tilesetgl.h" render_t RENDER; @@ -37,8 +38,9 @@ void renderUpdate() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); assertNoGLError(); - // Update shader stuff + // Update rendering data shaderManagerUpdate(); + tilesetGLBind(); // Hand off to the scene to do its rendering. sceneRender(); diff --git a/src/duskgl/display/shader/data/CMakeLists.txt b/src/duskgl/display/shader/data/CMakeLists.txt index babf1c4..96bcc96 100644 --- a/src/duskgl/display/shader/data/CMakeLists.txt +++ b/src/duskgl/display/shader/data/CMakeLists.txt @@ -9,4 +9,5 @@ target_sources(${DUSK_TARGET_NAME} transforms.c entities.c mapshaderdata.c + tilesetshaderdata.c ) \ No newline at end of file diff --git a/src/duskgl/display/shader/data/tilesets.glsl b/src/duskgl/display/shader/data/tilesets.glsl new file mode 100644 index 0000000..f19c0a3 --- /dev/null +++ b/src/duskgl/display/shader/data/tilesets.glsl @@ -0,0 +1,50 @@ +// Copyright (c) 2025 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#include "../../../../dusk/display/tilesetdefs.h" + +struct Tileset { + int columns; + int rows; + int width; + int height; +}; + +layout(std140) uniform b_Tilesets { + Tileset tilesets[TILESET_SLOT_COUNT]; +}; + +uniform sampler2D u_TilesetTextures[TILESET_SLOT_COUNT]; + +vec4 tilesetGetUVs(int tilesetIndex, int col, int row) { + Tileset tileset = tilesets[tilesetIndex]; + float segWidth = 1.0 / float(tileset.columns); + float segHeight = 1.0 / float(tileset.rows); + float x = float(col) * segWidth; + float y = float(row) * segHeight; + return vec4(x, y, x + segWidth, y + segHeight); +} + +vec4 tilesetGetUVsByIndex(int tilesetIndex, int index) { + Tileset tileset = tilesets[tilesetIndex]; + int col = index % tileset.columns; + int row = index / tileset.columns; + return tilesetGetUVs(tilesetIndex, col, row); +} + +vec4 tilesetGetColor(int tilesetIndex, vec2 coord) { + switch(tilesetIndex) { + case 0: + return texture(u_TilesetTextures[0], coord); + case 1: + return texture(u_TilesetTextures[1], coord); + case 2: + return texture(u_TilesetTextures[2], coord); + case 3: + return texture(u_TilesetTextures[3], coord); + default: + return vec4(1, 1, 1, 1); + } +} \ No newline at end of file diff --git a/src/duskgl/display/shader/data/tilesetshaderdata.c b/src/duskgl/display/shader/data/tilesetshaderdata.c new file mode 100644 index 0000000..ef9ec74 --- /dev/null +++ b/src/duskgl/display/shader/data/tilesetshaderdata.c @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "tilesetshaderdata.h" +#include "assert/assert.h" +#include "util/memory.h" + +shaderbuffer_t TILESET_SHADER_DATA_BUFFER; +tilesetshaderdata_t TILESET_SHADER_DATA_DATA; + +void tilesetShaderDataInit() { + memoryZero(&TILESET_SHADER_DATA_DATA, sizeof(tilesetshaderdata_t)); + shaderBufferInit(&TILESET_SHADER_DATA_BUFFER, sizeof(tilesetshaderdata_t)); +} + +void tilesetShaderDataUpdate() { + uint8_t i = 0; + do { + if(TILESET_SLOTS[i] == TILESET_NULL) continue; + tileset_t *tileset = &TILESETS[TILESET_SLOTS[i]]; + texture_t *texture = &TILESET_GL_TEXTURES[TILESET_SLOTS[i]]; + tilesetshaderdatatileset_t *dest = &TILESET_SHADER_DATA_DATA.tilesets[i]; + + dest->columns = tileset->columns; + dest->rows = tileset->rows; + dest->width = texture->width; + dest->height = texture->height; + } while(++i < TILESET_COUNT); + + shaderBufferBind(&TILESET_SHADER_DATA_BUFFER); + shaderBufferSetData(&TILESET_SHADER_DATA_BUFFER, &TILESET_SHADER_DATA_DATA); +} + +void tilesetShaderDataDispose() { + shaderBufferDispose(&TILESET_SHADER_DATA_BUFFER); +} \ No newline at end of file diff --git a/src/duskgl/display/shader/data/tilesetshaderdata.h b/src/duskgl/display/shader/data/tilesetshaderdata.h new file mode 100644 index 0000000..a0825a2 --- /dev/null +++ b/src/duskgl/display/shader/data/tilesetshaderdata.h @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "display/shader/shaderbuffer.h" +#include "display/tilesetgl.h" + +#define TILESET_BLOCK_NAME "b_Tileset" +#define TILESET_UNIFORM_TEXTURES_NAME "u_TilesetTextures" + +typedef struct { + int32_t columns; + int32_t rows; + int32_t width; + int32_t height; +} tilesetshaderdatatileset_t; + +typedef struct { + tilesetshaderdatatileset_t tilesets[TILESET_COUNT]; +} tilesetshaderdata_t; + +extern shaderbuffer_t TILESET_SHADER_DATA_BUFFER; +extern tilesetshaderdata_t TILESET_SHADER_DATA_DATA; + +/** + * Initializes the tileset buffer and data. + */ +void tilesetShaderDataInit(); + +/** + * Updates the tileset buffer with the current data. + */ +void tilesetShaderDataUpdate(); + +/** + * Destroys the tileset buffer. + */ +void tilesetShaderDataDispose(); \ No newline at end of file diff --git a/src/duskgl/display/shader/entityshader/entity_frag.glsl b/src/duskgl/display/shader/entityshader/entity_frag.glsl index 201a9a8..486e738 100644 --- a/src/duskgl/display/shader/entityshader/entity_frag.glsl +++ b/src/duskgl/display/shader/entityshader/entity_frag.glsl @@ -5,6 +5,7 @@ #include "../fragments/header.glsl" #include "../data/entities.glsl" +#include "../data/tilesets.glsl" // Inputs from vertex shader in vec2 v_TextureCoord; @@ -13,5 +14,6 @@ in vec2 v_TextureCoord; out vec4 FragColor; void main() { - FragColor = vec4(1, 1, 1, 1); + vec4 tColor = tilesetGetColor(0, v_TextureCoord); + FragColor = vec4(1, 1, 1, 1) * tColor; } diff --git a/src/duskgl/display/shader/shadermanager.c b/src/duskgl/display/shader/shadermanager.c index dd16e22..e5775c7 100644 --- a/src/duskgl/display/shader/shadermanager.c +++ b/src/duskgl/display/shader/shadermanager.c @@ -10,13 +10,15 @@ #include "display/shader/data/transforms.h" #include "display/shader/data/entities.h" #include "display/shader/data/mapshaderdata.h" +#include "display/shader/data/tilesetshaderdata.h" #include "display/shader/entityshader/entityshader.h" #include "display/shader/mapshader/mapshader.h" shadermanagerdatacallback_t SHADER_MANAGER_DATA_CALLBACKS[] = { { transformsInit, transformsUpdate, transformsDispose }, { entitiesInit, entitiesUpdate, entitiesDispose }, - { mapShaderDataInit, mapShaderDataUpdate, mapShaderDataDispose } + { mapShaderDataInit, mapShaderDataUpdate, mapShaderDataDispose }, + { tilesetShaderDataInit, tilesetShaderDataUpdate, tilesetShaderDataDispose } }; diff --git a/src/duskgl/display/tilesetgl.c b/src/duskgl/display/tilesetgl.c new file mode 100644 index 0000000..1ee87e1 --- /dev/null +++ b/src/duskgl/display/tilesetgl.c @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "tilesetgl.h" +#include "assert/assert.h" + +const char* TILESET_GL_TEXTURES_PATHS[TILESET_COUNT] = { + NULL, + "textures/bolder-8x8.png" +}; + +texture_t TILESET_GL_TEXTURES[TILESET_SLOT_COUNT]; + +void tilesetGLBind() { + uint8_t i; + do { + if(TILESET_SLOTS[i] == TILESET_NULL) continue; + textureBind(TILESET_GL_TEXTURES + i, i); + } while(++i < TILESET_SLOT_COUNT); +} + +void tilesetBind(const tilesetid_t id, const uint8_t slot) { + assertTrue(slot < TILESET_SLOT_COUNT, "Invalid slot"); + assertTrue(id < TILESET_COUNT, "Invalid tileset id"); + + TILESET_SLOTS[slot] = id; + textureLoad(TILESET_GL_TEXTURES + slot, TILESET_GL_TEXTURES_PATHS[id]); +} \ No newline at end of file diff --git a/src/duskgl/display/tilesetgl.h b/src/duskgl/display/tilesetgl.h new file mode 100644 index 0000000..514bd4e --- /dev/null +++ b/src/duskgl/display/tilesetgl.h @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "texture.h" +#include "display/tileset.h" + +extern const char* TILESET_GL_TEXTURES_PATHS[]; +extern texture_t TILESET_GL_TEXTURES[]; + +/** + * Binds the tileset to the OpenGL context. + */ +void tilesetGLBind(); \ No newline at end of file