diff --git a/assets/textures/8x8.png b/assets/textures/8x8.png new file mode 100644 index 0000000..46f927b Binary files /dev/null and b/assets/textures/8x8.png differ diff --git a/assets/textures/bolder-8x8.png b/assets/textures/bolder-8x8.png deleted file mode 100644 index 7c28d4a..0000000 Binary files a/assets/textures/bolder-8x8.png and /dev/null differ diff --git a/src/dusk/display/tileset.c b/src/dusk/display/tileset.c index 2c51748..aa5de98 100644 --- a/src/dusk/display/tileset.c +++ b/src/dusk/display/tileset.c @@ -11,7 +11,7 @@ tileset_t TILESETS[TILESET_COUNT] = { // TILESET_NULL { 0, 0 }, // TILESET_FONT - { 4, 4 } + { 1, 88 } }; tilesetid_t TILESET_SLOTS[TILESET_SLOT_COUNT] = { diff --git a/src/dusk/display/tilesetdefs.h b/src/dusk/display/tilesetdefs.h index 27e7aa9..62e0b76 100644 --- a/src/dusk/display/tilesetdefs.h +++ b/src/dusk/display/tilesetdefs.h @@ -10,7 +10,7 @@ #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_ENTITIES TILESET_SLOT_1 +#define TILESET_SLOT_MAP TILESET_SLOT_2 #define TILESET_SLOT_COUNT 4 \ No newline at end of file diff --git a/src/duskgl/CMakeLists.txt b/src/duskgl/CMakeLists.txt index 91cd86d..c163e8d 100644 --- a/src/duskgl/CMakeLists.txt +++ b/src/duskgl/CMakeLists.txt @@ -30,4 +30,4 @@ add_subdirectory(display) add_subdirectory(overworld) # Assets -copytool("textures/bolder-8x8.png") \ No newline at end of file +copytool("textures/8x8.png") \ No newline at end of file diff --git a/src/duskgl/display/shader/data/tilesets.glsl b/src/duskgl/display/shader/data/tilesets.glsl index f19c0a3..39fc5e9 100644 --- a/src/duskgl/display/shader/data/tilesets.glsl +++ b/src/duskgl/display/shader/data/tilesets.glsl @@ -4,12 +4,10 @@ // https://opensource.org/licenses/MIT #include "../../../../dusk/display/tilesetdefs.h" +#include "../fragments/packed.glsl" struct Tileset { - int columns; - int rows; - int width; - int height; + uvec4 tileset; }; layout(std140) uniform b_Tilesets { @@ -18,31 +16,47 @@ layout(std140) uniform b_Tilesets { uniform sampler2D u_TilesetTextures[TILESET_SLOT_COUNT]; -vec4 tilesetGetUVs(int tilesetIndex, int col, int row) { +uint tilesetGetColumns(uint tilesetIndex) { + return packedGetU32(0u, tilesets[tilesetIndex].tileset); +} + +uint tilesetGetRows(uint tilesetIndex) { + return packedGetU32(1u, tilesets[tilesetIndex].tileset); +} + +uint tilesetGetWidth(uint tilesetIndex) { + return packedGetU32(2u, tilesets[tilesetIndex].tileset); +} + +uint tilesetGetHeight(uint tilesetIndex) { + return packedGetU32(3u, tilesets[tilesetIndex].tileset); +} + +vec4 tilesetGetUVs(uint tilesetIndex, uint col, uint row) { Tileset tileset = tilesets[tilesetIndex]; - float segWidth = 1.0 / float(tileset.columns); - float segHeight = 1.0 / float(tileset.rows); + float segWidth = 1.0 / float(tilesetGetColumns(tilesetIndex)); + float segHeight = 1.0 / float(tilesetGetRows(tilesetIndex)); float x = float(col) * segWidth; float y = float(row) * segHeight; return vec4(x, y, x + segWidth, y + segHeight); } -vec4 tilesetGetUVsByIndex(int tilesetIndex, int index) { +vec4 tilesetGetUVsByIndex(uint tilesetIndex, uint index) { Tileset tileset = tilesets[tilesetIndex]; - int col = index % tileset.columns; - int row = index / tileset.columns; + uint col = index % tilesetGetColumns(tilesetIndex); + uint row = index / tilesetGetColumns(tilesetIndex); return tilesetGetUVs(tilesetIndex, col, row); } -vec4 tilesetGetColor(int tilesetIndex, vec2 coord) { +vec4 tilesetGetColor(uint tilesetIndex, vec2 coord) { switch(tilesetIndex) { - case 0: + case 0u: return texture(u_TilesetTextures[0], coord); - case 1: + case 1u: return texture(u_TilesetTextures[1], coord); - case 2: + case 2u: return texture(u_TilesetTextures[2], coord); - case 3: + case 3u: return texture(u_TilesetTextures[3], coord); default: return vec4(1, 1, 1, 1); diff --git a/src/duskgl/display/shader/data/tilesetshaderdata.c b/src/duskgl/display/shader/data/tilesetshaderdata.c index ef9ec74..df96677 100644 --- a/src/duskgl/display/shader/data/tilesetshaderdata.c +++ b/src/duskgl/display/shader/data/tilesetshaderdata.c @@ -8,33 +8,50 @@ #include "tilesetshaderdata.h" #include "assert/assert.h" #include "util/memory.h" +#include "display/shader/shader.h" shaderbuffer_t TILESET_SHADER_DATA_BUFFER; tilesetshaderdata_t TILESET_SHADER_DATA_DATA; +GLuint TILESET_SHADER_DATA_TEXTURES[TILESET_SLOT_COUNT]; void tilesetShaderDataInit() { memoryZero(&TILESET_SHADER_DATA_DATA, sizeof(tilesetshaderdata_t)); shaderBufferInit(&TILESET_SHADER_DATA_BUFFER, sizeof(tilesetshaderdata_t)); + + assertTrue( + sizeof(tilesetshaderdata_t) == sizeof(uvec4_t) * TILESET_SLOT_COUNT, + "Tileset Shader Data size mismatch" + ); + + uint8_t i = 0; + do { + TILESET_SHADER_DATA_TEXTURES[i] = i; + } while(++i < TILESET_SLOT_COUNT); } 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]]; + tilesetid_t id = TILESET_SLOTS[i]; + if(id == TILESET_NULL) continue; + tileset_t *tileset = &TILESETS[id]; + texture_t *texture = &TILESET_GL_TEXTURES[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); + } while(++i < TILESET_SLOT_COUNT); shaderBufferBind(&TILESET_SHADER_DATA_BUFFER); shaderBufferSetData(&TILESET_SHADER_DATA_BUFFER, &TILESET_SHADER_DATA_DATA); } +void tilesetShaderTexturesBind(const GLuint uniform) { + shaderSetTextures(uniform, TILESET_SHADER_DATA_TEXTURES, TILESET_SLOT_COUNT); +} + 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 index a0825a2..604cd49 100644 --- a/src/duskgl/display/shader/data/tilesetshaderdata.h +++ b/src/duskgl/display/shader/data/tilesetshaderdata.h @@ -9,22 +9,23 @@ #include "display/shader/shaderbuffer.h" #include "display/tilesetgl.h" -#define TILESET_BLOCK_NAME "b_Tileset" +#define TILESET_SHADER_DATA_BLOCK_NAME "b_Tilesets" #define TILESET_UNIFORM_TEXTURES_NAME "u_TilesetTextures" typedef struct { - int32_t columns; - int32_t rows; - int32_t width; - int32_t height; + uint32_t columns; + uint32_t rows; + uint32_t width; + uint32_t height; } tilesetshaderdatatileset_t; typedef struct { - tilesetshaderdatatileset_t tilesets[TILESET_COUNT]; + tilesetshaderdatatileset_t tilesets[TILESET_SLOT_COUNT]; } tilesetshaderdata_t; extern shaderbuffer_t TILESET_SHADER_DATA_BUFFER; extern tilesetshaderdata_t TILESET_SHADER_DATA_DATA; +extern GLuint TILESET_SHADER_DATA_TEXTURES[]; /** * Initializes the tileset buffer and data. @@ -36,6 +37,13 @@ void tilesetShaderDataInit(); */ void tilesetShaderDataUpdate(); +/** + * Binds the tileset textures to the given uniform. + * + * @param uniform The uniform to bind the textures to. + */ +void tilesetShaderTexturesBind(const GLuint uniform); + /** * Destroys the tileset buffer. */ diff --git a/src/duskgl/display/shader/entityshader/entity_frag.glsl b/src/duskgl/display/shader/entityshader/entity_frag.glsl index 486e738..1d70729 100644 --- a/src/duskgl/display/shader/entityshader/entity_frag.glsl +++ b/src/duskgl/display/shader/entityshader/entity_frag.glsl @@ -14,6 +14,6 @@ in vec2 v_TextureCoord; out vec4 FragColor; void main() { - vec4 tColor = tilesetGetColor(0, v_TextureCoord); + vec4 tColor = tilesetGetColor(uint(TILESET_SLOT_ENTITIES), v_TextureCoord); FragColor = vec4(1, 1, 1, 1) * tColor; } diff --git a/src/duskgl/display/shader/entityshader/entity_vert.glsl b/src/duskgl/display/shader/entityshader/entity_vert.glsl index e326847..2cf084d 100644 --- a/src/duskgl/display/shader/entityshader/entity_vert.glsl +++ b/src/duskgl/display/shader/entityshader/entity_vert.glsl @@ -6,6 +6,7 @@ #include "../fragments/header.glsl" #include "../data/transforms.glsl" #include "../data/entities.glsl" +#include "../data/tilesets.glsl" // Outputs to fragment shader out vec2 v_TextureCoord; @@ -14,8 +15,10 @@ void main() { uint instanceIndex = uint(gl_InstanceID); uint indiceIndex = quadGetIndiceIndex(gl_VertexID); + vec4 tilesetUVs = tilesetGetUVsByIndex(uint(TILESET_SLOT_ENTITIES), 1u); + vec2 vert = entityGetVertice(instanceIndex, indiceIndex); - vec2 uv = quadGetTextureCoordinate(indiceIndex); + vec2 uv = quadGetTextureCoordinate(indiceIndex, tilesetUVs); gl_Position = transforms.projection * transforms.view * vec4(vert, 0.0, 1.0); v_TextureCoord = uv; diff --git a/src/duskgl/display/shader/entityshader/entityshader.c b/src/duskgl/display/shader/entityshader/entityshader.c index 051fa6d..96874e7 100644 --- a/src/duskgl/display/shader/entityshader/entityshader.c +++ b/src/duskgl/display/shader/entityshader/entityshader.c @@ -13,6 +13,7 @@ #include "entity_frag.glsl.h" #include "display/shader/data/transforms.h" #include "display/shader/data/entities.h" +#include "display/shader/data/tilesetshaderdata.h" entityshader_t ENTITY_SHADER; @@ -36,13 +37,26 @@ void entityShaderInit() { ENTITIES_BLOCK_NAME ); + ENTITY_SHADER.tilesetsBlock = shaderGetBlock( + &ENTITY_SHADER.shader, + TILESET_SHADER_DATA_BLOCK_NAME + ); + // Uniforms + ENTITY_SHADER.tilesetTexturesUniform = shaderGetUniform( + &ENTITY_SHADER.shader, + TILESET_UNIFORM_TEXTURES_NAME + ); } void entityShaderUse() { shaderUse(&ENTITY_SHADER.shader); shaderBufferBindToBlock(&TRANSFORMS_BUFFER, ENTITY_SHADER.transformsBlock); shaderBufferBindToBlock(&ENTITIES_BUFFER, ENTITY_SHADER.entitiesBlock); + shaderBufferBindToBlock( + &TILESET_SHADER_DATA_BUFFER, ENTITY_SHADER.tilesetsBlock + ); + tilesetShaderTexturesBind(ENTITY_SHADER.tilesetTexturesUniform); } void entityShaderDispose() { diff --git a/src/duskgl/display/shader/entityshader/entityshader.h b/src/duskgl/display/shader/entityshader/entityshader.h index 1662317..a243dbc 100644 --- a/src/duskgl/display/shader/entityshader/entityshader.h +++ b/src/duskgl/display/shader/entityshader/entityshader.h @@ -10,8 +10,12 @@ typedef struct { shader_t shader; + GLuint entitiesBlock; GLuint transformsBlock; + GLuint tilesetsBlock; + + GLuint tilesetTexturesUniform; } entityshader_t; extern entityshader_t ENTITY_SHADER; diff --git a/src/duskgl/display/shader/fragments/packed.glsl b/src/duskgl/display/shader/fragments/packed.glsl index fcc5928..e37f5fd 100644 --- a/src/duskgl/display/shader/fragments/packed.glsl +++ b/src/duskgl/display/shader/fragments/packed.glsl @@ -11,6 +11,10 @@ uint packedGetU8(uint position, uvec4 data) { return (subData >> (position * 8u)) & 0xFFu; } +uint packedGetU32(uint position, uvec4 data) { + return data[position]; +} + int packedGetI8(uint position, uvec4 data) { uint subData = data[position / 4u]; diff --git a/src/duskgl/display/shader/fragments/quad.glsl b/src/duskgl/display/shader/fragments/quad.glsl index 74f9d63..949fcac 100644 --- a/src/duskgl/display/shader/fragments/quad.glsl +++ b/src/duskgl/display/shader/fragments/quad.glsl @@ -14,9 +14,9 @@ uint quadGetIndiceIndex(int vertexId) { vec2 quadGetVertice(uint indiceIndex) { vec2 vert = vec2(0, 0); - if(indiceIndex == 0u || indiceIndex == 4u) { + /*if(indiceIndex == 0u || indiceIndex == 4u) { // vert = vec2(0, 0); - } else if(indiceIndex == 1u) { + } else*/ if(indiceIndex == 1u) { vert = vec2(1, 0); } else if(indiceIndex == 2u || indiceIndex == 5u) { vert = vec2(1, 1); @@ -30,4 +30,10 @@ vec2 quadGetVertice(uint indiceIndex) { vec2 quadGetTextureCoordinate(uint indiceIndex) { vec2 vert = quadGetVertice(indiceIndex); return vert; +} + +vec2 quadGetTextureCoordinate(uint indiceIndex, vec4 uv) { + vec2 vert = quadGetVertice(indiceIndex); + vert.y = 1.0 - vert.y; + return vec2(uv.x + (uv.z - uv.x) * vert.x, uv.y + (uv.w - uv.y) * vert.y); } \ No newline at end of file diff --git a/src/duskgl/display/shader/shader.c b/src/duskgl/display/shader/shader.c index 6a43e03..9c068d8 100644 --- a/src/duskgl/display/shader/shader.c +++ b/src/duskgl/display/shader/shader.c @@ -120,6 +120,18 @@ GLuint shaderGetBlock(const shader_t *shader, const char *name) { return blockIndex; } +void shaderSetTextures( + const GLuint uniform, + const GLuint *textures, + const uint8_t count +) { + assertNotNull(textures, "textures must not be NULL"); + assertTrue(count > 0, "count must be greater than 0"); + + glUniform1iv(uniform, count, textures); + assertNoGLError(); +} + void shaderDispose(shader_t *shader) { assertNotNull(shader, "shader must not be NULL"); diff --git a/src/duskgl/display/shader/shader.h b/src/duskgl/display/shader/shader.h index 1bc6395..4c84589 100644 --- a/src/duskgl/display/shader/shader.h +++ b/src/duskgl/display/shader/shader.h @@ -54,6 +54,19 @@ GLuint shaderGetUniform(const shader_t *shader, const char_t *name); */ GLuint shaderGetBlock(const shader_t *shader, const char_t *name); +/** + * Sets texture uniforms to a shader. + * + * @param uniform The uniform to set. + * @param textures The textures to set. + * @param count The number of textures to set. + */ +void shaderSetTextures( + const GLuint uniform, + const GLuint *textures, + const uint8_t count +); + /** * Disposes of a shader. * diff --git a/src/duskgl/display/tilesetgl.c b/src/duskgl/display/tilesetgl.c index 1ee87e1..ac94028 100644 --- a/src/duskgl/display/tilesetgl.c +++ b/src/duskgl/display/tilesetgl.c @@ -10,7 +10,7 @@ const char* TILESET_GL_TEXTURES_PATHS[TILESET_COUNT] = { NULL, - "textures/bolder-8x8.png" + "textures/8x8.png" }; texture_t TILESET_GL_TEXTURES[TILESET_SLOT_COUNT];