This commit is contained in:
2026-06-18 20:25:54 -05:00
parent 730a5b2b10
commit 57b2cdb9d1
111 changed files with 865 additions and 3328 deletions
+2 -4
View File
@@ -3,12 +3,10 @@
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
# Includes
target_include_directories(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC
${CMAKE_CURRENT_LIST_DIR}
)
# Subdirs
add_subdirectory(display)
add_subdirectory(error)
add_subdirectory(error)
add_subdirectory(render)
-16
View File
@@ -1,16 +0,0 @@
# Copyright (c) 2026 Dominic Masters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
# Sources
target_sources(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC
displaygl.c
)
# Subdirs
add_subdirectory(framebuffer)
add_subdirectory(texture)
add_subdirectory(mesh)
add_subdirectory(shader)
-22
View File
@@ -1,22 +0,0 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "displaygl.h"
errorret_t displayOpenGLInit(void) {
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
errorChain(errorGLCheck());
#if DUSK_OPENGL_LEGACY
glDisable(GL_LIGHTING);// PSP defaults this on?
errorChain(errorGLCheck());
glShadeModel(GL_SMOOTH); // Fixes color on PSP?
errorChain(errorGLCheck());
#endif
errorOk();
}
-16
View File
@@ -1,16 +0,0 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "error/errorgl.h"
/**
* Initializes the OpenGL specific contexts for rendering.
*
* @return An errorret_t indicating success or failure of the initialization.
*/
errorret_t displayOpenGLInit(void);
@@ -1,10 +0,0 @@
# Copyright (c) 2026 Dominic Masters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
# Sources
target_sources(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC
framebuffergl.c
)
@@ -1,149 +0,0 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "display/display.h"
#include "display/framebuffer/framebuffer.h"
#include "assert/assertgl.h"
#include "util/memory.h"
errorret_t frameBufferGLInitBackBuffer(void) {
errorOk();
}
uint32_t frameBufferGLGetWidth(const framebuffer_t *framebuffer) {
if(framebuffer == NULL) {
return 0;
}
if(framebuffer == &FRAMEBUFFER_BACKBUFFER) {
#ifdef DUSK_DISPLAY_SIZE_DYNAMIC
int32_t windowWidth, windowHeight;
SDL_GetWindowSize(DISPLAY.window, &windowWidth, &windowHeight);
return windowWidth;
#else
return DUSK_DISPLAY_WIDTH;
#endif
}
return framebuffer->texture.width;
}
uint32_t frameBufferGLGetHeight(const framebuffer_t *framebuffer) {
if(framebuffer == NULL) {
return 0;
}
if(framebuffer == &FRAMEBUFFER_BACKBUFFER) {
#ifdef DUSK_DISPLAY_SIZE_DYNAMIC
int32_t windowWidth, windowHeight;
SDL_GetWindowSize(DISPLAY.window, &windowWidth, &windowHeight);
return windowHeight;
#else
return DUSK_DISPLAY_HEIGHT;
#endif
}
return framebuffer->texture.height;
}
errorret_t frameBufferGLBind(framebuffer_t *framebuffer) {
assertNotNull(framebuffer, "Framebuffer cannot be NULL");
#ifdef DUSK_DISPLAY_SIZE_DYNAMIC
if(framebuffer == &FRAMEBUFFER_BACKBUFFER) {
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
} else {
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer->id);
}
glViewport(
0, 0,
frameBufferGetWidth(framebuffer), frameBufferGetHeight(framebuffer)
);
#else
glViewport(
0, 0,
DUSK_DISPLAY_WIDTH, DUSK_DISPLAY_HEIGHT
);
#endif
errorChain(errorGLCheck());
errorOk();
}
void frameBufferGLClear(const uint8_t flags, const color_t color) {
GLbitfield glFlags = 0;
if(flags & FRAMEBUFFER_CLEAR_COLOR) {
glFlags |= GL_COLOR_BUFFER_BIT;
glClearColor(
color.r / 255.0f,
color.g / 255.0f,
color.b / 255.0f,
color.a / 255.0f
);
assertNoGLError("Failed to set clear color");
}
if(flags & FRAMEBUFFER_CLEAR_DEPTH) {
glFlags |= GL_DEPTH_BUFFER_BIT;
}
glClear(glFlags);
assertNoGLError("Failed to clear framebuffer");
}
#ifdef DUSK_DISPLAY_SIZE_DYNAMIC
errorret_t frameBufferGLInit(
framebuffer_t *fb,
const uint32_t width,
const uint32_t height
) {
assertNotNull(fb, "Framebuffer cannot be NULL");
assertTrue(width > 0 && height > 0, "W/H must be greater than 0");
memoryZero(fb, sizeof(framebuffer_t));
textureInit(&fb->texture, width, height, TEXTURE_FORMAT_RGBA,
(texturedata_t){ .rgbaColors = NULL }
);
errorChain(errorGLCheck());
glGenFramebuffersEXT(1, &fb->id);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->id);
errorChain(errorGLCheck());
glFramebufferTexture2DEXT(
GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, fb->texture.id, 0
);
errorChain(errorGLCheck());
if(
glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) !=
GL_FRAMEBUFFER_COMPLETE_EXT
) {
assertUnreachable("Framebuffer is not complete");
}
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
errorChain(errorGLCheck());
errorOk();
}
errorret_t frameBufferGLDispose(framebuffer_t *framebuffer) {
assertNotNull(framebuffer, "Framebuffer cannot be NULL");
if(framebuffer == &FRAMEBUFFER_BACKBUFFER) {
assertUnreachable("Cannot dispose of backbuffer");
}
errorChain(textureDispose(&framebuffer->texture));
glDeleteFramebuffersEXT(1, &framebuffer->id);
errorChain(errorGLCheck());
errorOk();
}
#endif
@@ -1,78 +0,0 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "display/texture/texture.h"
#include "error/errorgl.h"
typedef struct {
GLuint id;
texture_t texture;
} framebuffergl_t;
/**
* Initializes the backbuffer framebuffer. (OpenGL implementation).
*/
errorret_t frameBufferGLInitBackBuffer(void);
/**
* Gets the height of the framebuffer. (OpenGL implementation).
*
* @param framebuffer The framebuffer to get the height of.
* @return The height of the framebuffer, or 0 if the framebuffer is NULL.
*/
uint32_t frameBufferGLGetWidth(const framebuffergl_t *framebuffer);
/**
* Initializes an OpenGL style framebuffer.
*
* @param fb The framebuffer to initialize.
* @param width The width of the framebuffer.
* @param height The height of the framebuffer.
* @return Either error or not.
*/
uint32_t frameBufferGLGetHeight(const framebuffergl_t *framebuffer);
/**
* Gets the width of the framebuffer. (OpenGL implementation).
*
* @param framebuffer The framebuffer to get the width of.
* @return The width of the framebuffer, or 0 if the framebuffer is NULL.
*/
errorret_t frameBufferGLBind(framebuffergl_t *framebuffer);
/**
* Clears the framebuffer with the specified flags and color.
*
* @param flags The clear flags.
* @param color The clear color.
*/
void frameBufferGLClear(const uint8_t flags, const color_t color);
#ifdef DUSK_DISPLAY_SIZE_DYNAMIC
/**
* Initializes an OpenGL style framebuffer.
*
* @param fb The framebuffer to initialize.
* @param width The width of the framebuffer.
* @param height The height of the framebuffer.
* @return Either error or not.
*/
errorret_t frameBufferGLInit(
framebuffergl_t *fb,
const uint32_t width,
const uint32_t height
);
/**
* Disposes of the framebuffer. Will also be used for request disposing of the
* backbuffer.
*
* @param framebuffer The framebuffer to dispose of.
*/
errorret_t frameBufferGLDispose(framebuffergl_t *framebuffer);
#endif
@@ -1,21 +0,0 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "display/framebuffer/framebuffergl.h"
typedef framebuffergl_t framebufferplatform_t;
#define frameBufferPlatformInitBackBuffer frameBufferGLInitBackBuffer
#define frameBufferPlatformGetWidth frameBufferGLGetWidth
#define frameBufferPlatformGetHeight frameBufferGLGetHeight
#define frameBufferPlatformBind frameBufferGLBind
#define frameBufferPlatformClear frameBufferGLClear
#ifdef DUSK_DISPLAY_SIZE_DYNAMIC
#define frameBufferPlatformInit frameBufferGLInit
#define frameBufferPlatformDispose frameBufferGLDispose
#endif
-196
View File
@@ -1,196 +0,0 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "display/mesh/mesh.h"
#include "assert/assertgl.h"
#include "error/errorgl.h"
#include "display/shader/shadergl.h"
errorret_t meshInitGL(
meshgl_t *mesh,
const meshprimitivetypegl_t primitiveType,
const int32_t vertexCount,
const meshvertex_t *vertices
) {
assertNotNull(mesh, "Mesh cannot be NULL");
assertNotNull(vertices, "Vertices cannot be NULL");
assertTrue(vertexCount > 0, "Vertex count must be greater than 0");
mesh->primitiveType = primitiveType;
mesh->vertexCount = vertexCount;
mesh->vertices = vertices;
#ifdef DUSK_OPENGL_LEGACY
// Nothing needed.
#if MESH_ENABLE_COLOR
glEnableClientState(GL_COLOR_ARRAY);
errorChain(errorGLCheck());
#endif
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
errorChain(errorGLCheck());
glEnableClientState(GL_VERTEX_ARRAY);
errorChain(errorGLCheck());
#else
// Generate Vertex Buffer Object
glGenBuffers(1, &mesh->vboId);
errorChain(errorGLCheck());
glBindBuffer(GL_ARRAY_BUFFER, mesh->vboId);
errorChain(errorGLCheck());
glBufferData(
GL_ARRAY_BUFFER,
vertexCount * sizeof(meshvertex_t),
vertices,
GL_DYNAMIC_DRAW
);
errorChain(errorGLCheck());
// Generate Vertex Array Object
glGenVertexArrays(1, &mesh->vaoId);
errorChain(errorGLCheck());
glBindVertexArray(mesh->vaoId);
errorChain(errorGLCheck());
glBindBuffer(GL_ARRAY_BUFFER, mesh->vboId);
errorChain(errorGLCheck());
// Set up vertex attribute pointers
glVertexAttribPointer(
0,
MESH_VERTEX_POS_SIZE,
GL_FLOAT,
GL_FALSE,
sizeof(meshvertex_t),
(const GLvoid*)offsetof(meshvertex_t, pos)
);
errorChain(errorGLCheck());
glEnableVertexAttribArray(0);
errorChain(errorGLCheck());
glVertexAttribPointer(
1,
MESH_VERTEX_UV_SIZE,
GL_FLOAT,
GL_FALSE,
sizeof(meshvertex_t),
(const GLvoid*)offsetof(meshvertex_t, uv)
);
errorChain(errorGLCheck());
glEnableVertexAttribArray(1);
errorChain(errorGLCheck());
#if MESH_ENABLE_COLOR
glVertexAttribPointer(
2,
sizeof(color_t) / sizeof(GLubyte),
GL_UNSIGNED_BYTE,
GL_TRUE,
sizeof(meshvertex_t),
(const GLvoid*)offsetof(meshvertex_t, color)
);
errorChain(errorGLCheck());
glEnableVertexAttribArray(2);
errorChain(errorGLCheck());
#endif
// Unbind VAO and VBO to prevent accidental modification
glBindBuffer(GL_ARRAY_BUFFER, 0);
errorChain(errorGLCheck());
glBindVertexArray(0);
errorChain(errorGLCheck());
#endif
errorOk();
}
errorret_t meshFlushGL(
meshgl_t *mesh,
const int32_t vertOffset,
const int32_t vertCount
) {
#ifdef DUSK_OPENGL_LEGACY
// Nothing doing, we use the glClientState stuff.
#else
glBindBuffer(GL_ARRAY_BUFFER, mesh->vboId);
errorChain(errorGLCheck());
glBufferData(
GL_ARRAY_BUFFER,
mesh->vertexCount * sizeof(meshvertex_t),
mesh->vertices,
// vertCount * sizeof(meshvertex_t),
// &mesh->vertices[vertOffset],
GL_DYNAMIC_DRAW
);
errorChain(errorGLCheck());
#endif
errorOk();
}
errorret_t meshDrawGL(
const meshgl_t *mesh,
const int32_t offset,
const int32_t count
) {
#ifdef DUSK_OPENGL_LEGACY
// Legacy pointer style rendering
const GLsizei stride = sizeof(meshvertex_t);
#if MESH_ENABLE_COLOR
glColorPointer(
sizeof(color4b_t),
GL_UNSIGNED_BYTE,
stride,
(const GLvoid*)&mesh->vertices[offset].color
);
#endif
glTexCoordPointer(
MESH_VERTEX_UV_SIZE,
GL_FLOAT,
stride,
(const GLvoid*)&mesh->vertices[offset].uv[0]
);
glVertexPointer(
MESH_VERTEX_POS_SIZE,
GL_FLOAT,
stride,
(const GLvoid*)&mesh->vertices[offset].pos[0]
);
// Shader may have model matrix here
errorChain(shaderLegacyMatrixUpdate());
glDrawArrays(mesh->primitiveType, 0, count);
errorChain(errorGLCheck());
#else
// Modern VAO/VBO rendering
glBindVertexArray(mesh->vaoId);
errorChain(errorGLCheck());
glDrawArrays(mesh->primitiveType, offset, count);
errorChain(errorGLCheck());
glBindVertexArray(0);
errorChain(errorGLCheck());
#endif
errorOk();
}
int32_t meshGetVertexCountGL(const meshgl_t *mesh) {
return mesh->vertexCount;
}
errorret_t meshDisposeGL(meshgl_t *mesh) {
#ifdef DUSK_OPENGL_LEGACY
// No dynamic resources to free for this mesh implementation
#else
glDeleteBuffers(1, &mesh->vboId);
errorChain(errorGLCheck());
glDeleteVertexArrays(1, &mesh->vaoId);
errorChain(errorGLCheck());
#endif
errorOk();
}
-89
View File
@@ -1,89 +0,0 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "error/error.h"
#include "display/mesh/meshvertex.h"
typedef enum {
MESH_PRIMITIVE_TYPE_TRIANGLES = GL_TRIANGLES,
MESH_PRIMITIVE_TYPE_LINES = GL_LINES,
MESH_PRIMITIVE_TYPE_POINTS = GL_POINTS,
} meshprimitivetypegl_t;
typedef struct {
int32_t vertexCount;
meshprimitivetypegl_t primitiveType;
const meshvertex_t *vertices;
#ifdef DUSK_OPENGL_LEGACY
// Nothing needed
#else
GLuint vaoId;
GLuint vboId;
#endif
} meshgl_t;
/**
* Initializes a mesh for OpenGL.
*
* @param mesh The mesh to initialize.
* @param primitiveType The OpenGL primitive type (e.g., GL_TRIANGLES).
* @param vertexCount The number of vertices in the mesh.
* @param vertices The vertex data for the mesh.
* @return An errorret_t indicating success or failure.
*/
errorret_t meshInitGL(
meshgl_t *mesh,
const meshprimitivetypegl_t primitiveType,
const int32_t vertexCount,
const meshvertex_t *vertices
);
/**
* Flushes the vertices (stored in memory) to the GPU.
*
* @param mesh Mesh to flush vertices for.
* @param vertOffset First vertice index to flush.
* @param vertCount Count of vertices to flush.
* @return Error state.
*/
errorret_t meshFlushGL(
meshgl_t *mesh,
const int32_t vertOffset,
const int32_t vertCount
);
/**
* Draws a mesh using OpenGL.
*
* @param mesh The mesh to draw.
* @param vertexOffset The offset in the vertex array to start drawing from.
* @param vertexCount The number of vertices to draw. If -1, draws all vertices.
* @return An errorret_t indicating success or failure.
*/
errorret_t meshDrawGL(
const meshgl_t *mesh,
const int32_t vertexOffset,
const int32_t vertexCount
);
/**
* Gets the vertex count of a mesh used for OpenGL.
*
* @param mesh The mesh to get the vertex count from.
* @return The vertex count of the mesh.
*/
int32_t meshGetVertexCountGL(const meshgl_t *mesh);
/**
* Disposes a mesh used for OpenGL.
*
* @param mesh The mesh to dispose.
* @return An errorret_t indicating success or failure.
*/
errorret_t meshDisposeGL(meshgl_t *mesh);
-18
View File
@@ -1,18 +0,0 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "meshgl.h"
typedef meshprimitivetypegl_t meshprimitivetypeplatform_t;
typedef meshgl_t meshplatform_t;
#define meshInitPlatform meshInitGL
#define meshFlushPlatform meshFlushGL
#define meshDrawPlatform meshDrawGL
#define meshGetVertexCountPlatform meshGetVertexCountGL
#define meshDisposePlatform meshDisposeGL
-11
View File
@@ -1,11 +0,0 @@
# Copyright (c) 2026 Dominic Masters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
# Sources
target_sources(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC
shadergl.c
shaderunlitgl.c
)
-415
View File
@@ -1,415 +0,0 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "shadergl.h"
#include "util/memory.h"
#include "util/string.h"
#include "assert/assertgl.h"
#include "display/shader/shaderunlit.h"
#ifdef DUSK_OPENGL_LEGACY
shaderlegacygl_t SHADER_LEGACY = { 0 };
#endif
errorret_t shaderInitGL(shadergl_t *shader, const shaderdefinitiongl_t *def) {
assertNotNull(shader, "Shader cannot be null");
assertNotNull(def, "Shader definition cannot be null");
memoryZero(shader, sizeof(shadergl_t));
shader->definition = def;
#ifdef DUSK_OPENGL_LEGACY
glm_mat4_identity(shader->view);
glm_mat4_identity(shader->proj);
glm_mat4_identity(shader->model);
SHADER_LEGACY.boundShader = NULL;
errorOk();
#else
assertNotNull(def->vert, "Vertex shader source cannot be null");
assertNotNull(def->frag, "Fragment shader source cannot be null");
// Create vertex shader
shader->vertexShaderId = glCreateShader(GL_VERTEX_SHADER);
errorret_t err = errorGLCheck();
errorChain(err);
glShaderSource(shader->vertexShaderId, 1, &def->vert, NULL);
err = errorGLCheck();
if(errorIsNotOk(err)) {
glDeleteShader(shader->vertexShaderId);
errorChain(err);
}
glCompileShader(shader->vertexShaderId);
err = errorGLCheck();
if(errorIsNotOk(err)) {
glDeleteShader(shader->vertexShaderId);
errorChain(err);
}
GLint ok = 0;
glGetShaderiv(shader->vertexShaderId, GL_COMPILE_STATUS, &ok);
if(!ok) {
GLchar log[1024];
glGetShaderInfoLog(shader->vertexShaderId, sizeof(log), NULL, log);
glDeleteShader(shader->vertexShaderId);
errorThrow("Vertex shader compilation failed: %s", log);
}
// Create fragment shader
shader->fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER);
err = errorGLCheck();
if(errorIsNotOk(err)) {
glDeleteShader(shader->vertexShaderId);
errorChain(err);
}
glShaderSource(shader->fragmentShaderId, 1, &def->frag, NULL);
err = errorGLCheck();
if(errorIsNotOk(err)) {
glDeleteShader(shader->vertexShaderId);
glDeleteShader(shader->fragmentShaderId);
errorChain(err);
}
glCompileShader(shader->fragmentShaderId);
err = errorGLCheck();
if(errorIsNotOk(err)) {
glDeleteShader(shader->vertexShaderId);
glDeleteShader(shader->fragmentShaderId);
errorChain(err);
}
glGetShaderiv(shader->fragmentShaderId, GL_COMPILE_STATUS, &ok);
if(!ok) {
GLchar log[1024];
glGetShaderInfoLog(shader->fragmentShaderId, sizeof(log), NULL, log);
glDeleteShader(shader->vertexShaderId);
glDeleteShader(shader->fragmentShaderId);
errorThrow("Fragment shader compilation failed: %s", log);
}
// Create shader program
shader->shaderProgramId = glCreateProgram();
err = errorGLCheck();
if(errorIsNotOk(err)) {
glDeleteShader(shader->vertexShaderId);
glDeleteShader(shader->fragmentShaderId);
errorChain(err);
}
glAttachShader(shader->shaderProgramId, shader->vertexShaderId);
err = errorGLCheck();
if(errorIsNotOk(err)) {
glDeleteProgram(shader->shaderProgramId);
glDeleteShader(shader->vertexShaderId);
glDeleteShader(shader->fragmentShaderId);
errorChain(err);
}
glAttachShader(shader->shaderProgramId, shader->fragmentShaderId);
err = errorGLCheck();
if(errorIsNotOk(err)) {
glDeleteProgram(shader->shaderProgramId);
glDeleteShader(shader->vertexShaderId);
glDeleteShader(shader->fragmentShaderId);
errorChain(err);
}
glLinkProgram(shader->shaderProgramId);
err = errorGLCheck();
if(errorIsNotOk(err)) {
glDeleteProgram(shader->shaderProgramId);
glDeleteShader(shader->vertexShaderId);
glDeleteShader(shader->fragmentShaderId);
errorChain(err);
}
ok = 0;
glGetProgramiv(shader->shaderProgramId, GL_LINK_STATUS, &ok);
if(!ok) {
GLchar log[1024];
glGetProgramInfoLog(shader->shaderProgramId, sizeof(log), NULL, log);
glDeleteProgram(shader->shaderProgramId);
glDeleteShader(shader->vertexShaderId);
glDeleteShader(shader->fragmentShaderId);
errorThrow("Shader program linking failed: %s", log);
}
#endif
errorOk();
}
errorret_t shaderParamGetLocationGL(
shadergl_t *shader,
const char_t *name,
GLint *location
) {
assertNotNull(shader, "Shader cannot be null");
assertStrLenMin(name, 1, "Uniform name cannot be empty");
assertNotNull(location, "Location cannot be null");
#ifdef DUSK_OPENGL_LEGACY
assertUnreachable("Cannot get uniform locations on legacy opengl.");
#else
*location = glGetUniformLocation(shader->shaderProgramId, name);
errorChain(errorGLCheck());
if(*location == -1) {
errorThrow("Uniform '%s' not found in shader.", name);
}
#endif
errorOk();
}
errorret_t shaderSetMatrixGL(
shadergl_t *shader,
const char_t *name,
mat4 mat
) {
assertNotNull(shader, "Shader cannot be null");
assertStrLenMin(name, 1, "Uniform name cannot be empty");
assertNotNull(mat, "Matrix data cannot be null");
#ifdef DUSK_OPENGL_LEGACY
assertTrue(
SHADER_LEGACY.boundShader == shader,
"Shader must be bound to set legacy matrices."
);
// Use unaligned copy to safely handle possibly unaligned input matrices
if(stringCompare(name, SHADER_UNLIT_PROJECTION) == 0) {
SHADER_LEGACY.dirty |= SHADER_LEGACY_DIRTY_PROJ;
glm_mat4_ucopy(mat, shader->proj);
} else if(stringCompare(name, SHADER_UNLIT_VIEW) == 0) {
SHADER_LEGACY.dirty |= SHADER_LEGACY_DIRTY_VIEW;
glm_mat4_ucopy(mat, shader->view);
} else if(stringCompare(name, SHADER_UNLIT_MODEL) == 0) {
SHADER_LEGACY.dirty |= SHADER_LEGACY_DIRTY_MODEL;
glm_mat4_ucopy(mat, shader->model);
} else {
assertUnreachable("Cannot use a custom matrix on legacy opengl.");
}
#else
GLint location;
errorChain(shaderParamGetLocationGL(shader, name, &location));
glUniformMatrix4fv(location, 1, GL_FALSE, (const GLfloat *)mat);
errorChain(errorGLCheck());
#endif
errorOk();
}
errorret_t shaderSetTextureGL(
shadergl_t *shader,
const char_t *name,
texture_t *texture
) {
assertNotNull(shader, "Shader cannot be null");
assertStrLenMin(name, 1, "Uniform name cannot be empty");
#ifdef DUSK_OPENGL_LEGACY
assertStringEqual(
name,
SHADER_UNLIT_TEXTURE,
"Only one texture supported in legacy opengl."
);
// glActiveTexture(GL_TEXTURE0);
errorChain(errorGLCheck());
if(texture == NULL) {
glDisable(GL_TEXTURE_2D);
errorChain(errorGLCheck());
errorOk();
}
glEnable(GL_TEXTURE_2D);
errorChain(errorGLCheck());
glBindTexture(GL_TEXTURE_2D, texture->id);
errorChain(errorGLCheck());
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
errorChain(errorGLCheck());
// glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
// errorChain(errorGLCheck());
// glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
// errorChain(errorGLCheck());
// glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
// errorChain(errorGLCheck());
// glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
// errorChain(errorGLCheck());
// glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PRIMARY_COLOR);
// errorChain(errorGLCheck());
// glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
// errorChain(errorGLCheck());
#else
assertNotNull(shader->definition, "Shader definition cannot be null");
assertNotNull(shader->definition->setTexture, "Shader cannot do textures.");
errorChain(shader->definition->setTexture(shader, name, texture));
#endif
errorOk();
}
errorret_t shaderSetColorGL(
shadergl_t *shader,
const char_t *name,
color_t color
) {
assertNotNull(shader, "Shader cannot be null");
assertStrLenMin(name, 1, "Uniform name cannot be empty");
#ifdef DUSK_OPENGL_LEGACY
// if(color.a == 0) {
// glDisable(GL_TEXTURE_2D);
// errorChain(errorGLCheck());
// errorOk();
// }
// glActiveTexture(GL_TEXTURE1);
// errorChain(errorGLCheck());
// if(color.r == 255 && color.g == 255 && color.b == 255) {
// glDisable(GL_TEXTURE_2D);
// errorChain(errorGLCheck());
// errorOk();
// }
// glEnable(GL_TEXTURE_2D);
// errorChain(errorGLCheck());
// glBindTexture(GL_TEXTURE_2D, TEXTURE_WHITE.id);
// errorChain(errorGLCheck());
// GLfloat tint[4] = {
// ((float_t)color.r) / 255.0f,
// ((float_t)color.g) / 255.0f,
// ((float_t)color.b) / 255.0f,
// ((float_t)color.a) / 255.0f
// };
// glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, tint);
// errorChain(errorGLCheck());
// glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
// errorChain(errorGLCheck());
// glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
// errorChain(errorGLCheck());
// glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
// errorChain(errorGLCheck());
// glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
// errorChain(errorGLCheck());
// glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_CONSTANT);
// errorChain(errorGLCheck());
// glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
// errorChain(errorGLCheck());
glColor4f(
(float_t)color.r / 255.0f,
(float_t)color.g / 255.0f,
(float_t)color.b / 255.0f,
(float_t)color.a / 255.0f
);
errorChain(errorGLCheck());
#else
GLint location;
errorChain(shaderParamGetLocationGL(shader, name, &location));
glUniform4f(
location,
color.r / 255.0f,
color.g / 255.0f,
color.b / 255.0f,
color.a / 255.0f
);
errorChain(errorGLCheck());
#endif
errorOk();
}
errorret_t shaderBindGL(shadergl_t *shader) {
#ifdef DUSK_OPENGL_LEGACY
assertNotNull(shader, "Cannot bind a null shader.");
SHADER_LEGACY.boundShader = shader;
SHADER_LEGACY.dirty = (
SHADER_LEGACY_DIRTY_MODEL |
SHADER_LEGACY_DIRTY_PROJ |
SHADER_LEGACY_DIRTY_VIEW
);
#else
assertNotNull(shader, "Shader cannot be null");
glUseProgram(shader->shaderProgramId);
errorChain(errorGLCheck());
#endif
errorOk();
}
errorret_t shaderDisposeGL(shadergl_t *shader) {
assertNotNull(shader, "Shader cannot be null");
#ifdef DUSK_OPENGL_LEGACY
SHADER_LEGACY.boundShader = NULL;
#else
if(shader->shaderProgramId != 0) {
glDeleteProgram(shader->shaderProgramId);
}
if(shader->vertexShaderId != 0) {
glDeleteShader(shader->vertexShaderId);
}
if(shader->fragmentShaderId != 0) {
glDeleteShader(shader->fragmentShaderId);
}
assertNoGLError("Failed disposing shader");
#endif
memoryZero(shader, sizeof(shadergl_t));
errorOk();
}
#ifdef DUSK_OPENGL_LEGACY
errorret_t shaderLegacyMatrixUpdate() {
assertNotNull(SHADER_LEGACY.boundShader, "No shader is currently bound.");
if((SHADER_LEGACY.dirty & SHADER_LEGACY_DIRTY_PROJ) != 0) {
glMatrixMode(GL_PROJECTION);
errorChain(errorGLCheck());
glLoadIdentity();
errorChain(errorGLCheck());
glMultMatrixf((const GLfloat *)SHADER_LEGACY.boundShader->proj);
errorChain(errorGLCheck());
}
if(
(SHADER_LEGACY.dirty &
(SHADER_LEGACY_DIRTY_VIEW | SHADER_LEGACY_DIRTY_MODEL)) != 0
) {
glMatrixMode(GL_MODELVIEW);
errorChain(errorGLCheck());
mat4 viewModel;
glm_mat4_mul(
SHADER_LEGACY.boundShader->view,
SHADER_LEGACY.boundShader->model,
viewModel
);
glLoadMatrixf((const GLfloat *)viewModel);
errorChain(errorGLCheck());
}
SHADER_LEGACY.dirty = 0;
errorOk();
}
#endif
-148
View File
@@ -1,148 +0,0 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "error/errorgl.h"
#include "display/texture/texture.h"
typedef struct shadergl_s shadergl_t;
typedef union shadermaterial_u shadermaterial_t;
typedef errorret_t (*shadersettexturefn_t)(
shadergl_t *,
const char_t *,
texture_t *
);
typedef struct {
errorret_t (*setMaterial)(shadergl_t *, const shadermaterial_t *);
#ifdef DUSK_OPENGL_LEGACY
#else
errorret_t (*setTexture)(shadergl_t *, const char_t *, texture_t *);
const char_t *vert;
const char_t *frag;
#endif
} shaderdefinitiongl_t;
typedef struct shadergl_s {
const shaderdefinitiongl_t *definition;
#ifdef DUSK_OPENGL_LEGACY
mat4 view;
mat4 proj;
mat4 model;
#else
GLuint shaderProgramId;
GLuint vertexShaderId;
GLuint fragmentShaderId;
#endif
} shadergl_t;
#if DUSK_OPENGL_LEGACY
typedef struct {
shadergl_t *boundShader;
uint_fast8_t dirty;
} shaderlegacygl_t;
extern shaderlegacygl_t SHADER_LEGACY;
#define SHADER_LEGACY_DIRTY_PROJ (1 << 0)
#define SHADER_LEGACY_DIRTY_VIEW (1 << 1)
#define SHADER_LEGACY_DIRTY_MODEL (1 << 2)
#endif
/**
* Initializes a shader.
*
* @param shader The shader to initialize.
* @param def The definition of the shader to initialize with.
* @return An errorret_t indicating success or failure.
*/
errorret_t shaderInitGL(shadergl_t *shader, const shaderdefinitiongl_t *def);
/**
* Binds a shader for use in rendering.
*
* @param shader The shader to bind.
* @return An errorret_t indicating success or failure.
*/
errorret_t shaderBindGL(shadergl_t *shader);
/**
* Retrieves the location of a shader uniform parameter.
*
* @param shader The shader to query.
* @param name The name of the uniform parameter.
* @param location Output parameter to receive the location of the uniform.
* @return An errorret_t indicating success or failure.
*/
errorret_t shaderParamGetLocationGL(
shadergl_t *shader,
const char_t *name,
GLint *location
);
/**
* Sets a mat4 uniform parameter in the shader.
*
* @param shader The shader to update.
* @param name The name of the uniform parameter.
* @param mat The 4x4 matrix data to set.
* @return An errorret_t indicating success or failure.
*/
errorret_t shaderSetMatrixGL(
shadergl_t *shader,
const char_t *name,
mat4 matrix
);
/**
* Sets a color uniform parameter in the shader.
*
* @param shader The shader to update.
* @param name The name of the uniform parameter.
* @param color The color data to set.
* @return An errorret_t indicating success or failure.
*/
errorret_t shaderSetTextureGL(
shadergl_t *shader,
const char_t *name,
texture_t *texture
);
/**
* Sets a color uniform parameter in the shader.
*
* @param shader The shader to update.
* @param name The name of the uniform parameter.
* @param color The color data to set.
* @return An errorret_t indicating success or failure.
*/
errorret_t shaderSetColorGL(
shadergl_t *shader,
const char_t *name,
color_t color
);
/**
* Disposes of a shader, freeing any associated resources.
*
* @param shader The shader to dispose.
*/
errorret_t shaderDisposeGL(shadergl_t *shader);
#ifdef DUSK_OPENGL_LEGACY
/**
* During mesh rendering, this is requesting the legacy system to push all
* shaders necessary to render the currently bound shader's matrices.
*
* @return Any error state.
*/
errorret_t shaderLegacyMatrixUpdate();
#endif
@@ -1,19 +0,0 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "shadergl.h"
typedef shadergl_t shaderplatform_t;
typedef shaderdefinitiongl_t shaderdefinitionplatform_t;
#define shaderInitPlatform shaderInitGL
#define shaderBindPlatform shaderBindGL
#define shaderSetMatrixPlatform shaderSetMatrixGL
#define shaderSetTexturePlatform shaderSetTextureGL
#define shaderSetColorPlatform shaderSetColorGL
#define shaderDisposePlatform shaderDisposeGL
-213
View File
@@ -1,213 +0,0 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "display/shader/shaderunlit.h"
#include "assert/assertgl.h"
#ifdef DUSK_OPENGL_LEGACY
shaderdefinition_t SHADER_UNLIT_DEFINITION = {
.setMaterial = shaderUnlitSetMaterial,
};
#else
errorret_t shaderUnlitSetTextureGL(
shadergl_t *shader,
const char_t *name,
texture_t *texture
) {
assertNotNull(shader, "Shader cannot be null");
assertStrLenMin(name, 1, "Uniform name cannot be empty");
assertStringEqual(
name,
SHADER_UNLIT_TEXTURE,
"Only one texture supported in unlit shader."
);
GLint locTexture, locType, locColorCount, locColors;
errorChain(shaderParamGetLocationGL(shader, "u_TextureType", &locType));
// NULL textures
if(texture == NULL) {
glUniform1i(locType, 0);
errorChain(errorGLCheck());
errorOk();
}
// Set texture.
glActiveTexture(GL_TEXTURE0);
errorChain(errorGLCheck());
glBindTexture(GL_TEXTURE_2D, texture->id);
errorChain(errorGLCheck());
errorChain(shaderParamGetLocationGL(shader, name, &locTexture));
glUniform1i(locTexture, 0);
errorChain(errorGLCheck());
// Set texture type
if(texture->format == TEXTURE_FORMAT_PALETTE) {
glUniform1i(locType, 2);
errorChain(errorGLCheck());
shaderParamGetLocationGL(shader, "u_ColorCount", &locColorCount);
glUniform1i(locColorCount, texture->palette->count);
errorChain(errorGLCheck());
shaderParamGetLocationGL(shader, "u_Colors", &locColors);
GLuint paletteData[texture->palette->count];
for(size_t i = 0; i < texture->palette->count; i++) {
color_t color = texture->palette->colors[i];
paletteData[i] = (
((uint32_t)color.r << 24) |
((uint32_t)color.g << 16) |
((uint32_t)color.b << 8) |
((uint32_t)color.a << 0)
);
}
glUniform1uiv(locColors, texture->palette->count, paletteData);
errorChain(errorGLCheck());
} else {
glUniform1i(locType, 1);
errorChain(errorGLCheck());
}
errorOk();
}
shaderdefinition_t SHADER_UNLIT_DEFINITION = {
.setMaterial = shaderUnlitSetMaterial,
.setTexture = shaderUnlitSetTextureGL,
.vert =
#ifdef DUSK_OPENGL_ES
"#version 300 es\n"
"precision mediump float;\n"
// Attributes
"layout(location = 0) in vec3 a_Pos;\n"
"layout(location = 1) in vec2 a_TexCoord;\n"
#if MESH_ENABLE_COLOR
"layout(location = 2) in vec4 a_Color;\n"
#endif
// Uniforms
"uniform mat4 u_Proj;\n"
"uniform mat4 u_View;\n"
"uniform mat4 u_Model;\n"
// Vertex shader outputs
"out vec4 v_Color;\n"
"out vec2 v_TexCoord;\n"
"void main() {\n"
" gl_Position = u_Proj * u_View * u_Model * vec4(a_Pos, 1.0);\n"
#if MESH_ENABLE_COLOR
" v_Color = a_Color;\n"
#else
" v_Color = vec4(1.0);\n"
#endif
" v_TexCoord = a_TexCoord;\n"
"}\n",
#else
"#version 330 core\n"
// Attributes
"layout(location = 0) in vec3 a_Pos;\n"
"layout(location = 1) in vec2 a_TexCoord;\n"
#if MESH_ENABLE_COLOR
"layout(location = 2) in vec4 a_Color;\n"
#endif
// Uniforms
"uniform mat4 u_Proj;\n"
"uniform mat4 u_View;\n"
"uniform mat4 u_Model;\n"
// Vertex shader outputs
"out vec4 v_Color;\n"
"out vec2 v_TexCoord;\n"
"void main() {\n"
" gl_Position = u_Proj * u_View * u_Model * vec4(a_Pos, 1.0);\n"
#if MESH_ENABLE_COLOR
" v_Color = a_Color;\n"
#else
" v_Color = vec4(1.0);\n"
#endif
" v_TexCoord = a_TexCoord;\n"
"}\n",
#endif
.frag =
#ifdef DUSK_OPENGL_ES
"#version 300 es\n"
"precision mediump float;\n"
// Uniforms
"uniform sampler2D u_Texture;\n"
"uniform int u_TextureType;\n"
"uniform uint u_Colors[256];\n"// For paletted textures.
"uniform int u_ColorCount;\n"
"uniform vec4 u_Color;\n"
// Fragment shader inputs
"in vec4 v_Color;\n"
"in vec2 v_TexCoord;\n"
// Fragment shader output
"out vec4 FragColor;\n"
"void main() {\n"
" if(u_TextureType == 0) {\n"// No texture
" FragColor = v_Color * u_Color;\n"
" return;\n"
" }\n"
" if(u_TextureType == 1) {\n"// Regular texture
" FragColor = texture(u_Texture, v_TexCoord) * v_Color * u_Color;\n"
" return;\n"
" }\n"
" if(u_TextureType == 2) {\n"// Paletted texture
" vec4 texColor = texture(u_Texture, v_TexCoord);\n"
" uint index = uint(floor(texColor.r * 255.0));\n"
" uint palColor = u_Colors[index];\n"
" float r = float((palColor >> 24) & 0xFFu) / 255.0;\n"
" float g = float((palColor >> 16) & 0xFFu) / 255.0;\n"
" float b = float((palColor >> 8) & 0xFFu) / 255.0;\n"
" float a = float((palColor >> 0) & 0xFFu) / 255.0;\n"
" FragColor = vec4(r, g, b, a) * u_Color;\n"
" return;\n"
" }\n"
" FragColor = v_Color * u_Color;\n"// Unknown texture type?
"}\n",
#else
"#version 330 core\n"
// Uniforms
"uniform sampler2D u_Texture;\n"
"uniform int u_TextureType;\n"
"uniform uint u_Colors[256];\n"// For paletted textures.
"uniform int u_ColorCount;\n"
"uniform vec4 u_Color;\n"
// Fragment shader inputs
"in vec4 v_Color;\n"
"in vec2 v_TexCoord;\n"
// Fragment shader output
"out vec4 FragColor;\n"
"void main() {\n"
" if(u_TextureType == 0) {\n"// No texture
" FragColor = v_Color * u_Color;\n"
" return;\n"
" }\n"
" if(u_TextureType == 1) {\n"// Regular texture
" FragColor = texture(u_Texture, v_TexCoord) * v_Color * u_Color;\n"
" return;\n"
" }\n"
" if(u_TextureType == 2) {\n"// Paletted texture
" vec4 texColor = texture(u_Texture, v_TexCoord);\n"
" uint index = uint(floor(texColor.r * 255.0));\n"
" uint palColor = u_Colors[index];\n"
" float r = float((palColor >> 24) & 0xFFu) / 255.0;\n"
" float g = float((palColor >> 16) & 0xFFu) / 255.0;\n"
" float b = float((palColor >> 8) & 0xFFu) / 255.0;\n"
" float a = float((palColor >> 0) & 0xFFu) / 255.0;\n"
" FragColor = vec4(r, g, b, a) * u_Color;\n"
" return;\n"
" }\n"
" FragColor = v_Color * u_Color;\n"// Unknown texture type?
"}\n",
#endif
};
#endif
-10
View File
@@ -1,10 +0,0 @@
# Copyright (c) 2026 Dominic Masters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
# Sources
target_sources(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC
texturegl.c
)
-95
View File
@@ -1,95 +0,0 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "display/texture/texture.h"
#include "assert/assert.h"
#include "error/errorgl.h"
#include "util/memory.h"
errorret_t textureInitGL(
texturegl_t *texture,
const int32_t width,
const int32_t height,
const textureformatgl_t format,
const texturedata_t data
) {
glGenTextures(1, &texture->id);
errorChain(errorGLCheck());
glBindTexture(GL_TEXTURE_2D, texture->id);
errorChain(errorGLCheck());
switch(format) {
case TEXTURE_FORMAT_RGBA:
glTexImage2D(
GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, (void*)data.rgbaColors
);
errorChain(errorGLCheck());
break;
case TEXTURE_FORMAT_PALETTE:
texture->palette = data.paletted.palette;
assertTrue(
texture->palette == &PALETTES[0],
"Only the first palette is supported in legacy opengl."
);
#ifdef DUSK_OPENGL_LEGACY
glColorTableEXT(
GL_TEXTURE_2D, GL_RGBA, texture->palette->count, GL_RGBA,
GL_UNSIGNED_BYTE, (const void*)texture->palette->colors
);
errorChain(errorGLCheck());
glTexImage2D(
GL_TEXTURE_2D,
0, GL_COLOR_INDEX8_EXT,
width, height,
0, GL_COLOR_INDEX8_EXT,
GL_UNSIGNED_BYTE, (void*)data.paletted.indices
);
errorChain(errorGLCheck());
#else
// For modern systems we send to only the R channel and the shader does
// the rest.
glTexImage2D(
GL_TEXTURE_2D, 0, GL_RED, width, height, 0,
GL_RED, GL_UNSIGNED_BYTE, (void*)data.paletted.indices
);
errorChain(errorGLCheck());
#endif
break;
default:
assertUnreachable("Unknown texture format");
break;
}
errorChain(errorGLCheck());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
errorChain(errorGLCheck());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
errorChain(errorGLCheck());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
errorChain(errorGLCheck());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
errorChain(errorGLCheck());
glBindTexture(GL_TEXTURE_2D, 0);
errorChain(errorGLCheck());
errorOk();
}
errorret_t textureDisposeGL(texturegl_t *texture) {
assertNotNull(texture, "Texture cannot be NULL");
assertTrue(texture->id != 0, "Texture ID must be valid");
glDeleteTextures(1, &texture->id);
errorChain(errorGLCheck());
errorOk();
}
-54
View File
@@ -1,54 +0,0 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "dusk.h"
typedef union texturedata_u texturedata_t;
typedef enum {
TEXTURE_FORMAT_RGBA = GL_RGBA,
TEXTURE_FORMAT_PALETTE = GL_COLOR_INDEX8_EXT,
// TEXTURE_FORMAT_DXT5 = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
} textureformatgl_t;
typedef struct {
GLuint id;
textureformatgl_t format;
int32_t width;
int32_t height;
union {
palette_t *palette;
};
} texturegl_t;
/**
* Initializes a texture.
*
* @param texture The texture to initialize.
* @param width The width of the texture.
* @param height The height of the texture.
* @param format The format of the texture (e.g., GL_RGBA, GL_ALPHA).
* @param data The data for the texture, the format changes per format.
* @return An error if the texture failed to initialize, otherwise success.
*/
errorret_t textureInitGL(
texturegl_t *texture,
const int32_t width,
const int32_t height,
const textureformatgl_t format,
const texturedata_t data
);
/**
* Disposes a texture.
*
* @param texture The texture to dispose.
* @return An error if the texture failed to dispose, otherwise success.
*/
errorret_t textureDisposeGL(texturegl_t *texture);
@@ -1,15 +0,0 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "display/texture/texturegl.h"
typedef textureformatgl_t textureformatplatform_t;
typedef texturegl_t textureplatform_t;
#define textureInitPlatform textureInitGL
#define textureDisposePlatform textureDisposeGL
+4 -4
View File
@@ -1,17 +1,17 @@
/**
* Copyright (c) 2026 Dominic Masters
*
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "errorgl.h"
#include "duskgl.h"
#include "error/errorgl.h"
errorret_t errorGLCheck(void) {
GLenum err = glGetError();
if(err != GL_NO_ERROR) {
errorThrow("GL Error: %d", err);
}
errorOk();
}
}
@@ -1,10 +1,9 @@
# Copyright (c) 2026 Dominic Masters
#
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
# Sources
target_sources(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC
meshgl.c
)
rendergl.c
)
+153
View File
@@ -0,0 +1,153 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "render/rendergl.h"
#include "error/errorgl.h"
#include "render/rop.h"
static const char *VERT_SRC =
"#version 330 core\n"
"layout(location=0) in vec2 aPos;\n"
"layout(location=1) in vec4 aColor;\n"
"uniform vec2 uRes;\n"
"out vec4 vColor;\n"
"void main() {\n"
" vec2 clip = (aPos / uRes) * 2.0 - 1.0;\n"
" clip.y = -clip.y;\n"
" gl_Position = vec4(clip, 0.0, 1.0);\n"
" vColor = aColor;\n"
"}\n";
static const char *FRAG_SRC =
"#version 330 core\n"
"in vec4 vColor;\n"
"out vec4 fragColor;\n"
"void main() {\n"
" fragColor = vColor;\n"
"}\n";
typedef struct {
GLuint prog;
GLuint vao;
GLuint vbo;
GLint uRes;
} rendergl_t;
static rendergl_t renderGL;
static GLuint compileShader(GLenum type, const char *src) {
GLuint s = glCreateShader(type);
glShaderSource(s, 1, &src, NULL);
glCompileShader(s);
return s;
}
errorret_t renderGLInit(void) {
GLuint vert = compileShader(GL_VERTEX_SHADER, VERT_SRC);
GLuint frag = compileShader(GL_FRAGMENT_SHADER, FRAG_SRC);
renderGL.prog = glCreateProgram();
glAttachShader(renderGL.prog, vert);
glAttachShader(renderGL.prog, frag);
glLinkProgram(renderGL.prog);
glDeleteShader(vert);
glDeleteShader(frag);
errorChain(errorGLCheck());
renderGL.uRes = glGetUniformLocation(renderGL.prog, "uRes");
glGenVertexArrays(1, &renderGL.vao);
glGenBuffers(1, &renderGL.vbo);
glBindVertexArray(renderGL.vao);
glBindBuffer(GL_ARRAY_BUFFER, renderGL.vbo);
/* 6 verts * (2 pos + 4 color) floats — enough for one sprite */
glBufferData(GL_ARRAY_BUFFER, 6 * 6 * sizeof(GLfloat), NULL, GL_DYNAMIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (void*)(2*sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
errorChain(errorGLCheck());
errorOk();
}
static void drawSprite(const ropsprite_t *s, float rW, float rH) {
float r = s->tint.r / 255.0f;
float g = s->tint.g / 255.0f;
float b = s->tint.b / 255.0f;
float a = s->tint.a / 255.0f;
float x0 = (float)s->x;
float y0 = (float)s->y;
float x1 = x0 + (float)s->w;
float y1 = y0 + (float)s->h;
GLfloat verts[6][6] = {
{ x0, y1, r,g,b,a },
{ x0, y0, r,g,b,a },
{ x1, y0, r,g,b,a },
{ x0, y1, r,g,b,a },
{ x1, y0, r,g,b,a },
{ x1, y1, r,g,b,a },
};
glBindVertexArray(renderGL.vao);
glBindBuffer(GL_ARRAY_BUFFER, renderGL.vbo);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(verts), verts);
glDrawArrays(GL_TRIANGLES, 0, 6);
(void)rW; (void)rH;
}
errorret_t renderGLFlush(ropbuffer_t *buf, int winW, int winH) {
glViewport(0, 0, winW, winH);
errorChain(errorGLCheck());
glUseProgram(renderGL.prog);
glUniform2f(renderGL.uRes, (GLfloat)winW, (GLfloat)winH);
errorChain(errorGLCheck());
for(uint32_t i = 0; i < buf->count; i++) {
const ropheader_t *hdr = (const ropheader_t *)(buf->data + i * ROP_SIZE);
switch(hdr->op) {
case ROP_CLEAR: {
const ropclear_t *c = (const ropclear_t *)hdr;
glClearColor(
c->color.r / 255.0f,
c->color.g / 255.0f,
c->color.b / 255.0f,
c->color.a / 255.0f
);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
errorChain(errorGLCheck());
break;
}
case ROP_DRAW_SPRITE: {
const ropsprite_t *s = (const ropsprite_t *)hdr;
drawSprite(s, (float)winW, (float)winH);
errorChain(errorGLCheck());
break;
}
default:
break;
}
}
glUseProgram(0);
glBindVertexArray(0);
errorOk();
}
void renderGLDispose(void) {
if(renderGL.vbo) { glDeleteBuffers(1, &renderGL.vbo); renderGL.vbo = 0; }
if(renderGL.vao) { glDeleteVertexArrays(1, &renderGL.vao); renderGL.vao = 0; }
if(renderGL.prog) { glDeleteProgram(renderGL.prog); renderGL.prog = 0; }
}
+15
View File
@@ -0,0 +1,15 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "duskgl.h"
#include "error/error.h"
#include "render/ropbuffer.h"
errorret_t renderGLInit(void);
errorret_t renderGLFlush(ropbuffer_t *buf, int winW, int winH);
void renderGLDispose(void);