prog
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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
|
||||
@@ -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
|
||||
)
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
)
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
)
|
||||
@@ -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; }
|
||||
}
|
||||
@@ -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);
|
||||
Reference in New Issue
Block a user