About to start shaders
This commit is contained in:
@ -23,5 +23,6 @@ target_sources(${DUSK_TARGET_NAME}
|
|||||||
|
|
||||||
# Subdirs
|
# Subdirs
|
||||||
add_subdirectory(assert)
|
add_subdirectory(assert)
|
||||||
add_subdirectory(render)
|
add_subdirectory(display)
|
||||||
add_subdirectory(overworld)
|
add_subdirectory(overworld)
|
||||||
|
add_subdirectory(util)
|
9
src/dusk/display/displaydefs.h
Normal file
9
src/dusk/display/displaydefs.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SCREEN_WIDTH 320
|
||||||
|
#define SCREEN_HEIGHT 240
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "render/scene.h"
|
#include "display/scene.h"
|
||||||
|
|
||||||
game_t GAME;
|
game_t GAME;
|
||||||
|
|
||||||
|
@ -6,7 +6,11 @@
|
|||||||
# Sources
|
# Sources
|
||||||
target_sources(${DUSK_TARGET_NAME}
|
target_sources(${DUSK_TARGET_NAME}
|
||||||
PRIVATE
|
PRIVATE
|
||||||
|
framebuffer.c
|
||||||
render.c
|
render.c
|
||||||
|
quad.c
|
||||||
|
texture.c
|
||||||
)
|
)
|
||||||
|
|
||||||
# Subdirs
|
# Subdirs
|
||||||
|
add_subdirectory(shader)
|
130
src/duskgl/display/framebuffer.c
Normal file
130
src/duskgl/display/framebuffer.c
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "framebuffer.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
#include "assert/assertgl.h"
|
||||||
|
#include "display/window.h"
|
||||||
|
|
||||||
|
framebuffer_t FRAMEBUFFER;
|
||||||
|
|
||||||
|
void frameBufferInit(const int32_t width, const int32_t height) {
|
||||||
|
assertTrue(width > 0, "Width must be greater than 0");
|
||||||
|
assertTrue(height > 0, "Height must be greater than 0");
|
||||||
|
|
||||||
|
FRAMEBUFFER.id = -1;
|
||||||
|
FRAMEBUFFER.width = -1;
|
||||||
|
FRAMEBUFFER.height = -1;
|
||||||
|
FRAMEBUFFER.texture = -1;
|
||||||
|
|
||||||
|
frameBufferSetSize(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void frameBufferSetSize(const int32_t width, const int32_t height) {
|
||||||
|
assertTrue(width > 0, "Width must be greater than 0");
|
||||||
|
assertTrue(height > 0, "Height must be greater than 0");
|
||||||
|
|
||||||
|
if(FRAMEBUFFER.width == width && FRAMEBUFFER.height == height) return;
|
||||||
|
|
||||||
|
FRAMEBUFFER.width = width;
|
||||||
|
FRAMEBUFFER.height = height;
|
||||||
|
|
||||||
|
frameBufferUnbind();
|
||||||
|
|
||||||
|
// Delete old texture and depth buffer
|
||||||
|
if(FRAMEBUFFER.texture != -1) {
|
||||||
|
glDeleteTextures(1, &FRAMEBUFFER.texture);
|
||||||
|
assertNoGLError();
|
||||||
|
FRAMEBUFFER.texture = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(FRAMEBUFFER.id != -1) {
|
||||||
|
glDeleteFramebuffers(1, &FRAMEBUFFER.id);
|
||||||
|
assertNoGLError();
|
||||||
|
FRAMEBUFFER.id = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate framebuffer
|
||||||
|
glGenFramebuffers(1, &FRAMEBUFFER.id);
|
||||||
|
assertNoGLError();
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, FRAMEBUFFER.id);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
// Create new texture
|
||||||
|
glGenTextures(1, &FRAMEBUFFER.texture);
|
||||||
|
assertNoGLError();
|
||||||
|
glBindTexture(GL_TEXTURE_2D, FRAMEBUFFER.texture);
|
||||||
|
assertNoGLError();
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
assertNoGLError();
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
assertNoGLError();
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
assertNoGLError();
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
assertNoGLError();
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
assertNoGLError();
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, FRAMEBUFFER.texture, 0);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
// Check framebuffer completeness
|
||||||
|
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||||
|
assertNoGLError();
|
||||||
|
assertTrue(status == GL_FRAMEBUFFER_COMPLETE, "Framebuffer is not complete");
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
assertNoGLError();
|
||||||
|
}
|
||||||
|
|
||||||
|
void frameBufferBind() {
|
||||||
|
if(FRAMEBUFFER.id == -1) return;
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, FRAMEBUFFER.id);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
glViewport(0, 0, FRAMEBUFFER.width, FRAMEBUFFER.height);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
assertNoGLError();
|
||||||
|
}
|
||||||
|
|
||||||
|
void frameBufferTextureBind(const GLuint slot) {
|
||||||
|
if(FRAMEBUFFER.texture == -1) return;
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE0 + slot);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, FRAMEBUFFER.texture);
|
||||||
|
assertNoGLError();
|
||||||
|
}
|
||||||
|
|
||||||
|
void frameBufferUnbind() {
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
glClearColor(0.05f, 0.05f, 0.05f, 1.0f);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
assertNoGLError();
|
||||||
|
}
|
||||||
|
|
||||||
|
void frameBufferDispose() {
|
||||||
|
glDeleteFramebuffers(1, &FRAMEBUFFER.id);
|
||||||
|
glDeleteTextures(1, &FRAMEBUFFER.texture);
|
||||||
|
|
||||||
|
FRAMEBUFFER.id = -1;
|
||||||
|
FRAMEBUFFER.texture = -1;
|
||||||
|
}
|
56
src/duskgl/display/framebuffer.h
Normal file
56
src/duskgl/display/framebuffer.h
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "duskgl.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GLuint id;
|
||||||
|
GLuint texture;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
} framebuffer_t;
|
||||||
|
|
||||||
|
extern framebuffer_t FRAMEBUFFER;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the framebuffer.
|
||||||
|
*
|
||||||
|
* @param width The width of the framebuffer.
|
||||||
|
* @param height The height of the framebuffer.
|
||||||
|
*/
|
||||||
|
void frameBufferInit(const int32_t width, const int32_t height);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the size of the framebuffer.
|
||||||
|
*
|
||||||
|
* @param width The width of the framebuffer.
|
||||||
|
* @param height The height of the framebuffer.
|
||||||
|
*/
|
||||||
|
void frameBufferSetSize(const int32_t width, const int32_t height);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Binds the framebuffer.
|
||||||
|
*/
|
||||||
|
void frameBufferBind();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unbinds the framebuffer.
|
||||||
|
*/
|
||||||
|
void frameBufferUnbind();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Binds the framebuffer texture to a slot.
|
||||||
|
*
|
||||||
|
* @param slot The slot to bind the texture to.
|
||||||
|
*/
|
||||||
|
void frameBufferTextureBind(const GLuint slot);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unbinds the framebuffer.
|
||||||
|
*/
|
||||||
|
void frameBufferDispose();
|
108
src/duskgl/display/quad.c
Normal file
108
src/duskgl/display/quad.c
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "assert/assertgl.h"
|
||||||
|
#include "quad.h"
|
||||||
|
|
||||||
|
duskquad_t QUAD;
|
||||||
|
|
||||||
|
void quadInit() {
|
||||||
|
// Create the single quad.
|
||||||
|
const float quadPositions[] = {
|
||||||
|
0.0f, 0.0f, 0.0f, // Bottom-left corner
|
||||||
|
1.0f, 0.0f, 0.0f, // Bottom-right corner
|
||||||
|
1.0f, 1.0f, 0.0f, // Top-right corner
|
||||||
|
0.0f, 1.0f, 0.0f // Top-left corner
|
||||||
|
};
|
||||||
|
|
||||||
|
const float quadUVs[] = {
|
||||||
|
0.0f, 0.0f,
|
||||||
|
1.0f, 0.0f,
|
||||||
|
1.0f, 1.0f,
|
||||||
|
0.0f, 1.0f
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint32_t quadIndices[] = {
|
||||||
|
0, 1, 2,
|
||||||
|
2, 3, 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
glGenVertexArrays(1, &QUAD.quadVAO);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
glBindVertexArray(QUAD.quadVAO);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
// Positions
|
||||||
|
glGenBuffers(1, &QUAD.quadVBO);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, QUAD.quadVBO);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
glBufferData(
|
||||||
|
GL_ARRAY_BUFFER, sizeof(quadPositions), quadPositions, GL_STATIC_DRAW
|
||||||
|
);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
// UVs
|
||||||
|
glGenBuffers(1, &QUAD.quadUVVBO);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, QUAD.quadUVVBO);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(quadUVs), quadUVs, GL_STATIC_DRAW);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(1);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
// Indices
|
||||||
|
glGenBuffers(1, &QUAD.quadEBO);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, QUAD.quadEBO);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
glBufferData(
|
||||||
|
GL_ELEMENT_ARRAY_BUFFER, sizeof(quadIndices), quadIndices, GL_STATIC_DRAW
|
||||||
|
);
|
||||||
|
assertNoGLError();
|
||||||
|
}
|
||||||
|
|
||||||
|
void quadRender(const int32_t count) {
|
||||||
|
glBindVertexArray(QUAD.quadVAO);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
glDrawElementsInstanced(
|
||||||
|
GL_TRIANGLES, 6,
|
||||||
|
GL_UNSIGNED_INT, 0,
|
||||||
|
count
|
||||||
|
);
|
||||||
|
assertNoGLError();
|
||||||
|
}
|
||||||
|
|
||||||
|
void quadDispose() {
|
||||||
|
glDeleteBuffers(1, &QUAD.quadVBO);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
glDeleteBuffers(1, &QUAD.quadEBO);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
glDeleteVertexArrays(1, &QUAD.quadVAO);
|
||||||
|
assertNoGLError();
|
||||||
|
}
|
35
src/duskgl/display/quad.h
Normal file
35
src/duskgl/display/quad.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "duskgl.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GLuint quadVBO;
|
||||||
|
GLuint quadUVVBO;
|
||||||
|
GLuint quadVAO;
|
||||||
|
GLuint quadEBO;
|
||||||
|
} duskquad_t;
|
||||||
|
|
||||||
|
extern duskquad_t QUAD;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the quad.
|
||||||
|
*/
|
||||||
|
void quadInit();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders quads.
|
||||||
|
*
|
||||||
|
* @param count The number of quads to render.
|
||||||
|
*/
|
||||||
|
void quadRender(const int32_t count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disposes of the quad.
|
||||||
|
*/
|
||||||
|
void quadDispose();
|
@ -7,12 +7,17 @@
|
|||||||
|
|
||||||
#include "assert/assertgl.h"
|
#include "assert/assertgl.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "render/scene.h"
|
#include "display/scene.h"
|
||||||
|
#include "display/shader/shadermanager.h"
|
||||||
|
#include "display/quad.h"
|
||||||
|
|
||||||
render_t RENDER;
|
render_t RENDER;
|
||||||
|
|
||||||
void renderInit() {
|
void renderInit() {
|
||||||
memset(&RENDER, 0, sizeof(render_t));
|
memset(&RENDER, 0, sizeof(render_t));
|
||||||
|
|
||||||
|
shaderManagerInit();
|
||||||
|
quadInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderUpdate() {
|
void renderUpdate() {
|
||||||
@ -21,5 +26,6 @@ void renderUpdate() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void renderDispose() {
|
void renderDispose() {
|
||||||
|
quadDispose();
|
||||||
|
shaderManagerDispose();
|
||||||
}
|
}
|
15
src/duskgl/display/shader/CMakeLists.txt
Normal file
15
src/duskgl/display/shader/CMakeLists.txt
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# Copyright (c) 2025 Dominic Masters
|
||||||
|
#
|
||||||
|
# This software is released under the MIT License.
|
||||||
|
# https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
|
# Sources
|
||||||
|
target_sources(${DUSK_TARGET_NAME}
|
||||||
|
PRIVATE
|
||||||
|
shadermanager.c
|
||||||
|
shader.c
|
||||||
|
shaderbuffer.c
|
||||||
|
)
|
||||||
|
|
||||||
|
# Subdirs
|
||||||
|
add_subdirectory(entityshader)
|
14
src/duskgl/display/shader/entityshader/CMakeLists.txt
Normal file
14
src/duskgl/display/shader/entityshader/CMakeLists.txt
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# Copyright (c) 2025 Dominic Masters
|
||||||
|
#
|
||||||
|
# This software is released under the MIT License.
|
||||||
|
# https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
|
# Shaders
|
||||||
|
glsltool(entity_vert.glsl)
|
||||||
|
glsltool(entity_frag.glsl)
|
||||||
|
|
||||||
|
# Sources
|
||||||
|
target_sources(${DUSK_TARGET_NAME}
|
||||||
|
PRIVATE
|
||||||
|
entityshader.c
|
||||||
|
)
|
27
src/duskgl/display/shader/entityshader/entity.glsl
Normal file
27
src/duskgl/display/shader/entityshader/entity.glsl
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#include "../fragments/header.glsl"
|
||||||
|
#include "../fragments/transforms.glsl"
|
||||||
|
|
||||||
|
#define ENTITY_TILE_OFFSET_X (MAP_TILE_WIDTH - ENTITY_WIDTH) / 2
|
||||||
|
#define ENTITY_TILE_OFFSET_Y (MAP_TILE_HEIGHT - ENTITY_HEIGHT) / 2
|
||||||
|
|
||||||
|
struct Entity {
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
int tileset;
|
||||||
|
int tile;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(std140) uniform b_Data {
|
||||||
|
Entity entities[MAP_ENTITY_COUNT_MAX];
|
||||||
|
int entityCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
vec4 entityGetCoordinates(Entity ent) {
|
||||||
|
int vx = (ent.x * MAP_TILE_WIDTH) + ENTITY_TILE_OFFSET_X;
|
||||||
|
int vy = (ent.y * MAP_TILE_HEIGHT) + ENTITY_TILE_OFFSET_Y;
|
||||||
|
return vec4(vx, vy, vx + ENTITY_WIDTH, vy + ENTITY_HEIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 entityGetUVs(Entity ent) {
|
||||||
|
return tilesetGetUVsByIndex(ent.tileset, ent.tile);
|
||||||
|
}
|
18
src/duskgl/display/shader/entityshader/entity_frag.glsl
Normal file
18
src/duskgl/display/shader/entityshader/entity_frag.glsl
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#include "entity.glsl"
|
||||||
|
|
||||||
|
in vec2 v_TextureCoord;
|
||||||
|
flat in int v_Entity;
|
||||||
|
|
||||||
|
out vec4 FragColor;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
Entity e = entities[v_Entity];
|
||||||
|
vec4 textureColor = tilesetGetColor(e.tileset, v_TextureCoord);
|
||||||
|
|
||||||
|
// We remove the pink color as transparent
|
||||||
|
if(textureColor.r == 1.0 && textureColor.g == 0.0 && textureColor.b == 1.0) {
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
|
||||||
|
FragColor = textureColor;
|
||||||
|
}
|
35
src/duskgl/display/shader/entityshader/entity_vert.glsl
Normal file
35
src/duskgl/display/shader/entityshader/entity_vert.glsl
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#include "entity.glsl"
|
||||||
|
|
||||||
|
// Outputs to fragment shader
|
||||||
|
out vec2 v_TextureCoord;
|
||||||
|
flat out int v_Entity;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
int entityIndex = gl_InstanceID;
|
||||||
|
int indiceIndex = gl_VertexID % 6;
|
||||||
|
|
||||||
|
Entity entity = entities[entityIndex];
|
||||||
|
|
||||||
|
vec4 quadPos = entityGetCoordinates(entity);
|
||||||
|
vec4 quadUVs = entityGetUVs(entity);
|
||||||
|
|
||||||
|
vec2 vertex;
|
||||||
|
vec2 uv;
|
||||||
|
if(indiceIndex == 0 || indiceIndex == 4) {
|
||||||
|
vertex = quadPos.xy;
|
||||||
|
uv = quadUVs.xy;
|
||||||
|
} else if(indiceIndex == 1) {
|
||||||
|
vertex = quadPos.zy;
|
||||||
|
uv = quadUVs.zy;
|
||||||
|
} else if(indiceIndex == 2 || indiceIndex == 5) {
|
||||||
|
vertex = quadPos.zw;
|
||||||
|
uv = quadUVs.zw;
|
||||||
|
} else if(indiceIndex == 3) {
|
||||||
|
vertex = quadPos.xw;
|
||||||
|
uv = quadUVs.xw;
|
||||||
|
}
|
||||||
|
|
||||||
|
gl_Position = transforms.projection * transforms.view * vec4(vertex, 0.0, 1.0);
|
||||||
|
v_TextureCoord = uv;
|
||||||
|
v_Entity = entityIndex;
|
||||||
|
}
|
32
src/duskgl/display/shader/entityshader/entityshader.c
Normal file
32
src/duskgl/display/shader/entityshader/entityshader.c
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "assert/assert.h"
|
||||||
|
#include "assert/assertgl.h"
|
||||||
|
#include "entityshader.h"
|
||||||
|
#include "entity_vert.glsl.h"
|
||||||
|
#include "entity_frag.glsl.h"
|
||||||
|
|
||||||
|
entityshader_t ENTITY_SHADER;
|
||||||
|
|
||||||
|
void entityShaderInit() {
|
||||||
|
memset(&ENTITY_SHADER, 0, sizeof(entityshader_t));
|
||||||
|
|
||||||
|
shaderInit(
|
||||||
|
&ENTITY_SHADER.shader,
|
||||||
|
entity_vertShaderSource,
|
||||||
|
entity_fragShaderSource
|
||||||
|
);
|
||||||
|
|
||||||
|
// Uniform buffers
|
||||||
|
|
||||||
|
// Uniforms
|
||||||
|
}
|
||||||
|
|
||||||
|
void entityShaderDispose() {
|
||||||
|
shaderDispose(&ENTITY_SHADER.shader);
|
||||||
|
}
|
31
src/duskgl/display/shader/entityshader/entityshader.h
Normal file
31
src/duskgl/display/shader/entityshader/entityshader.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "display/shader/shader.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
shader_t shader;
|
||||||
|
|
||||||
|
// GLuint dataBlock;
|
||||||
|
// GLuint transformsBlock;
|
||||||
|
// GLuint tilesetsBlock;
|
||||||
|
|
||||||
|
// GLuint uniformTilesetTextures;
|
||||||
|
} entityshader_t;
|
||||||
|
|
||||||
|
extern entityshader_t ENTITY_SHADER;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the entity shader.
|
||||||
|
*/
|
||||||
|
void entityShaderInit();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disposes of the entity shader.
|
||||||
|
*/
|
||||||
|
void entityShaderDispose();
|
6
src/duskgl/display/shader/fragments/header.glsl
Normal file
6
src/duskgl/display/shader/fragments/header.glsl
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#version 330 core
|
||||||
|
|
||||||
|
// Copyright (c) 2025 Dominic Masters
|
||||||
|
//
|
||||||
|
// This software is released under the MIT License.
|
||||||
|
// https://opensource.org/licenses/MIT
|
25
src/duskgl/display/shader/fragments/quad.glsl
Normal file
25
src/duskgl/display/shader/fragments/quad.glsl
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// Copyright (c) 2025 Dominic Masters
|
||||||
|
//
|
||||||
|
// This software is released under the MIT License.
|
||||||
|
// https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
|
vec2 quadGetVertice(uint indiceIndex) {
|
||||||
|
vec2 vert = vec2(0, 0);
|
||||||
|
|
||||||
|
if(indiceIndex == 0u || indiceIndex == 4u) {
|
||||||
|
// vert = vec2(0, 0);
|
||||||
|
} else if(indiceIndex == 1u) {
|
||||||
|
vert = vec2(1, 0);
|
||||||
|
} else if(indiceIndex == 2u || indiceIndex == 5u) {
|
||||||
|
vert = vec2(1, 1);
|
||||||
|
} else if(indiceIndex == 3u) {
|
||||||
|
vert = vec2(0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return vert;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 quadGetTextureCoordinate(uint indiceIndex) {
|
||||||
|
vec2 vert = quadGetVertice(indiceIndex);
|
||||||
|
return vert;
|
||||||
|
}
|
32
src/duskgl/display/shader/fragments/transforms.glsl
Normal file
32
src/duskgl/display/shader/fragments/transforms.glsl
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// Copyright (c) 2025 Dominic Masters
|
||||||
|
//
|
||||||
|
// This software is released under the MIT License.
|
||||||
|
// https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
|
#include "../../../../dusk/display/displaydefs.h"
|
||||||
|
|
||||||
|
struct Transform {
|
||||||
|
mat4 projection;
|
||||||
|
mat4 view;
|
||||||
|
vec2 resolution;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(std140) uniform b_Transforms {
|
||||||
|
Transform transforms;
|
||||||
|
};
|
||||||
|
|
||||||
|
vec2 transformDisplayGetSize() {
|
||||||
|
return vec2(DISPLAY_WIDTH, DISPLAY_HEIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
float transformDisplayGetAspectRatio() {
|
||||||
|
return (float(DISPLAY_WIDTH) / float(DISPLAY_HEIGHT));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 transformResolutionGetSize() {
|
||||||
|
return transforms.resolution;
|
||||||
|
}
|
||||||
|
|
||||||
|
float transformResolutionGetAspectRatio() {
|
||||||
|
return (transforms.resolution.x / transforms.resolution.y);
|
||||||
|
}
|
134
src/duskgl/display/shader/shader.c
Normal file
134
src/duskgl/display/shader/shader.c
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "shader.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
#include "assert/assertgl.h"
|
||||||
|
|
||||||
|
void shaderInit(
|
||||||
|
shader_t *shader,
|
||||||
|
const char *vertexSource,
|
||||||
|
const char *fragmentSource
|
||||||
|
) {
|
||||||
|
assertNotNull(shader, "shader must not be NULL");
|
||||||
|
assertNotNull(vertexSource, "vertexSource must not be NULL");
|
||||||
|
assertNotNull(fragmentSource, "fragmentSource must not be NULL");
|
||||||
|
|
||||||
|
int32_t success;
|
||||||
|
char infoLog[SHADER_LOG_LENGTH];
|
||||||
|
|
||||||
|
// Create vertex shader
|
||||||
|
shader->vertexShader = glCreateShader(GL_VERTEX_SHADER);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
glShaderSource(shader->vertexShader, 1, &vertexSource, NULL);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
glCompileShader(shader->vertexShader);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
glGetShaderiv(shader->vertexShader, GL_COMPILE_STATUS, &success);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
if(!success) {
|
||||||
|
glGetShaderInfoLog(
|
||||||
|
shader->vertexShader, SHADER_LOG_LENGTH, NULL, infoLog
|
||||||
|
);
|
||||||
|
assertNoGLError();
|
||||||
|
assertUnreachable(infoLog);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create fragment shader
|
||||||
|
shader->fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
glShaderSource(shader->fragmentShader, 1, &fragmentSource, NULL);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
glCompileShader(shader->fragmentShader);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
glGetShaderiv(shader->fragmentShader, GL_COMPILE_STATUS, &success);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
if(!success) {
|
||||||
|
glGetShaderInfoLog(
|
||||||
|
shader->fragmentShader, SHADER_LOG_LENGTH, NULL, infoLog
|
||||||
|
);
|
||||||
|
assertNoGLError();
|
||||||
|
assertUnreachable(infoLog);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create shader program
|
||||||
|
shader->shaderProgram = glCreateProgram();
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
glAttachShader(shader->shaderProgram, shader->vertexShader);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
glAttachShader(shader->shaderProgram, shader->fragmentShader);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
glLinkProgram(shader->shaderProgram);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
glGetProgramiv(shader->shaderProgram, GL_LINK_STATUS, &success);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
if(!success) {
|
||||||
|
glGetProgramInfoLog(shader->shaderProgram, SHADER_LOG_LENGTH, NULL, infoLog);
|
||||||
|
assertNoGLError();
|
||||||
|
assertUnreachable(infoLog);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void shaderUse(const shader_t *shader) {
|
||||||
|
assertNotNull(shader, "shader must not be NULL");
|
||||||
|
|
||||||
|
glUseProgram(shader->shaderProgram);
|
||||||
|
assertNoGLError();
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint shaderGetUniform(const shader_t *shader, const char_t *name) {
|
||||||
|
assertNotNull(shader, "shader must not be NULL");
|
||||||
|
assertNotNull(name, "name must not be NULL");
|
||||||
|
|
||||||
|
GLuint uniform = glGetUniformLocation(shader->shaderProgram, name);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
return uniform;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint shaderGetBlock(const shader_t *shader, const char *name) {
|
||||||
|
assertNotNull(shader, "shader must not be NULL");
|
||||||
|
assertNotNull(name, "name must not be NULL");
|
||||||
|
|
||||||
|
GLuint blockIndex = glGetUniformBlockIndex(shader->shaderProgram, name);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
// TODO: I really don't think this should be here at all.
|
||||||
|
glUniformBlockBinding(shader->shaderProgram, blockIndex, blockIndex);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
return blockIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
void shaderDispose(shader_t *shader) {
|
||||||
|
assertNotNull(shader, "shader must not be NULL");
|
||||||
|
|
||||||
|
glDeleteProgram(shader->shaderProgram);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
glDeleteShader(shader->vertexShader);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
glDeleteShader(shader->fragmentShader);
|
||||||
|
assertNoGLError();
|
||||||
|
}
|
62
src/duskgl/display/shader/shader.h
Normal file
62
src/duskgl/display/shader/shader.h
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "duskgl.h"
|
||||||
|
|
||||||
|
#define SHADER_LOG_LENGTH 512
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GLuint shaderProgram;
|
||||||
|
GLuint vertexShader;
|
||||||
|
GLuint fragmentShader;
|
||||||
|
} shader_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a shader.
|
||||||
|
*
|
||||||
|
* @param shader The shader to initialize.
|
||||||
|
* @param vertexSource The vertex shader source.
|
||||||
|
* @param fragmentSource The fragment shader source.
|
||||||
|
*/
|
||||||
|
void shaderInit(
|
||||||
|
shader_t *shader,
|
||||||
|
const char_t *vertexSource,
|
||||||
|
const char_t *fragmentSource
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uses a shader.
|
||||||
|
*
|
||||||
|
* @param shader The shader to use.
|
||||||
|
*/
|
||||||
|
void shaderUse(const shader_t *shader);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a uniform from a shader.
|
||||||
|
*
|
||||||
|
* @param shader The shader to get the uniform from.
|
||||||
|
* @param name The name of the uniform.
|
||||||
|
* @return The uniform.
|
||||||
|
*/
|
||||||
|
GLuint shaderGetUniform(const shader_t *shader, const char_t *name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a block id from a shader.
|
||||||
|
*
|
||||||
|
* @param shader The shader to get the block from.
|
||||||
|
* @param name The name of the block.
|
||||||
|
* @return The block index/identifier.
|
||||||
|
*/
|
||||||
|
GLuint shaderGetBlock(const shader_t *shader, const char_t *name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disposes of a shader.
|
||||||
|
*
|
||||||
|
* @param shader The shader to dispose of.
|
||||||
|
*/
|
||||||
|
void shaderDispose(shader_t *shader);
|
55
src/duskgl/display/shader/shaderbuffer.c
Normal file
55
src/duskgl/display/shader/shaderbuffer.c
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "assert/assert.h"
|
||||||
|
#include "shaderbuffer.h"
|
||||||
|
#include "assert/assertgl.h"
|
||||||
|
|
||||||
|
void shaderBufferInit(shaderbuffer_t *shaderBuffer, const size_t size) {
|
||||||
|
assertNotNull(shaderBuffer, "shaderBuffer cannot be NULL.");
|
||||||
|
assertTrue(size > 0, "size must be greater than 0.");
|
||||||
|
|
||||||
|
shaderBuffer->size = size;
|
||||||
|
|
||||||
|
glGenBuffers(1, &shaderBuffer->id);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
shaderBufferBind(shaderBuffer);
|
||||||
|
|
||||||
|
glBufferData(GL_UNIFORM_BUFFER, size, NULL, GL_STATIC_DRAW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void shaderBufferBind(shaderbuffer_t *shaderBuffer) {
|
||||||
|
assertNotNull(shaderBuffer, "shaderBuffer cannot be NULL.");
|
||||||
|
|
||||||
|
glBindBuffer(GL_UNIFORM_BUFFER, shaderBuffer->id);
|
||||||
|
assertNoGLError();
|
||||||
|
}
|
||||||
|
|
||||||
|
void shaderBufferSetData(shaderbuffer_t *shaderBuffer, const void *data) {
|
||||||
|
assertNotNull(shaderBuffer, "shaderBuffer cannot be NULL.");
|
||||||
|
assertNotNull(data, "data cannot be NULL.");
|
||||||
|
|
||||||
|
glBufferData(GL_UNIFORM_BUFFER, shaderBuffer->size, data, GL_STATIC_DRAW);
|
||||||
|
assertNoGLError();
|
||||||
|
}
|
||||||
|
|
||||||
|
void shaderBufferBindToBlock(
|
||||||
|
shaderbuffer_t *shaderBuffer,
|
||||||
|
const GLuint blockIndex
|
||||||
|
) {
|
||||||
|
assertNotNull(shaderBuffer, "shaderBuffer cannot be NULL.");
|
||||||
|
|
||||||
|
glBindBufferBase(GL_UNIFORM_BUFFER, blockIndex, shaderBuffer->id);
|
||||||
|
assertNoGLError();
|
||||||
|
}
|
||||||
|
|
||||||
|
void shaderBufferDispose(shaderbuffer_t *shaderBuffer) {
|
||||||
|
assertNotNull(shaderBuffer, "shaderBuffer cannot be NULL.");
|
||||||
|
glDeleteBuffers(1, &shaderBuffer->id);
|
||||||
|
assertNoGLError();
|
||||||
|
}
|
61
src/duskgl/display/shader/shaderbuffer.h
Normal file
61
src/duskgl/display/shader/shaderbuffer.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "duskgl.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GLuint id;
|
||||||
|
size_t size;
|
||||||
|
} shaderbuffer_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a shader buffer.
|
||||||
|
*
|
||||||
|
* @param shaderBuffer The shader buffer to initialize.
|
||||||
|
* @param size The size of the buffer.
|
||||||
|
*/
|
||||||
|
void shaderBufferInit(
|
||||||
|
shaderbuffer_t *shaderBuffer,
|
||||||
|
const size_t size
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Binds a shader buffer.
|
||||||
|
*
|
||||||
|
* @param shaderBuffer The shader buffer to bind.
|
||||||
|
*/
|
||||||
|
void shaderBufferBind(shaderbuffer_t *shaderBuffer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the data of a shader buffer.
|
||||||
|
*
|
||||||
|
* @param shaderBuffer The shader buffer to set the data of.
|
||||||
|
* @param data The data to set.
|
||||||
|
*/
|
||||||
|
void shaderBufferSetData(
|
||||||
|
shaderbuffer_t *shaderBuffer,
|
||||||
|
const void *data
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Binds a shader buffer to a block.
|
||||||
|
*
|
||||||
|
* @param shaderBuffer The shader buffer to bind.
|
||||||
|
* @param blockIndex The block index to bind to.
|
||||||
|
*/
|
||||||
|
void shaderBufferBindToBlock(
|
||||||
|
shaderbuffer_t *shaderBuffer,
|
||||||
|
const GLuint blockIndex
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disposes of a shader buffer.
|
||||||
|
*
|
||||||
|
* @param shaderBuffer The shader buffer to dispose of.
|
||||||
|
*/
|
||||||
|
void shaderBufferDispose(shaderbuffer_t *shaderBuffer);
|
16
src/duskgl/display/shader/shadermanager.c
Normal file
16
src/duskgl/display/shader/shadermanager.c
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "shadermanager.h"
|
||||||
|
|
||||||
|
void shaderManagerInit() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void shaderManagerDispose() {
|
||||||
|
|
||||||
|
}
|
23
src/duskgl/display/shader/shadermanager.h
Normal file
23
src/duskgl/display/shader/shadermanager.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "duskgl.h"
|
||||||
|
|
||||||
|
// typedef struct {
|
||||||
|
|
||||||
|
// } shadermanager_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the Shader Manager
|
||||||
|
*/
|
||||||
|
void shaderManagerInit();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disposes of the Shader Manager
|
||||||
|
*/
|
||||||
|
void shaderManagerDispose();
|
102
src/duskgl/display/texture.c
Normal file
102
src/duskgl/display/texture.c
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2023 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "texture.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
#include "assert/assertgl.h"
|
||||||
|
#include "asset.h"
|
||||||
|
#include "util/math.h"
|
||||||
|
|
||||||
|
#define TEXTURE_BUFFER_SIZE 32768
|
||||||
|
|
||||||
|
int32_t TEXTURE_ACTIVE_COUNT;
|
||||||
|
|
||||||
|
void textureLoad(
|
||||||
|
texture_t *texture,
|
||||||
|
const char_t *path
|
||||||
|
) {
|
||||||
|
assertNotNull(texture, "Texture is null.");
|
||||||
|
assertNotNull(path, "Path is null.");
|
||||||
|
|
||||||
|
// Open asset
|
||||||
|
assetOpen(path);
|
||||||
|
|
||||||
|
// Setup spng
|
||||||
|
spng_ctx *ctx = spng_ctx_new(0);
|
||||||
|
spng_set_png_stream(ctx, &textureSPNGBuffer, NULL);
|
||||||
|
|
||||||
|
// Get image info
|
||||||
|
struct spng_ihdr ihdr;
|
||||||
|
spng_get_ihdr(ctx, &ihdr);
|
||||||
|
texture->width = ihdr.width;
|
||||||
|
texture->height = ihdr.height;
|
||||||
|
|
||||||
|
// Decode the image. I can probably stream this in the future.
|
||||||
|
size_t dataSize = ihdr.width * ihdr.height * 4;// 4 for RGBA
|
||||||
|
uint8_t *data = (uint8_t *)malloc(dataSize);
|
||||||
|
assertNotNull(data, "Failed to allocate memory for texture data.");
|
||||||
|
spng_decode_image(ctx, data, dataSize, SPNG_FMT_RGBA8, 0);
|
||||||
|
|
||||||
|
// Finish decoding
|
||||||
|
spng_ctx_free(ctx);
|
||||||
|
assetClose();
|
||||||
|
|
||||||
|
// Create texture
|
||||||
|
glGenTextures(1, &texture->id);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture->id);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
// Buffer then cleanup
|
||||||
|
glTexImage2D(
|
||||||
|
GL_TEXTURE_2D, 0, GL_RGBA,
|
||||||
|
texture->width, texture->height,
|
||||||
|
0, GL_RGBA, GL_UNSIGNED_BYTE, data
|
||||||
|
);
|
||||||
|
assertNoGLError();
|
||||||
|
free(data);
|
||||||
|
|
||||||
|
// Setup texture parameters
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
assertNoGLError();
|
||||||
|
}
|
||||||
|
|
||||||
|
void textureBind(
|
||||||
|
const texture_t *texture,
|
||||||
|
const GLuint slot
|
||||||
|
) {
|
||||||
|
assertNotNull(texture, "Texture is null.");
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE0 + slot);
|
||||||
|
assertNoGLError();
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture->id);
|
||||||
|
assertNoGLError();
|
||||||
|
}
|
||||||
|
|
||||||
|
void textureDispose(texture_t *texture) {
|
||||||
|
glDeleteTextures(1, &texture->id);
|
||||||
|
assertNoGLError();
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t textureSPNGBuffer(
|
||||||
|
spng_ctx *ctx,
|
||||||
|
void *user,
|
||||||
|
void *destination,
|
||||||
|
size_t length
|
||||||
|
) {
|
||||||
|
size_t read = assetRead(destination, length);
|
||||||
|
if(read == 0) return SPNG_IO_EOF;
|
||||||
|
return SPNG_OK;
|
||||||
|
}
|
63
src/duskgl/display/texture.h
Normal file
63
src/duskgl/display/texture.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2023 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "duskgl.h"
|
||||||
|
#include <spng.h>
|
||||||
|
|
||||||
|
extern int32_t TEXTURE_ACTIVE_COUNT;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t width;
|
||||||
|
uint32_t height;
|
||||||
|
GLuint id;
|
||||||
|
} texture_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a texture to be read to be used.
|
||||||
|
*
|
||||||
|
* @param texture Texture to initialize.
|
||||||
|
* @param path Path of the file to load.
|
||||||
|
*/
|
||||||
|
void textureLoad(
|
||||||
|
texture_t *texture,
|
||||||
|
const char_t *path
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Binds the texture to the given slot (for use by the shaders).
|
||||||
|
*
|
||||||
|
* @param texture Texture to bind.
|
||||||
|
* @param slot Slot to bind to.
|
||||||
|
*/
|
||||||
|
void textureBind(
|
||||||
|
const texture_t *texture,
|
||||||
|
const GLuint slot
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unloads a previously initialized texture.
|
||||||
|
*
|
||||||
|
* @param texture Texture to destroy.
|
||||||
|
*/
|
||||||
|
void textureDispose(texture_t *texture);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback function for libspng to read from the asset.
|
||||||
|
*
|
||||||
|
* @param ctx The spng context.
|
||||||
|
* @param user User data.
|
||||||
|
* @param destination Destination buffer.
|
||||||
|
* @param length Length of the buffer.
|
||||||
|
* @return The amount of data read.
|
||||||
|
*/
|
||||||
|
int32_t textureSPNGBuffer(
|
||||||
|
spng_ctx *ctx,
|
||||||
|
void *user,
|
||||||
|
void *destination,
|
||||||
|
size_t length
|
||||||
|
);
|
@ -7,9 +7,10 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "duskglfw.h"
|
#include "duskglfw.h"
|
||||||
|
#include "display/displaydefs.h"
|
||||||
|
|
||||||
#define WINDOW_WIDTH_DEFAULT 800
|
#define WINDOW_WIDTH_DEFAULT SCREEN_WIDTH*4
|
||||||
#define WINDOW_HEIGHT_DEFAULT 600
|
#define WINDOW_HEIGHT_DEFAULT SCREEN_HEIGHT*4
|
||||||
|
|
||||||
extern GLFWwindow* window;
|
extern GLFWwindow* window;
|
||||||
extern int32_t WINDOW_WIDTH;
|
extern int32_t WINDOW_WIDTH;
|
||||||
|
Reference in New Issue
Block a user