From 5ac21db9976661298514fb5583b348efdde8bfcd Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Sun, 22 Mar 2026 10:44:28 -0500 Subject: [PATCH] Shaders adapted for Legacy GL --- cmake/targets/linux.cmake | 1 + src/dusk/display/shader/shader.c | 2 +- src/dusk/display/shader/shader.h | 2 +- src/duskgl/display/displaygl.c | 7 -- src/duskgl/display/mesh/meshgl.c | 10 ++ src/duskgl/display/shader/shadergl.c | 141 +++++++++++++++++----- src/duskgl/display/shader/shadergl.h | 33 ++++- src/duskgl/display/shader/shaderunlitgl.c | 38 +++--- src/dusksdl2/display/displaysdl2.c | 11 +- 9 files changed, 184 insertions(+), 61 deletions(-) diff --git a/cmake/targets/linux.cmake b/cmake/targets/linux.cmake index f83d136..bec0a02 100644 --- a/cmake/targets/linux.cmake +++ b/cmake/targets/linux.cmake @@ -29,6 +29,7 @@ target_compile_definitions(${DUSK_LIBRARY_TARGET_NAME} PUBLIC DUSK_SDL2 DUSK_OPENGL DUSK_LINUX + DUSK_OPENGL_LEGACY DUSK_DISPLAY_SIZE_DYNAMIC DUSK_DISPLAY_WIDTH_DEFAULT=640 DUSK_DISPLAY_HEIGHT_DEFAULT=480 diff --git a/src/dusk/display/shader/shader.c b/src/dusk/display/shader/shader.c index 9f7e914..cc6550a 100644 --- a/src/dusk/display/shader/shader.c +++ b/src/dusk/display/shader/shader.c @@ -23,7 +23,7 @@ errorret_t shaderBind(shader_t *shader) { errorret_t shaderSetMatrix( shader_t *shader, const char_t *name, - const mat4 matrix + mat4 matrix ) { assertNotNull(shader, "Shader cannot be null"); assertStrLenMin(name, 1, "Uniform name cannot be empty"); diff --git a/src/dusk/display/shader/shader.h b/src/dusk/display/shader/shader.h index b543ac4..2af399d 100644 --- a/src/dusk/display/shader/shader.h +++ b/src/dusk/display/shader/shader.h @@ -54,7 +54,7 @@ errorret_t shaderBind(shader_t *shader); errorret_t shaderSetMatrix( shader_t *shader, const char_t *name, - const mat4 matrix + mat4 matrix ); /** diff --git a/src/duskgl/display/displaygl.c b/src/duskgl/display/displaygl.c index 0affce3..e8b2420 100644 --- a/src/duskgl/display/displaygl.c +++ b/src/duskgl/display/displaygl.c @@ -8,8 +8,6 @@ #include "displaygl.h" errorret_t displayOpenGLInit(void) { - - glDisable(GL_CULL_FACE); // glDisable(GL_LIGHTING);// PSP defaults this on? // glShadeModel(GL_SMOOTH); // Fixes color on PSP? @@ -26,10 +24,5 @@ errorret_t displayOpenGLInit(void) { glPixelStorei(GL_UNPACK_ALIGNMENT, 1); errorChain(errorGLCheck()); - // glEnableClientState(GL_COLOR_ARRAY);// To confirm: every frame on PSP? - // glEnableClientState(GL_TEXTURE_COORD_ARRAY); - // glEnableClientState(GL_VERTEX_ARRAY); - // errorChain(errorGLCheck()); - errorOk(); } \ No newline at end of file diff --git a/src/duskgl/display/mesh/meshgl.c b/src/duskgl/display/mesh/meshgl.c index 88dd62d..c931868 100644 --- a/src/duskgl/display/mesh/meshgl.c +++ b/src/duskgl/display/mesh/meshgl.c @@ -8,6 +8,7 @@ #include "display/mesh/mesh.h" #include "assert/assertgl.h" #include "error/errorgl.h" +#include "display/shader/shadergl.h" errorret_t meshInitGL( meshgl_t *mesh, @@ -25,6 +26,10 @@ errorret_t meshInitGL( #ifdef DUSK_OPENGL_LEGACY // Nothing needed. + glEnableClientState(GL_COLOR_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glEnableClientState(GL_VERTEX_ARRAY); + errorChain(errorGLCheck()); #else // Generate Vertex Buffer Object glGenBuffers(1, &mesh->vboId); @@ -143,6 +148,11 @@ errorret_t meshDrawGL( (const GLvoid*)&mesh->vertices[offset].pos ); + // Shader may have model matrix here + #ifdef DUSK_OPENGL_LEGACY + errorChain(shaderLegacyMatrixUpdate()); + #endif + glDrawArrays(mesh->primitiveType, offset, count); errorChain(errorGLCheck()); #else diff --git a/src/duskgl/display/shader/shadergl.c b/src/duskgl/display/shader/shadergl.c index 2c82aa3..b753a43 100644 --- a/src/duskgl/display/shader/shadergl.c +++ b/src/duskgl/display/shader/shadergl.c @@ -7,7 +7,13 @@ #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"); @@ -15,7 +21,11 @@ errorret_t shaderInitGL(shadergl_t *shader, const shaderdefinitiongl_t *def) { memoryZero(shader, sizeof(shadergl_t)); #ifdef DUSK_OPENGL_LEGACY - // No initialization needed for legacy shader + glm_mat4_identity(shader->view); + glm_mat4_identity(shader->proj); + glm_mat4_identity(shader->model); + + SHADER_LEGACY.boundShader = NULL; errorOk(); #else // Create vertex shader @@ -139,12 +149,16 @@ errorret_t shaderParamGetLocationGL( assertStrLenMin(name, 1, "Uniform name cannot be empty"); assertNotNull(location, "Location cannot be null"); - shadergl_t *shaderGL = (shadergl_t *)shader; - *location = glGetUniformLocation(shaderGL->shaderProgramId, name); - errorret_t err = errorGLCheck(); - if(err.code != ERROR_OK) { - errorChain(err); - } + #ifdef DUSK_OPENGL_LEGACY + assertUnreachable("Cannot get uniform locations on legacy opengl."); + #else + shadergl_t *shaderGL = (shadergl_t *)shader; + *location = glGetUniformLocation(shaderGL->shaderProgramId, name); + errorret_t err = errorGLCheck(); + if(err.code != ERROR_OK) { + errorChain(err); + } + #endif errorOk(); } @@ -152,27 +166,58 @@ errorret_t shaderParamGetLocationGL( errorret_t shaderSetMatrixGL( shadergl_t *shader, const char_t *name, - const mat4 mat + mat4 mat ) { assertNotNull(shader, "Shader cannot be null"); assertNotNull(mat, "Matrix data cannot be null"); assertStrLenMin(name, 1, "Uniform name cannot be empty"); - GLint location; - errorChain(shaderParamGetLocationGL(shader, name, &location)); + #ifdef DUSK_OPENGL_LEGACY + assertTrue( + SHADER_LEGACY.boundShader == shader, + "Shader must be bound to set legacy matrices." + ); + if(stringCompare(name, SHADER_UNLIT_PROJECTION) == 0) { + SHADER_LEGACY.dirty |= SHADER_LEGACY_DIRTY_PROJ; + glm_mat4_copy(mat, shader->proj); - glUniformMatrix4fv(location, 1, GL_FALSE, (const GLfloat *)mat); - errorChain(errorGLCheck()); + } else if(stringCompare(name, SHADER_UNLIT_VIEW) == 0) { + SHADER_LEGACY.dirty |= SHADER_LEGACY_DIRTY_VIEW; + glm_mat4_copy(mat, shader->view); + + } else if(stringCompare(name, SHADER_UNLIT_MODEL) == 0) { + SHADER_LEGACY.dirty |= SHADER_LEGACY_DIRTY_MODEL; + glm_mat4_copy(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 shaderBindGL(shadergl_t *shader) { - assertNotNull(shader, "Shader cannot be null"); - - glUseProgram(shader->shaderProgramId); - errorChain(errorGLCheck()); + #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(); } @@ -180,22 +225,58 @@ errorret_t shaderBindGL(shadergl_t *shader) { errorret_t shaderDisposeGL(shadergl_t *shader) { assertNotNull(shader, "Shader cannot be null"); - if(shader->shaderProgramId != 0) { - glDeleteProgram(shader->shaderProgramId); - errorChain(errorGLCheck()); - } - - if(shader->vertexShaderId != 0) { - glDeleteShader(shader->vertexShaderId); - errorChain(errorGLCheck()); - } + #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); - errorChain(errorGLCheck()); - } + if(shader->fragmentShaderId != 0) { + glDeleteShader(shader->fragmentShaderId); + } + + assertNoGLError("Failed disposing shader"); + #endif - assertNoGLError("Failed disposing shader"); 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) != 0) { + glMatrixMode(GL_MODELVIEW); + errorChain(errorGLCheck()); + glLoadIdentity(); + errorChain(errorGLCheck()); + glMultMatrixf((const GLfloat *)SHADER_LEGACY.boundShader->view); + errorChain(errorGLCheck()); + } + + if((SHADER_LEGACY.dirty & SHADER_LEGACY_DIRTY_MODEL) != 0) { + glMatrixMode(GL_MODELVIEW); + errorChain(errorGLCheck()); + glMultMatrixf((const GLfloat *)SHADER_LEGACY.boundShader->model); + errorChain(errorGLCheck()); + } + + SHADER_LEGACY.dirty = 0; + errorOk(); + } +#endif \ No newline at end of file diff --git a/src/duskgl/display/shader/shadergl.h b/src/duskgl/display/shader/shadergl.h index 56d50cf..2ba660e 100644 --- a/src/duskgl/display/shader/shadergl.h +++ b/src/duskgl/display/shader/shadergl.h @@ -16,6 +16,12 @@ typedef struct { GLuint vertexShaderId; GLuint fragmentShaderId; #endif + + #if DUSK_OPENGL_LEGACY + mat4 view; + mat4 proj; + mat4 model; + #endif } shadergl_t; typedef struct { @@ -27,6 +33,19 @@ typedef struct { #endif } shaderdefinitiongl_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. * @@ -69,7 +88,7 @@ errorret_t shaderParamGetLocationGL( errorret_t shaderSetMatrixGL( shadergl_t *shader, const char_t *name, - const mat4 matrix + mat4 matrix ); /** @@ -77,4 +96,14 @@ errorret_t shaderSetMatrixGL( * * @param shader The shader to dispose. */ -errorret_t shaderDisposeGL(shadergl_t *shader); \ No newline at end of file +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 \ No newline at end of file diff --git a/src/duskgl/display/shader/shaderunlitgl.c b/src/duskgl/display/shader/shaderunlitgl.c index 9a653d1..179dc4e 100644 --- a/src/duskgl/display/shader/shaderunlitgl.c +++ b/src/duskgl/display/shader/shaderunlitgl.c @@ -7,21 +7,25 @@ #include "display/shader/shaderunlit.h" -shaderdefinition_t SHADER_UNLIT_DEFINITION = { - .vert = - "#version 330 core\n" - "layout(location = 0) in vec3 aPos;\n" - "uniform mat4 u_Proj;\n" - "uniform mat4 u_View;\n" - "uniform mat4 u_Model;\n" - "void main() {\n" - " gl_Position = u_Proj * u_View * u_Model * vec4(aPos, 1.0);\n" - "}\n", +#ifdef DUSK_OPENGL_LEGACY + shaderdefinition_t SHADER_UNLIT_DEFINITION = { 0 }; +#else + shaderdefinition_t SHADER_UNLIT_DEFINITION = { + .vert = + "#version 330 core\n" + "layout(location = 0) in vec3 aPos;\n" + "uniform mat4 u_Proj;\n" + "uniform mat4 u_View;\n" + "uniform mat4 u_Model;\n" + "void main() {\n" + " gl_Position = u_Proj * u_View * u_Model * vec4(aPos, 1.0);\n" + "}\n", - .frag = - "#version 330 core\n" - "out vec4 FragColor;\n" - "void main() {\n" - " FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" - "}\n" -}; \ No newline at end of file + .frag = + "#version 330 core\n" + "out vec4 FragColor;\n" + "void main() {\n" + " FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" + "}\n" + }; +#endif \ No newline at end of file diff --git a/src/dusksdl2/display/displaysdl2.c b/src/dusksdl2/display/displaysdl2.c index f8582d8..c34d8f8 100644 --- a/src/dusksdl2/display/displaysdl2.c +++ b/src/dusksdl2/display/displaysdl2.c @@ -23,9 +23,14 @@ errorret_t displaySDL2Init(void) { SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); // SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); // SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); - - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); + + #ifdef DUSK_OPENGL_LEGACY + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); + #else + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); + #endif // Create window with OpenGL flag. DISPLAY.window = SDL_CreateWindow(