From 7737d096ee4ad30dd5cdfeb8c1f0c7cbfa6ab088 Mon Sep 17 00:00:00 2001 From: Classic0306 <190026317+Classic0306@users.noreply.github.com> Date: Wed, 20 May 2026 00:08:58 +0200 Subject: [PATCH 01/11] vertex and fragment shader and uniforms --- src/gl/gl_renderer.c | 111 +++++++++++++++++++++++++++++++++++++++++++ src/gl/gl_renderer.h | 2 + src/renderer.h | 13 +++++ src/vm_builtins.c | 64 +++++++++++++++++++++++++ 4 files changed, 190 insertions(+) diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index 1198787a..fdb41d17 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -103,6 +103,28 @@ static GLuint linkProgram(GLuint vertShader, GLuint fragShader) { return program; } +static GLuint linkProgramCompat(GLuint vertShader, GLuint fragShader) { + GLuint program = glCreateProgram(); + glAttachShader(program, vertShader); + glAttachShader(program, fragShader); + + glBindAttribLocation(program, 0, "in_Position"); + glBindAttribLocation(program, 2, "in_Colour"); + glBindAttribLocation(program, 1, "in_TexCoord"); + + glLinkProgram(program); + + GLint success; + glGetProgramiv(program, GL_LINK_STATUS, &success); + if (!success) { + char infoLog[512]; + glGetProgramInfoLog(program, sizeof(infoLog), nullptr, infoLog); + fprintf(stderr, "GL: Shader linking failed: %s\n", infoLog); + abort(); + } + return program; +} + // ===[ Batch Flush ]=== static void flushBatch(GLRenderer* gl) { @@ -164,6 +186,25 @@ static void glInit(Renderer* renderer, DataWin* dataWin) { gl->shaderProgram = linkProgram(vertShader, fragShader); glDeleteShader(vertShader); glDeleteShader(fragShader); + //yeah find the way to get the shaders here!!! + fprintf(stderr, "GL: %u Shaders Found\n", dataWin->shdr.count); + for (uint32_t i = 0; dataWin->shdr.count > i; i++) + { + Shader* shdr = &dataWin->shdr.shaders[i]; + //fprintf(stderr, "GL: Shader %u %s Type %u\n", i, shdr->name, shdr->type); + //GLuint* GMLShaders; + fprintf(stderr, "GL: Compiling %s Vertex Shader\n", shdr->name); + GLuint vertShaderT = compileShader(GL_VERTEX_SHADER, shdr->glsl_Vertex); + fprintf(stderr, "GL: Compiling %s Fragment Shader\n", shdr->name); + GLuint fragShaderT = compileShader(GL_FRAGMENT_SHADER, shdr->glsl_Fragment); + gl->GMLShaderCount++; + gl->GMLShaders = safeRealloc(gl->GMLShaders, gl->GMLShaderCount * sizeof(GLuint)); + fprintf(stderr, "GL: Linking %s\n", shdr->name); + gl->GMLShaders[i] = linkProgramCompat(vertShaderT, fragShaderT); + + + + } gl->uProjection = glGetUniformLocation(gl->shaderProgram, "uProjection"); gl->uTexture = glGetUniformLocation(gl->shaderProgram, "uTexture"); @@ -335,6 +376,7 @@ static void glBeginView(Renderer* renderer, int32_t viewX, int32_t viewY, int32_ glUseProgram(gl->shaderProgram); glUniformMatrix4fv(gl->uProjection, 1, GL_FALSE, projection.m); + renderer->GML_Matrices[MATRIX_WORLD_VIEW_PROJECTION] = projection; glUniform1i(gl->uTexture, 0); glActiveTexture(GL_TEXTURE0); @@ -386,6 +428,7 @@ static void glBeginGUI(Renderer* renderer, int32_t guiW, int32_t guiH, int32_t p glUseProgram(gl->shaderProgram); glUniformMatrix4fv(gl->uProjection, 1, GL_FALSE, projection.m); + renderer->GML_Matrices[MATRIX_WORLD_VIEW_PROJECTION] = projection; glUniform1i(gl->uTexture, 0); glActiveTexture(GL_TEXTURE0); @@ -1382,6 +1425,7 @@ static bool glSetRenderTarget(Renderer* renderer, int32_t surfaceId) { if (surfaceId == renderer->runner->applicationSurfaceId) { glUniformMatrix4fv(gl->uProjection, 1, GL_FALSE, renderer->PreviousViewMatrix.m); + renderer->GML_Matrices[MATRIX_WORLD_VIEW_PROJECTION] = renderer->PreviousViewMatrix; glViewport(gl->base.CPortX, gl->base.CPortY, gl->base.CPortW, gl->base.CPortH); glEnable(GL_SCISSOR_TEST); return true; @@ -1392,6 +1436,7 @@ static bool glSetRenderTarget(Renderer* renderer, int32_t surfaceId) { Matrix4f_identity(&projection); Matrix4f_ortho(&projection, 0.0f, (float) gl->surfaceWidth[surfaceId], (float) gl->surfaceHeight[surfaceId], 0.0f, -1.0f, 1.0f); glUniformMatrix4fv(gl->uProjection, 1, GL_FALSE, projection.m); + renderer->GML_Matrices[MATRIX_WORLD_VIEW_PROJECTION] = projection; glViewport(0, 0, gl->surfaceWidth[surfaceId], gl->surfaceHeight[surfaceId]); glDisable(GL_SCISSOR_TEST); return true; @@ -1668,6 +1713,68 @@ static void glGpuSetFog(Renderer* renderer, bool enable, uint32_t color) { glUniform4f(gl->uFogColor, r, g, b, enable ? 1.0f : 0.0f); } +static void glGpuSetShader(Renderer* renderer, int32_t ShaderIndex) { + GLRenderer* gl = (GLRenderer*) renderer; + flushBatch(gl); + GLuint Shader = gl->GMLShaders[ShaderIndex]; + GLint gm_BaseTexture = glGetUniformLocation(Shader, "gm_BaseTexture"); + GLint gm_Matrices0 = glGetUniformLocation(Shader, "gm_Matrices[0]"); + GLint gm_Matrices1 = glGetUniformLocation(Shader, "gm_Matrices[1]"); + GLint gm_Matrices2 = glGetUniformLocation(Shader, "gm_Matrices[2]"); + GLint gm_Matrices3 = glGetUniformLocation(Shader, "gm_Matrices[3]"); + GLint gm_Matrices4 = glGetUniformLocation(Shader, "gm_Matrices[4]"); + + glUseProgram(Shader); + if (gm_BaseTexture != -1) { + glUniform1i(gm_BaseTexture, 0); + } + + if (gm_Matrices0 != -1) { + glUniformMatrix4fv(gm_Matrices4, 1, GL_FALSE, renderer->GML_Matrices[MATRIX_VIEW].m); + } + if (gm_Matrices1 != -1) { + glUniformMatrix4fv(gm_Matrices4, 1, GL_FALSE, renderer->GML_Matrices[MATRIX_PROJECTION].m); + } + if (gm_Matrices2 != -1) { + glUniformMatrix4fv(gm_Matrices4, 1, GL_FALSE, renderer->GML_Matrices[MATRIX_WORLD].m); + } + if (gm_Matrices3 != -1) { + glUniformMatrix4fv(gm_Matrices4, 1, GL_FALSE, renderer->GML_Matrices[MATRIX_WORLD_VIEW].m); + } + if (gm_Matrices4 != -1) { + glUniformMatrix4fv(gm_Matrices4, 1, GL_FALSE, renderer->GML_Matrices[MATRIX_WORLD_VIEW_PROJECTION].m); + } +} + +static void glGpuResetShader(Renderer* renderer) { + GLRenderer* gl = (GLRenderer*) renderer; + flushBatch(gl); + glUseProgram(gl->shaderProgram); +} + +static int32_t glShaderGetUniform(Renderer* renderer, int32_t shaderIndex, char* uniform) { + GLRenderer* gl = (GLRenderer*) renderer; + flushBatch(gl); + GLuint Shader = gl->GMLShaders[shaderIndex]; + return glGetUniformLocation(Shader, uniform); +} + +static void glShaderSetUniformF(Renderer* renderer, int32_t handle, int8_t count, float value1, float value2, float value3, float value4) { + GLRenderer* gl = (GLRenderer*) renderer; + flushBatch(gl); + + if (count == 1) { + glUniform1f(handle, value1); + } else if (count == 2) { + glUniform2f(handle, value1, value2); + } else if (count == 3) { + glUniform3f(handle, value1, value2, value3); + } else if (count == 4) { + glUniform4f(handle, value1, value2, value3, value4); + } + +} + // ===[ Vtable ]=== static RendererVtable glVtable; @@ -1722,6 +1829,10 @@ Renderer* GLRenderer_create(void) { glVtable.drawSurface = glDrawSurface; glVtable.surfaceResize = glSurfaceResize; glVtable.surfaceFree = glSurfaceFree; + glVtable.gpuSetShader = glGpuSetShader, + glVtable.gpuResetShader = glGpuResetShader, + glVtable.shaderGetUniform = glShaderGetUniform, + glVtable.shaderSetUniformF = glShaderSetUniformF, gl->base.drawColor = 0xFFFFFF; // white (BGR) gl->base.drawAlpha = 1.0f; gl->base.drawFont = -1; diff --git a/src/gl/gl_renderer.h b/src/gl/gl_renderer.h index 67561c50..c5ec8bab 100644 --- a/src/gl/gl_renderer.h +++ b/src/gl/gl_renderer.h @@ -24,6 +24,8 @@ typedef struct { GLint uTexture; GLint uAlphaTestRef; GLint uFogColor; + GLuint* GMLShaders; + uint32_t GMLShaderCount; bool alphaTestEnable; float alphaTestRef; diff --git a/src/renderer.h b/src/renderer.h index 7d57ee01..1397b36c 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -30,6 +30,13 @@ #define bm_inv_dest_color 10 #define bm_src_alpha_sat 11 +#define MATRIX_VIEW 0 +#define MATRIX_PROJECTION 1 +#define MATRIX_WORLD 2 +#define MATRIX_WORLD_VIEW 3 +#define MATRIX_WORLD_VIEW_PROJECTION 4 +#define MATRICES_MAX 5 + // Sentinel returned by ensureApplicationSurface on platforms that don't back the application_surface with a real entry in the renderer's surface table. // // Also used as the initial value of Runner.applicationSurfaceId before the first ensure call. @@ -110,6 +117,11 @@ typedef struct { // Optional: tile a source sub-rect (in tpag source-page space) across a dest rect, for nine-slice Repeat/BlankRepeat at angle 0. // srcX/srcY are post tpag->targetX/Y. nullptr = per-tile drawSpritePart fallback (also used for Mirror and non-zero angle). void (*drawTiledPart)(Renderer* renderer, int32_t tpagIndex, int32_t srcX, int32_t srcY, int32_t srcW, int32_t srcH, float dstX, float dstY, float dstW, float dstH, uint32_t color, float alpha); + // Shader Functions + void (*gpuSetShader)(Renderer* renderer, int32_t shaderIndex); + void (*gpuResetShader)(Renderer* renderer); + int32_t (*shaderGetUniform)(Renderer* renderer, int32_t shaderIndex, char* uniform); + void (*shaderSetUniformF)(Renderer* renderer, int32_t handle, int8_t count, float value1, float value2, float value3, float value4); } RendererVtable; // ===[ Renderer Base Struct ]=== @@ -130,6 +142,7 @@ struct Renderer { int32_t CPortW; int32_t CPortH; Runner* runner; + Matrix4f GML_Matrices[MATRICES_MAX]; }; // ===[ Shared Helpers (platform-agnostic) ]=== diff --git a/src/vm_builtins.c b/src/vm_builtins.c index 54c6f88c..0d292dac 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -12944,6 +12944,65 @@ static RValue builtin_parameter_string(VMContext* ctx, RValue* args, int32_t arg return RValue_makeString(ctx->runner->gameArgs[index]); } +static RValue builtin_shader_set(VMContext* ctx, MAYBE_UNUSED RValue* args, MAYBE_UNUSED int32_t argCount) { + + int32_t ShaderID = (int32_t) RValue_toReal(args[0]); + //fprintf(stderr, "Set Shader ID %u\n", ShaderID); + //gpuSetShader + if (ctx->runner->renderer->vtable->gpuSetShader != nullptr) { + ctx->runner->renderer->vtable->gpuSetShader(ctx->runner->renderer, ShaderID); + } + return RValue_makeUndefined(); +} + +static RValue builtin_shader_reset(VMContext* ctx, MAYBE_UNUSED RValue* args, MAYBE_UNUSED int32_t argCount) { + + if (ctx->runner->renderer->vtable->gpuResetShader != nullptr) { + ctx->runner->renderer->vtable->gpuResetShader(ctx->runner->renderer); + } + return RValue_makeUndefined(); +} + +static RValue builtin_shader_get_uniform(VMContext* ctx, MAYBE_UNUSED RValue* args, MAYBE_UNUSED int32_t argCount) { + + int32_t ShaderID = (int32_t) RValue_toReal(args[0]); + char* uniform = RValue_toString(args[1]); + if (ctx->runner->renderer->vtable->shaderGetUniform != nullptr) { + return RValue_makeReal(ctx->runner->renderer->vtable->shaderGetUniform(ctx->runner->renderer, ShaderID, uniform)); + } + return RValue_makeReal(-1); +} + +static RValue builtin_shader_set_uniformF(VMContext* ctx, MAYBE_UNUSED RValue* args, MAYBE_UNUSED int32_t argCount) { + + int32_t handle = (int32_t) RValue_toReal(args[0]); + float value1, value2, value3, value4; + //fprintf(stderr, "Set ARG Count %u\n", argCount); + if (ctx->runner->renderer->vtable->shaderSetUniformF != nullptr) { + //return RValue_makeReal(ctx->runner->renderer->vtable->shaderSetUniformF(ctx->runner->renderer, ShaderID, uniform)); + if (argCount == 2) { + value1 = (float) RValue_toReal(args[2]); + ctx->runner->renderer->vtable->shaderSetUniformF(ctx->runner->renderer, handle, 1, value1, 0.0, 0.0, 0.0); + } else if (argCount == 3) { + value1 = (float) RValue_toReal(args[2]); + value2 = (float) RValue_toReal(args[3]); + ctx->runner->renderer->vtable->shaderSetUniformF(ctx->runner->renderer, handle, 2, value1, value2, 0.0, 0.0); + } else if (argCount == 4) { + value1 = (float) RValue_toReal(args[2]); + value2 = (float) RValue_toReal(args[3]); + value3 = (float) RValue_toReal(args[4]); + ctx->runner->renderer->vtable->shaderSetUniformF(ctx->runner->renderer, handle, 3, value1, value2, value3, 0.0); + } else if (argCount == 5) { + value1 = (float) RValue_toReal(args[2]); + value2 = (float) RValue_toReal(args[3]); + value3 = (float) RValue_toReal(args[4]); + value4 = (float) RValue_toReal(args[5]); + ctx->runner->renderer->vtable->shaderSetUniformF(ctx->runner->renderer, handle, 4, value1, value2, value3, value4); + } + + } + return RValue_makeUndefined(); +} // ===[ REGISTRATION ]=== void VMBuiltins_registerAll(VMContext* ctx) { @@ -13808,4 +13867,9 @@ void VMBuiltins_registerAll(VMContext* ctx) { VM_registerBuiltin(ctx, "game_change", builtin_game_change); VM_registerBuiltin(ctx, "parameter_count", builtin_parameter_count); VM_registerBuiltin(ctx, "parameter_string", builtin_parameter_string); + VM_registerBuiltin(ctx,"shader_set", builtin_shader_set); + VM_registerBuiltin(ctx,"shader_reset", builtin_shader_reset); + VM_registerBuiltin(ctx,"shader_get_uniform", builtin_shader_get_uniform); + VM_registerBuiltin(ctx,"shader_set_uniform_f", builtin_shader_set_uniformF); + } From 87da316619e03c4c8a8c4df4cca92da7e3124e1f Mon Sep 17 00:00:00 2001 From: Classic0306 <190026317+Classic0306@users.noreply.github.com> Date: Thu, 21 May 2026 16:56:38 +0200 Subject: [PATCH 02/11] more shader thingies --- src/gl/gl_renderer.c | 77 +++++++++++++++++++++++++++++--- src/gl/gl_renderer.h | 1 + src/renderer.h | 8 +++- src/runner.c | 2 +- src/vm_builtins.c | 104 ++++++++++++++++++++++++++++++++++++------- 5 files changed, 167 insertions(+), 25 deletions(-) diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index fdb41d17..08098367 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -199,10 +199,39 @@ static void glInit(Renderer* renderer, DataWin* dataWin) { GLuint fragShaderT = compileShader(GL_FRAGMENT_SHADER, shdr->glsl_Fragment); gl->GMLShaderCount++; gl->GMLShaders = safeRealloc(gl->GMLShaders, gl->GMLShaderCount * sizeof(GLuint)); + gl->Sampler2DLookUpTable = safeRealloc(gl->Sampler2DLookUpTable, gl->GMLShaderCount * sizeof(int32_t*)); fprintf(stderr, "GL: Linking %s\n", shdr->name); gl->GMLShaders[i] = linkProgramCompat(vertShaderT, fragShaderT); - + //Texture Set Stage BS has to be done bruh :( + int32_t SamplerIndex = 0; + GLint UniformCount; + glGetProgramiv(gl->GMLShaders[i], GL_ACTIVE_UNIFORMS, &UniformCount); + + gl->Sampler2DLookUpTable[i] = malloc(UniformCount * sizeof(int32_t)); + + GLint LongestUniformName = 0; + glGetProgramiv(gl->GMLShaders[i], GL_ACTIVE_UNIFORM_MAX_LENGTH, &LongestUniformName); + char *UniformName = malloc(LongestUniformName); + + for (GLint b = 0; b < UniformCount; b++) { + GLsizei length = 0; + GLint size = 0; + GLenum type = 0; + glGetActiveUniform(gl->GMLShaders[i], b, LongestUniformName, &length, &size, &type, UniformName); + //glGetUniformIndices + gl->Sampler2DLookUpTable[i][b] = -1; + if (type == GL_SAMPLER_2D) + { + GLint location = glGetUniformLocation(gl->GMLShaders[i], UniformName); + SamplerIndex += 1; + gl->Sampler2DLookUpTable[i][b] = SamplerIndex; + //printf("GL: %s Should Be Texture Stage %d at %d\n", UniformName, SamplerIndex, location); + } + printf("GL: Uniform Index %d is Sampler2D Index %d\n", b, gl->Sampler2DLookUpTable[i][b]); + } + free(UniformName); + //fprintf(stderr, "GL: Shader Uniform Count %u\n", UniformCount); } @@ -1730,36 +1759,40 @@ static void glGpuSetShader(Renderer* renderer, int32_t ShaderIndex) { } if (gm_Matrices0 != -1) { - glUniformMatrix4fv(gm_Matrices4, 1, GL_FALSE, renderer->GML_Matrices[MATRIX_VIEW].m); + glUniformMatrix4fv(gm_Matrices0, 1, GL_FALSE, renderer->GML_Matrices[MATRIX_VIEW].m); } if (gm_Matrices1 != -1) { - glUniformMatrix4fv(gm_Matrices4, 1, GL_FALSE, renderer->GML_Matrices[MATRIX_PROJECTION].m); + glUniformMatrix4fv(gm_Matrices1, 1, GL_FALSE, renderer->GML_Matrices[MATRIX_PROJECTION].m); } if (gm_Matrices2 != -1) { - glUniformMatrix4fv(gm_Matrices4, 1, GL_FALSE, renderer->GML_Matrices[MATRIX_WORLD].m); + glUniformMatrix4fv(gm_Matrices2, 1, GL_FALSE, renderer->GML_Matrices[MATRIX_WORLD].m); } if (gm_Matrices3 != -1) { - glUniformMatrix4fv(gm_Matrices4, 1, GL_FALSE, renderer->GML_Matrices[MATRIX_WORLD_VIEW].m); + glUniformMatrix4fv(gm_Matrices3, 1, GL_FALSE, renderer->GML_Matrices[MATRIX_WORLD_VIEW].m); } if (gm_Matrices4 != -1) { glUniformMatrix4fv(gm_Matrices4, 1, GL_FALSE, renderer->GML_Matrices[MATRIX_WORLD_VIEW_PROJECTION].m); } + renderer->CurrentShader = ShaderIndex; } static void glGpuResetShader(Renderer* renderer) { GLRenderer* gl = (GLRenderer*) renderer; flushBatch(gl); glUseProgram(gl->shaderProgram); + renderer->CurrentShader = -1; } static int32_t glShaderGetUniform(Renderer* renderer, int32_t shaderIndex, char* uniform) { GLRenderer* gl = (GLRenderer*) renderer; flushBatch(gl); GLuint Shader = gl->GMLShaders[shaderIndex]; + //fprintf(stderr, "GL: Uniform Location %u\n", glGetUniformLocation(Shader, uniform)); + return glGetUniformLocation(Shader, uniform); } -static void glShaderSetUniformF(Renderer* renderer, int32_t handle, int8_t count, float value1, float value2, float value3, float value4) { +static void glShaderSetUniformF(Renderer* renderer, int32_t handle, int32_t count, float value1, float value2, float value3, float value4) { GLRenderer* gl = (GLRenderer*) renderer; flushBatch(gl); @@ -1775,6 +1808,31 @@ static void glShaderSetUniformF(Renderer* renderer, int32_t handle, int8_t count } +static int32_t glSpriteGetTexture(Renderer* renderer, int32_t tpagIndex) { + GLRenderer* gl = (GLRenderer*) renderer; + TexturePageItem* tpag; + GLuint texId; + int32_t texW, texH; + if (!resolveSpriteTexture(gl, tpagIndex, &tpag, &texId, &texW, &texH)) return -1; + + return (int32_t) texId; + +} + +//static void glTextureSetStage(Renderer* renderer, int32_t stage, int32_t texture) { +// GLRenderer* gl = (GLRenderer*) renderer; +// +//} + +static float glTextureGetTexelWidth(Renderer* renderer, int16_t pageId) { + GLRenderer* gl = (GLRenderer*) renderer; + return (1.0 / (float) gl->textureWidths[pageId]); +} + +static float glTextureGetTexelHeight(Renderer* renderer, int16_t pageId) { + GLRenderer* gl = (GLRenderer*) renderer; + return (1.0 / (float) gl->textureHeights[pageId]); +} // ===[ Vtable ]=== static RendererVtable glVtable; @@ -1833,12 +1891,17 @@ Renderer* GLRenderer_create(void) { glVtable.gpuResetShader = glGpuResetShader, glVtable.shaderGetUniform = glShaderGetUniform, glVtable.shaderSetUniformF = glShaderSetUniformF, + glVtable.spriteGetTexture = glSpriteGetTexture, + glVtable.textureGetTexelWidth = glTextureGetTexelWidth, + glVtable.textureGetTexelHeight = glTextureGetTexelHeight, + //.textureSetStage = glTextureSetStage, + gl->base.drawColor = 0xFFFFFF; // white (BGR) gl->base.drawAlpha = 1.0f; gl->base.drawFont = -1; gl->base.drawHalign = 0; gl->base.drawValign = 0; gl->base.circlePrecision = 24; - + gl->base.CurrentShader = -1; return (Renderer*) gl; } diff --git a/src/gl/gl_renderer.h b/src/gl/gl_renderer.h index c5ec8bab..010ea8ab 100644 --- a/src/gl/gl_renderer.h +++ b/src/gl/gl_renderer.h @@ -26,6 +26,7 @@ typedef struct { GLint uFogColor; GLuint* GMLShaders; uint32_t GMLShaderCount; + int32_t** Sampler2DLookUpTable; bool alphaTestEnable; float alphaTestRef; diff --git a/src/renderer.h b/src/renderer.h index 1397b36c..69ed10ce 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -37,6 +37,8 @@ #define MATRIX_WORLD_VIEW_PROJECTION 4 #define MATRICES_MAX 5 +#define MAX_TEXTURE_STAGES 8 + // Sentinel returned by ensureApplicationSurface on platforms that don't back the application_surface with a real entry in the renderer's surface table. // // Also used as the initial value of Runner.applicationSurfaceId before the first ensure call. @@ -121,7 +123,10 @@ typedef struct { void (*gpuSetShader)(Renderer* renderer, int32_t shaderIndex); void (*gpuResetShader)(Renderer* renderer); int32_t (*shaderGetUniform)(Renderer* renderer, int32_t shaderIndex, char* uniform); - void (*shaderSetUniformF)(Renderer* renderer, int32_t handle, int8_t count, float value1, float value2, float value3, float value4); + void (*shaderSetUniformF)(Renderer* renderer, int32_t handle, int32_t count, float value1, float value2, float value3, float value4); + int32_t (*spriteGetTexture)(Renderer* renderer, int32_t tpagIndex); + float (*textureGetTexelWidth)(Renderer* renderer, int16_t pageId); + float (*textureGetTexelHeight)(Renderer* renderer, int16_t pageId); } RendererVtable; // ===[ Renderer Base Struct ]=== @@ -143,6 +148,7 @@ struct Renderer { int32_t CPortH; Runner* runner; Matrix4f GML_Matrices[MATRICES_MAX]; + int32_t CurrentShader; }; // ===[ Shared Helpers (platform-agnostic) ]=== diff --git a/src/runner.c b/src/runner.c index 839c2559..faddb4f2 100644 --- a/src/runner.c +++ b/src/runner.c @@ -2112,7 +2112,7 @@ void Runner_initFirstRoom(Runner* runner) { repeat(dataWin->glob.count, i) { int32_t codeId = dataWin->glob.codeIds[i]; if (codeId >= 0 && dataWin->code.count > (uint32_t) codeId) { - fprintf(stderr, "Runner: Executing global init script: %s\n", dataWin->code.entries[codeId].name); + //fprintf(stderr, "Runner: Executing global init script: %s\n", dataWin->code.entries[codeId].name); RValue result = VM_executeCode(runner->vmContext, codeId); RValue_free(&result); } diff --git a/src/vm_builtins.c b/src/vm_builtins.c index 0d292dac..8d6bb4c9 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -12963,14 +12963,24 @@ static RValue builtin_shader_reset(VMContext* ctx, MAYBE_UNUSED RValue* args, MA return RValue_makeUndefined(); } +static RValue builtin_shader_current(VMContext* ctx, MAYBE_UNUSED RValue* args, MAYBE_UNUSED int32_t argCount) { + + if (ctx->runner->renderer != nullptr) { + return RValue_makeReal(ctx->runner->renderer->CurrentShader); + } + return RValue_makeReal(-1); +} + + + static RValue builtin_shader_get_uniform(VMContext* ctx, MAYBE_UNUSED RValue* args, MAYBE_UNUSED int32_t argCount) { int32_t ShaderID = (int32_t) RValue_toReal(args[0]); char* uniform = RValue_toString(args[1]); if (ctx->runner->renderer->vtable->shaderGetUniform != nullptr) { - return RValue_makeReal(ctx->runner->renderer->vtable->shaderGetUniform(ctx->runner->renderer, ShaderID, uniform)); + return RValue_makeInt32(ctx->runner->renderer->vtable->shaderGetUniform(ctx->runner->renderer, ShaderID, uniform)); } - return RValue_makeReal(-1); + return RValue_makeInt32(-1); } static RValue builtin_shader_set_uniformF(VMContext* ctx, MAYBE_UNUSED RValue* args, MAYBE_UNUSED int32_t argCount) { @@ -12981,28 +12991,84 @@ static RValue builtin_shader_set_uniformF(VMContext* ctx, MAYBE_UNUSED RValue* a if (ctx->runner->renderer->vtable->shaderSetUniformF != nullptr) { //return RValue_makeReal(ctx->runner->renderer->vtable->shaderSetUniformF(ctx->runner->renderer, ShaderID, uniform)); if (argCount == 2) { - value1 = (float) RValue_toReal(args[2]); + value1 = (float) RValue_toReal(args[1]); ctx->runner->renderer->vtable->shaderSetUniformF(ctx->runner->renderer, handle, 1, value1, 0.0, 0.0, 0.0); } else if (argCount == 3) { - value1 = (float) RValue_toReal(args[2]); - value2 = (float) RValue_toReal(args[3]); + value1 = (float) RValue_toReal(args[1]); + value2 = (float) RValue_toReal(args[2]); ctx->runner->renderer->vtable->shaderSetUniformF(ctx->runner->renderer, handle, 2, value1, value2, 0.0, 0.0); } else if (argCount == 4) { - value1 = (float) RValue_toReal(args[2]); - value2 = (float) RValue_toReal(args[3]); - value3 = (float) RValue_toReal(args[4]); + value1 = (float) RValue_toReal(args[1]); + value2 = (float) RValue_toReal(args[2]); + value3 = (float) RValue_toReal(args[3]); ctx->runner->renderer->vtable->shaderSetUniformF(ctx->runner->renderer, handle, 3, value1, value2, value3, 0.0); } else if (argCount == 5) { - value1 = (float) RValue_toReal(args[2]); - value2 = (float) RValue_toReal(args[3]); - value3 = (float) RValue_toReal(args[4]); - value4 = (float) RValue_toReal(args[5]); + value1 = (float) RValue_toReal(args[1]); + value2 = (float) RValue_toReal(args[2]); + value3 = (float) RValue_toReal(args[3]); + value4 = (float) RValue_toReal(args[4]); + //fprintf(stderr, "Value4 %.8f\n", value4); ctx->runner->renderer->vtable->shaderSetUniformF(ctx->runner->renderer, handle, 4, value1, value2, value3, value4); } } return RValue_makeUndefined(); } + +static RValue builtin_sprite_get_uvs(VMContext* ctx, MAYBE_UNUSED RValue* args, MAYBE_UNUSED int32_t argCount) { + + int32_t spriteIndex = (int32_t) RValue_toReal(args[0]); + int32_t subimg = RValue_toInt32(args[1]); + int32_t TpagIndex = Renderer_resolveTPAGIndex(ctx->dataWin, spriteIndex, subimg); + //I think default texture page size is 2048x2048? + float DivW = 0.00048828125; //1.0/2048.0 + float DivH = 0.00048828125; //1.0/2048.0 + + if (ctx->runner->renderer->vtable->textureGetTexelWidth != nullptr) { + DivW = ctx->runner->renderer->vtable->textureGetTexelWidth(ctx->runner->renderer, ctx->dataWin->tpag.items[TpagIndex].texturePageId); + DivH = ctx->runner->renderer->vtable->textureGetTexelHeight(ctx->runner->renderer, ctx->dataWin->tpag.items[TpagIndex].texturePageId); + } + + float left = (float) ctx->dataWin->tpag.items[TpagIndex].sourceX * DivW; + float top = (float) ctx->dataWin->tpag.items[TpagIndex].sourceY * DivH; + float right = (float) left + (ctx->dataWin->tpag.items[TpagIndex].sourceWidth * DivW); + float bottom = (float) top + (ctx->dataWin->tpag.items[TpagIndex].sourceHeight * DivH); + + + + GMLArray* out = GMLArray_create(8); + *GMLArray_slot(out, 0) = RValue_makeReal(left); + *GMLArray_slot(out, 1) = RValue_makeReal(top); + *GMLArray_slot(out, 2) = RValue_makeReal(right); + *GMLArray_slot(out, 3) = RValue_makeReal(bottom); + *GMLArray_slot(out, 4) = RValue_makeReal(0.0); + *GMLArray_slot(out, 5) = RValue_makeReal(0.0); + *GMLArray_slot(out, 6) = RValue_makeReal(0.0); + *GMLArray_slot(out, 7) = RValue_makeReal(0.0); + return RValue_makeArray(out); +} + +static RValue builtin_sprite_get_texture(VMContext* ctx, MAYBE_UNUSED RValue* args, MAYBE_UNUSED int32_t argCount) { + + int32_t spriteIndex = (int32_t) RValue_toReal(args[0]); + int32_t subimg = RValue_toInt32(args[1]); + int32_t TpagIndex = Renderer_resolveTPAGIndex(ctx->dataWin, spriteIndex, subimg); + + return RValue_makeInt32(ctx->runner->renderer->vtable->spriteGetTexture(ctx->runner->renderer, TpagIndex)); +} + +static RValue builtin_texture_get_texel_width(VMContext* ctx, MAYBE_UNUSED RValue* args, MAYBE_UNUSED int32_t argCount) { + + int16_t TpagIndex = (int16_t) RValue_toReal(args[0]); + return RValue_makeReal(ctx->runner->renderer->vtable->textureGetTexelWidth(ctx->runner->renderer, ctx->dataWin->tpag.items[TpagIndex].texturePageId)); +} + +static RValue builtin_texture_get_texel_height(VMContext* ctx, MAYBE_UNUSED RValue* args, MAYBE_UNUSED int32_t argCount) { + + int16_t TpagIndex = (int16_t) RValue_toReal(args[0]); + return RValue_makeReal(ctx->runner->renderer->vtable->textureGetTexelHeight(ctx->runner->renderer, ctx->dataWin->tpag.items[TpagIndex].texturePageId)); +} + // ===[ REGISTRATION ]=== void VMBuiltins_registerAll(VMContext* ctx) { @@ -13867,9 +13933,15 @@ void VMBuiltins_registerAll(VMContext* ctx) { VM_registerBuiltin(ctx, "game_change", builtin_game_change); VM_registerBuiltin(ctx, "parameter_count", builtin_parameter_count); VM_registerBuiltin(ctx, "parameter_string", builtin_parameter_string); - VM_registerBuiltin(ctx,"shader_set", builtin_shader_set); - VM_registerBuiltin(ctx,"shader_reset", builtin_shader_reset); - VM_registerBuiltin(ctx,"shader_get_uniform", builtin_shader_get_uniform); - VM_registerBuiltin(ctx,"shader_set_uniform_f", builtin_shader_set_uniformF); + VM_registerBuiltin(ctx, "shader_set", builtin_shader_set); + VM_registerBuiltin(ctx, "shader_reset", builtin_shader_reset); + VM_registerBuiltin(ctx, "shader_current", builtin_shader_current); + VM_registerBuiltin(ctx, "shader_get_uniform", builtin_shader_get_uniform); + + VM_registerBuiltin(ctx, "shader_set_uniform_f", builtin_shader_set_uniformF); + VM_registerBuiltin(ctx, "sprite_get_uvs", builtin_sprite_get_uvs); + VM_registerBuiltin(ctx, "sprite_get_texture", builtin_sprite_get_texture); + VM_registerBuiltin(ctx, "texture_get_texel_width", builtin_texture_get_texel_width); + VM_registerBuiltin(ctx, "texture_get_texel_height", builtin_texture_get_texel_height); } From 82351eb43f287993ab5326ab99be456a83b057bb Mon Sep 17 00:00:00 2001 From: Classic0306 <190026317+Classic0306@users.noreply.github.com> Date: Sun, 24 May 2026 14:13:47 +0200 Subject: [PATCH 03/11] I dunno what to name this commit --- src/gl/gl_renderer.c | 289 +++++++++++++++++++++++++++----------- src/gl/gl_renderer.h | 1 + src/gl_common/gl_common.c | 5 +- src/renderer.h | 2 + src/vm_builtins.c | 24 +++- 5 files changed, 233 insertions(+), 88 deletions(-) diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index 08098367..8af6da45 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -109,8 +109,8 @@ static GLuint linkProgramCompat(GLuint vertShader, GLuint fragShader) { glAttachShader(program, fragShader); glBindAttribLocation(program, 0, "in_Position"); - glBindAttribLocation(program, 2, "in_Colour"); glBindAttribLocation(program, 1, "in_TexCoord"); + glBindAttribLocation(program, 2, "in_Colour"); glLinkProgram(program); @@ -180,16 +180,15 @@ static void glInit(Renderer* renderer, DataWin* dataWin) { GLRenderer* gl = (GLRenderer*) renderer; renderer->dataWin = dataWin; - // Compile shaders + //compile em shaders! GLuint vertShader = compileShader(GL_VERTEX_SHADER, vertexShaderSource); GLuint fragShader = compileShader(GL_FRAGMENT_SHADER, fragmentShaderSource); gl->shaderProgram = linkProgram(vertShader, fragShader); glDeleteShader(vertShader); glDeleteShader(fragShader); - //yeah find the way to get the shaders here!!! + //yeah find the way to get the shaders here!!! fprintf(stderr, "GL: %u Shaders Found\n", dataWin->shdr.count); - for (uint32_t i = 0; dataWin->shdr.count > i; i++) - { + for (uint32_t i = 0; dataWin->shdr.count > i; i++) { Shader* shdr = &dataWin->shdr.shaders[i]; //fprintf(stderr, "GL: Shader %u %s Type %u\n", i, shdr->name, shdr->type); //GLuint* GMLShaders; @@ -208,11 +207,11 @@ static void glInit(Renderer* renderer, DataWin* dataWin) { GLint UniformCount; glGetProgramiv(gl->GMLShaders[i], GL_ACTIVE_UNIFORMS, &UniformCount); - gl->Sampler2DLookUpTable[i] = malloc(UniformCount * sizeof(int32_t)); - + gl->Sampler2DLookUpTable[i] = safeMalloc(UniformCount * sizeof(int32_t)); + //bool FoundBaseTexture = false; GLint LongestUniformName = 0; glGetProgramiv(gl->GMLShaders[i], GL_ACTIVE_UNIFORM_MAX_LENGTH, &LongestUniformName); - char *UniformName = malloc(LongestUniformName); + char *UniformName = safeMalloc(LongestUniformName); for (GLint b = 0; b < UniformCount; b++) { GLsizei length = 0; @@ -223,13 +222,22 @@ static void glInit(Renderer* renderer, DataWin* dataWin) { gl->Sampler2DLookUpTable[i][b] = -1; if (type == GL_SAMPLER_2D) { + //if (UniformName == "gm_BaseTexture") { + // FoundBaseTexture = true; + //} GLint location = glGetUniformLocation(gl->GMLShaders[i], UniformName); + glUseProgram(gl->GMLShaders[i]); + glUniform1i(location, SamplerIndex); SamplerIndex += 1; gl->Sampler2DLookUpTable[i][b] = SamplerIndex; //printf("GL: %s Should Be Texture Stage %d at %d\n", UniformName, SamplerIndex, location); + //printf("GL: Uniform Index %d is Sampler2D Index %d %s\n", b, gl->Sampler2DLookUpTable[i][b], UniformName); } - printf("GL: Uniform Index %d is Sampler2D Index %d\n", b, gl->Sampler2DLookUpTable[i][b]); + //printf("GL: Uniform Index %d is Sampler2D Index %d\n", b, gl->Sampler2DLookUpTable[i][b]); } + //if (FoundBaseTexture == false) { + // printf("GL: gm_BaseTexture Not Used In Shader %s \n", shdr->name); + //} free(UniformName); //fprintf(stderr, "GL: Shader Uniform Count %u\n", UniformCount); @@ -331,6 +339,72 @@ static void glInit(Renderer* renderer, DataWin* dataWin) { fprintf(stderr, "GL: Renderer initialized (%u texture pages)\n", gl->textureCount); } +static void glGpuResetShader(Renderer* renderer) { + GLRenderer* gl = (GLRenderer*) renderer; + flushBatch(gl); + glUseProgram(gl->shaderProgram); + renderer->CurrentShader = -1; +} + +static void glGpuSetShader(Renderer* renderer, int32_t ShaderIndex) { + GLRenderer* gl = (GLRenderer*) renderer; + flushBatch(gl); + GLuint Shader = gl->GMLShaders[ShaderIndex]; + glUseProgram(Shader); + //Gotta set those built-ins! they ain't gonna set themselves + GLint gm_Matrices0 = glGetUniformLocation(Shader, "gm_Matrices[0]"); + GLint gm_Matrices1 = glGetUniformLocation(Shader, "gm_Matrices[1]"); + GLint gm_Matrices2 = glGetUniformLocation(Shader, "gm_Matrices[2]"); + GLint gm_Matrices3 = glGetUniformLocation(Shader, "gm_Matrices[3]"); + GLint gm_Matrices4 = glGetUniformLocation(Shader, "gm_Matrices[4]"); + GLint gm_BaseTexture = glGetUniformLocation(Shader, "gm_BaseTexture"); + + GLint gm_FogStart = glGetUniformLocation(Shader, "gm_FogStart"); + GLint gm_RcpFogRange = glGetUniformLocation(Shader, "gm_RcpFogRange"); + GLint gm_PS_FogEnabled = glGetUniformLocation(Shader, "gm_PS_FogEnabled"); + GLint gm_FogColour = glGetUniformLocation(Shader, "gm_FogColour"); + GLint gm_VS_FogEnabled = glGetUniformLocation(Shader, "gm_VS_FogEnabled"); + + GLint gm_AlphaTestEnabled = glGetUniformLocation(Shader, "gm_AlphaTestEnabled"); + GLint gm_AlphaRefValue = glGetUniformLocation(Shader, "gm_AlphaRefValue"); + + if (gm_BaseTexture != -1) { + glUniform1i(gm_BaseTexture, 0); + } + + if (gm_Matrices0 != -1) { + glUniformMatrix4fv(gm_Matrices0, 1, GL_FALSE, renderer->GML_Matrices[MATRIX_VIEW].m); + } + if (gm_Matrices1 != -1) { + glUniformMatrix4fv(gm_Matrices1, 1, GL_FALSE, renderer->GML_Matrices[MATRIX_PROJECTION].m); + } + if (gm_Matrices2 != -1) { + glUniformMatrix4fv(gm_Matrices2, 1, GL_FALSE, renderer->GML_Matrices[MATRIX_WORLD].m); + } + if (gm_Matrices3 != -1) { + glUniformMatrix4fv(gm_Matrices3, 1, GL_FALSE, renderer->GML_Matrices[MATRIX_WORLD_VIEW].m); + } + if (gm_Matrices4 != -1) { + glUniformMatrix4fv(gm_Matrices4, 1, GL_FALSE, renderer->GML_Matrices[MATRIX_WORLD_VIEW_PROJECTION].m); + } + + + if (gm_FogColour != -1) { + glUniform1i(gm_FogColour, gl->fogColor); + } + + + if (gm_AlphaTestEnabled != -1) { + glUniform1i(gm_AlphaTestEnabled, gl->alphaTestEnable); + } + if (gm_AlphaRefValue != -1) { + glUniform1f(gm_AlphaRefValue, gl->alphaTestRef); + } + + renderer->CurrentShader = ShaderIndex; +} + + static void glDestroy(Renderer* renderer) { GLRenderer* gl = (GLRenderer*) renderer; @@ -537,8 +611,8 @@ bool GLRenderer_ensureTextureLoaded(GLRenderer* gl, uint32_t pageId) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); free(pixels); fprintf(stderr, "GL: Loaded TXTR page %u (%dx%d)\n", pageId, w, h); @@ -1454,20 +1528,29 @@ static bool glSetRenderTarget(Renderer* renderer, int32_t surfaceId) { if (surfaceId == renderer->runner->applicationSurfaceId) { glUniformMatrix4fv(gl->uProjection, 1, GL_FALSE, renderer->PreviousViewMatrix.m); - renderer->GML_Matrices[MATRIX_WORLD_VIEW_PROJECTION] = renderer->PreviousViewMatrix; glViewport(gl->base.CPortX, gl->base.CPortY, gl->base.CPortW, gl->base.CPortH); glEnable(GL_SCISSOR_TEST); + renderer->GML_Matrices[MATRIX_WORLD_VIEW_PROJECTION] = renderer->PreviousViewMatrix; return true; } // Normal surface bind: surface-local ortho covering the whole surface, no scissor. Matrix4f projection; Matrix4f_identity(&projection); - Matrix4f_ortho(&projection, 0.0f, (float) gl->surfaceWidth[surfaceId], (float) gl->surfaceHeight[surfaceId], 0.0f, -1.0f, 1.0f); + Matrix4f_ortho(&projection, 0.0f, (float) gl->surfaceWidth[surfaceId], 0.0f, (float) gl->surfaceHeight[surfaceId], -1.0f, 1.0f); glUniformMatrix4fv(gl->uProjection, 1, GL_FALSE, projection.m); - renderer->GML_Matrices[MATRIX_WORLD_VIEW_PROJECTION] = projection; glViewport(0, 0, gl->surfaceWidth[surfaceId], gl->surfaceHeight[surfaceId]); glDisable(GL_SCISSOR_TEST); + renderer->GML_Matrices[MATRIX_WORLD_VIEW_PROJECTION] = projection; + if (renderer->CurrentShader != -1) + { + glGpuSetShader(renderer, (int32_t) renderer->CurrentShader); + } else { + glUseProgram(gl->shaderProgram); + glUniform1i(gl->uTexture, 0); + glUniformMatrix4fv(gl->uProjection, 1, GL_FALSE, projection.m); + } + return true; } @@ -1508,8 +1591,8 @@ static void glDrawSurface(Renderer* renderer, int32_t surfaceID, int32_t srcLeft // Texture is bottom-up in GL; GML src is top-down, so flip V. float u0 = (float) srcLeft / (float) texW; float u1 = (float) (srcLeft + srcWidth) / (float) texW; - float v0 = 1.0f - (float) srcTop / (float) texH; - float v1 = 1.0f - (float) (srcTop + srcHeight) / (float) texH; + float v1 = (float) srcTop / (float) texH; + float v0 = (float) (srcTop + srcHeight) / (float) texH; float localX1 = (float) srcWidth; float localY1 = (float) srcHeight; @@ -1520,10 +1603,10 @@ static void glDrawSurface(Renderer* renderer, int32_t surfaceID, int32_t srcLeft Matrix4f_setTransform2D(&transform, x, y, xscale, yscale, angleRad); float x0, y0, x1, y1, x2, y2, x3, y3; - Matrix4f_transformPoint(&transform, 0.0f, 0.0f, &x0, &y0); // top-left - Matrix4f_transformPoint(&transform, localX1, 0.0f, &x1, &y1); // top-right - Matrix4f_transformPoint(&transform, localX1, localY1, &x2, &y2); // bottom-right - Matrix4f_transformPoint(&transform, 0.0f, localY1, &x3, &y3); // bottom-left + Matrix4f_transformPoint(&transform, 0.0f, localY1, &x0, &y0); // top-left + Matrix4f_transformPoint(&transform, localX1, localY1, &x1, &y1); // top-right + Matrix4f_transformPoint(&transform, localX1, 0.0, &x2, &y2); // bottom-right + Matrix4f_transformPoint(&transform, 0.0f, 0.0, &x3, &y3); // bottom-left float r = (float) BGR_R(color) / 255.0f; float g = (float) BGR_G(color) / 255.0f; @@ -1560,25 +1643,30 @@ static int32_t glCreateSpriteFromSurface(Renderer* renderer, int32_t surfaceID, glBindFramebuffer(GL_READ_FRAMEBUFFER, gl->surfaces[surfaceID]); // OpenGL Y is bottom-up, GML Y is top-down; flip Y to the GL coordinate. int32_t glY = gl->surfaceHeight[surfaceID] - y - h; + //if (surfaceID != APPLICATION_SURFACE_ID) { + glY = y; + //} uint8_t* pixels = safeMalloc((size_t) w * (size_t) h * 4); if (pixels == nullptr) return -1; glReadPixels(x, glY, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - - // Flip vertically (OpenGL reads bottom-to-top) - size_t rowBytes = (size_t) w * 4; - uint8_t* rowTemp = safeMalloc(rowBytes); - repeat(h / 2, row) { - uint8_t* top = pixels + row * rowBytes; - uint8_t* bot = pixels + (h - 1 - row) * rowBytes; - memcpy(rowTemp, top, rowBytes); - memcpy(top, bot, rowBytes); - memcpy(bot, rowTemp, rowBytes); + /* + if (surfaceID == APPLICATION_SURFACE_ID) { + // Flip vertically (OpenGL reads bottom-to-top) + size_t rowBytes = (size_t) w * 4; + uint8_t* rowTemp = safeMalloc(rowBytes); + repeat(h / 2, row) { + uint8_t* top = pixels + row * rowBytes; + uint8_t* bot = pixels + (h - 1 - row) * rowBytes; + memcpy(rowTemp, top, rowBytes); + memcpy(top, bot, rowBytes); + memcpy(bot, rowTemp, rowBytes); + } + free(rowTemp); } - free(rowTemp); - + */ // Create a new GL texture from the captured pixels GLuint newTexId; glGenTextures(1, &newTexId); @@ -1586,8 +1674,8 @@ static int32_t glCreateSpriteFromSurface(Renderer* renderer, int32_t surfaceID, glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); free(pixels); @@ -1742,67 +1830,85 @@ static void glGpuSetFog(Renderer* renderer, bool enable, uint32_t color) { glUniform4f(gl->uFogColor, r, g, b, enable ? 1.0f : 0.0f); } -static void glGpuSetShader(Renderer* renderer, int32_t ShaderIndex) { +static int32_t glShaderGetUniform(Renderer* renderer, int32_t shaderIndex, char* uniform) { GLRenderer* gl = (GLRenderer*) renderer; flushBatch(gl); - GLuint Shader = gl->GMLShaders[ShaderIndex]; - GLint gm_BaseTexture = glGetUniformLocation(Shader, "gm_BaseTexture"); - GLint gm_Matrices0 = glGetUniformLocation(Shader, "gm_Matrices[0]"); - GLint gm_Matrices1 = glGetUniformLocation(Shader, "gm_Matrices[1]"); - GLint gm_Matrices2 = glGetUniformLocation(Shader, "gm_Matrices[2]"); - GLint gm_Matrices3 = glGetUniformLocation(Shader, "gm_Matrices[3]"); - GLint gm_Matrices4 = glGetUniformLocation(Shader, "gm_Matrices[4]"); - - glUseProgram(Shader); - if (gm_BaseTexture != -1) { - glUniform1i(gm_BaseTexture, 0); - } - - if (gm_Matrices0 != -1) { - glUniformMatrix4fv(gm_Matrices0, 1, GL_FALSE, renderer->GML_Matrices[MATRIX_VIEW].m); - } - if (gm_Matrices1 != -1) { - glUniformMatrix4fv(gm_Matrices1, 1, GL_FALSE, renderer->GML_Matrices[MATRIX_PROJECTION].m); - } - if (gm_Matrices2 != -1) { - glUniformMatrix4fv(gm_Matrices2, 1, GL_FALSE, renderer->GML_Matrices[MATRIX_WORLD].m); + if (renderer->CurrentShader != -1) { + glUseProgram(gl->GMLShaders[renderer->CurrentShader]); //tf you mean this fixed the invalid location thing shouldn't GML code assume the same shader is still bound??? why was it even changed what the fu } - if (gm_Matrices3 != -1) { - glUniformMatrix4fv(gm_Matrices3, 1, GL_FALSE, renderer->GML_Matrices[MATRIX_WORLD_VIEW].m); - } - if (gm_Matrices4 != -1) { - glUniformMatrix4fv(gm_Matrices4, 1, GL_FALSE, renderer->GML_Matrices[MATRIX_WORLD_VIEW_PROJECTION].m); - } - renderer->CurrentShader = ShaderIndex; -} + GLuint Shader = gl->GMLShaders[shaderIndex]; + //fprintf(stderr, "GL: Uniform Get Location %u\n", glGetUniformLocation(Shader, uniform)); -static void glGpuResetShader(Renderer* renderer) { - GLRenderer* gl = (GLRenderer*) renderer; - flushBatch(gl); - glUseProgram(gl->shaderProgram); - renderer->CurrentShader = -1; + return glGetUniformLocation(Shader, uniform); } -static int32_t glShaderGetUniform(Renderer* renderer, int32_t shaderIndex, char* uniform) { +static int32_t glShaderGetSamplerIndex(Renderer* renderer, int32_t shaderIndex, char* uniform) { GLRenderer* gl = (GLRenderer*) renderer; flushBatch(gl); GLuint Shader = gl->GMLShaders[shaderIndex]; - //fprintf(stderr, "GL: Uniform Location %u\n", glGetUniformLocation(Shader, uniform)); - return glGetUniformLocation(Shader, uniform); + GLint UniformCount; + glGetProgramiv(Shader, GL_ACTIVE_UNIFORMS, &UniformCount); + + const GLchar* name = uniform; + GLuint index; + + glGetUniformIndices(Shader, 1, &name, &index); + + if (index == GL_INVALID_INDEX) + { + return -1; + } + + return gl->Sampler2DLookUpTable[shaderIndex][index]; } + static void glShaderSetUniformF(Renderer* renderer, int32_t handle, int32_t count, float value1, float value2, float value3, float value4) { GLRenderer* gl = (GLRenderer*) renderer; flushBatch(gl); + int32_t RealCount = count; + if (renderer->CurrentShader != -1) { + GLuint Shader = gl->GMLShaders[renderer->CurrentShader]; + glUseProgram(Shader); //tf you mean this fixed the invalid location thing shouldn't GML code assume the same shader is still bound??? why was it even changed what the fu + + GLint UniformCount; + glGetProgramiv(Shader, GL_ACTIVE_UNIFORMS, &UniformCount); + GLint LongestUniformName = 0; + glGetProgramiv(Shader, GL_ACTIVE_UNIFORM_MAX_LENGTH, &LongestUniformName); + char *UniformName = safeMalloc(LongestUniformName); - if (count == 1) { + for (GLint b = 0; b < UniformCount; b++) { + GLsizei length = 0; + GLint size = 0; + GLenum type = 0; + glGetActiveUniform(Shader, b, LongestUniformName, &length, &size, &type, UniformName); + + int32_t location = glGetUniformLocation(Shader, UniformName); + if (location == handle) + { + //fprintf(stderr, "GL: TF BRO IS RIGHT?\n"); + if (type == GL_FLOAT) RealCount = 1; + if (type == GL_FLOAT_VEC2) RealCount = 2; + if (type == GL_FLOAT_VEC3) RealCount = 3; + if (type == GL_FLOAT_VEC4) RealCount = 4; + } + + + } + free(UniformName); + + + + } + + if (RealCount == 1) { glUniform1f(handle, value1); - } else if (count == 2) { + } else if (RealCount == 2) { glUniform2f(handle, value1, value2); - } else if (count == 3) { + } else if (RealCount == 3) { glUniform3f(handle, value1, value2, value3); - } else if (count == 4) { + } else if (RealCount == 4) { glUniform4f(handle, value1, value2, value3, value4); } @@ -1815,22 +1921,36 @@ static int32_t glSpriteGetTexture(Renderer* renderer, int32_t tpagIndex) { int32_t texW, texH; if (!resolveSpriteTexture(gl, tpagIndex, &tpag, &texId, &texW, &texH)) return -1; - return (int32_t) texId; + return texId; } -//static void glTextureSetStage(Renderer* renderer, int32_t stage, int32_t texture) { -// GLRenderer* gl = (GLRenderer*) renderer; -// -//} +static void glTextureSetStage(Renderer* renderer, int32_t slot, int32_t texID) { + GLRenderer* gl = (GLRenderer*) renderer; + flushBatch(gl); + if (slot < 0) { + return; + } + if (slot == -1) { + fprintf(stderr, "GL: SOMETHING WRONK\n"); + return; + } + //return; + glActiveTexture(GL_TEXTURE0 + (slot-1)); + glBindTexture(GL_TEXTURE_2D, texID); + glActiveTexture(GL_TEXTURE0); + +} static float glTextureGetTexelWidth(Renderer* renderer, int16_t pageId) { - GLRenderer* gl = (GLRenderer*) renderer; + GLRenderer* gl = (GLRenderer*) renderer; + ensureTextureLoaded(gl, (uint32_t) pageId); return (1.0 / (float) gl->textureWidths[pageId]); } static float glTextureGetTexelHeight(Renderer* renderer, int16_t pageId) { - GLRenderer* gl = (GLRenderer*) renderer; + GLRenderer* gl = (GLRenderer*) renderer; + ensureTextureLoaded(gl, (uint32_t) pageId); return (1.0 / (float) gl->textureHeights[pageId]); } // ===[ Vtable ]=== @@ -1894,7 +2014,8 @@ Renderer* GLRenderer_create(void) { glVtable.spriteGetTexture = glSpriteGetTexture, glVtable.textureGetTexelWidth = glTextureGetTexelWidth, glVtable.textureGetTexelHeight = glTextureGetTexelHeight, - //.textureSetStage = glTextureSetStage, + glVtable.shaderGetSamplerIndex = glShaderGetSamplerIndex, + glVtable.textureSetStage = glTextureSetStage, gl->base.drawColor = 0xFFFFFF; // white (BGR) gl->base.drawAlpha = 1.0f; diff --git a/src/gl/gl_renderer.h b/src/gl/gl_renderer.h index 010ea8ab..0112a46c 100644 --- a/src/gl/gl_renderer.h +++ b/src/gl/gl_renderer.h @@ -27,6 +27,7 @@ typedef struct { GLuint* GMLShaders; uint32_t GMLShaderCount; int32_t** Sampler2DLookUpTable; + GLint** Sampler2DLocationLookUpTable; bool alphaTestEnable; float alphaTestRef; diff --git a/src/gl_common/gl_common.c b/src/gl_common/gl_common.c index e356b55a..f43e0b3d 100644 --- a/src/gl_common/gl_common.c +++ b/src/gl_common/gl_common.c @@ -34,8 +34,9 @@ void GLCommon_beginLetterboxBlit(GLuint fbo) { void GLCommon_endLetterboxBlit(int32_t fboWidth, int32_t fboHeight, int32_t gameW, int32_t gameH, int32_t windowW, int32_t windowH) { int32_t sx, sy, ex, ey; + glClearColor(0.0, 0.0, 0.0, 1.0); GLCommon_computeLetterbox(gameW, gameH, windowW, windowH, &sx, &sy, &ex, &ey); - glBlitFramebuffer(0, 0, fboWidth, fboHeight, sx, sy, ex, ey, GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBlitFramebuffer(0, 0, fboWidth, fboHeight, sx, ey, ex, sy, GL_COLOR_BUFFER_BIT, GL_NEAREST); glBindFramebuffer(GL_FRAMEBUFFER, 0); } @@ -86,7 +87,7 @@ void GLCommon_surfaceBlit(GLuint* surfaces, int32_t* surfaceWidth, int32_t* surf if (part) { // GL Y is bottom-up; convert GML's top-down (srcX, srcY) source rect. - int32_t srcY0 = srcFboH - srcY - srcH; + int32_t srcY0 = srcY; glBlitFramebuffer(srcX, srcY0, srcX + srcW, srcY0 + srcH, dstX, dstY, dstX + srcW, dstY + srcH, GL_COLOR_BUFFER_BIT, GL_NEAREST); } else { glBlitFramebuffer(0, 0, srcFboW, srcFboH, dstX, dstY, dstX + srcFboW, dstY + srcFboH, GL_COLOR_BUFFER_BIT, GL_NEAREST); diff --git a/src/renderer.h b/src/renderer.h index 69ed10ce..702e130f 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -123,10 +123,12 @@ typedef struct { void (*gpuSetShader)(Renderer* renderer, int32_t shaderIndex); void (*gpuResetShader)(Renderer* renderer); int32_t (*shaderGetUniform)(Renderer* renderer, int32_t shaderIndex, char* uniform); + int32_t (*shaderGetSamplerIndex)(Renderer* renderer, int32_t shaderIndex, char* uniform); void (*shaderSetUniformF)(Renderer* renderer, int32_t handle, int32_t count, float value1, float value2, float value3, float value4); int32_t (*spriteGetTexture)(Renderer* renderer, int32_t tpagIndex); float (*textureGetTexelWidth)(Renderer* renderer, int16_t pageId); float (*textureGetTexelHeight)(Renderer* renderer, int16_t pageId); + void (*textureSetStage)(Renderer* renderer, int32_t slot, int32_t texID); } RendererVtable; // ===[ Renderer Base Struct ]=== diff --git a/src/vm_builtins.c b/src/vm_builtins.c index 8d6bb4c9..acd4eb89 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -12983,6 +12983,26 @@ static RValue builtin_shader_get_uniform(VMContext* ctx, MAYBE_UNUSED RValue* ar return RValue_makeInt32(-1); } +static RValue builtin_shader_get_sampler_index(VMContext* ctx, MAYBE_UNUSED RValue* args, MAYBE_UNUSED int32_t argCount) { + + int32_t ShaderID = (int32_t) RValue_toReal(args[0]); + char* uniform = RValue_toString(args[1]); + if (ctx->runner->renderer->vtable->shaderGetSamplerIndex != nullptr) { + return RValue_makeInt32(ctx->runner->renderer->vtable->shaderGetSamplerIndex(ctx->runner->renderer, ShaderID, uniform)); + } + return RValue_makeInt32(-1); +} + +static RValue builtin_texture_set_stage(VMContext* ctx, MAYBE_UNUSED RValue* args, MAYBE_UNUSED int32_t argCount) { + + int32_t TextureSlot = (int32_t) RValue_toReal(args[0]); + int32_t texID = (int32_t) RValue_toInt32(args[1]); + if (ctx->runner->renderer->vtable->textureSetStage != nullptr) { + ctx->runner->renderer->vtable->textureSetStage(ctx->runner->renderer, TextureSlot, texID); + } + return RValue_makeUndefined(); +} + static RValue builtin_shader_set_uniformF(VMContext* ctx, MAYBE_UNUSED RValue* args, MAYBE_UNUSED int32_t argCount) { int32_t handle = (int32_t) RValue_toReal(args[0]); @@ -13937,11 +13957,11 @@ void VMBuiltins_registerAll(VMContext* ctx) { VM_registerBuiltin(ctx, "shader_reset", builtin_shader_reset); VM_registerBuiltin(ctx, "shader_current", builtin_shader_current); VM_registerBuiltin(ctx, "shader_get_uniform", builtin_shader_get_uniform); - + VM_registerBuiltin(ctx, "shader_get_sampler_index", builtin_shader_get_sampler_index); VM_registerBuiltin(ctx, "shader_set_uniform_f", builtin_shader_set_uniformF); VM_registerBuiltin(ctx, "sprite_get_uvs", builtin_sprite_get_uvs); VM_registerBuiltin(ctx, "sprite_get_texture", builtin_sprite_get_texture); VM_registerBuiltin(ctx, "texture_get_texel_width", builtin_texture_get_texel_width); VM_registerBuiltin(ctx, "texture_get_texel_height", builtin_texture_get_texel_height); - + VM_registerBuiltin(ctx, "texture_set_stage", builtin_texture_set_stage); } From c1e997004f8e1495a5227f90340a55a1be10dc43 Mon Sep 17 00:00:00 2001 From: Classic0306 <190026317+Classic0306@users.noreply.github.com> Date: Sun, 24 May 2026 17:05:48 +0200 Subject: [PATCH 04/11] blah blah --- src/gl/gl_renderer.c | 16 ++++------------ src/runner.c | 2 +- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index 8af6da45..a00fefff 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -207,8 +207,8 @@ static void glInit(Renderer* renderer, DataWin* dataWin) { GLint UniformCount; glGetProgramiv(gl->GMLShaders[i], GL_ACTIVE_UNIFORMS, &UniformCount); + //I know it looks baddd.... butttt it works gl->Sampler2DLookUpTable[i] = safeMalloc(UniformCount * sizeof(int32_t)); - //bool FoundBaseTexture = false; GLint LongestUniformName = 0; glGetProgramiv(gl->GMLShaders[i], GL_ACTIVE_UNIFORM_MAX_LENGTH, &LongestUniformName); char *UniformName = safeMalloc(LongestUniformName); @@ -218,28 +218,20 @@ static void glInit(Renderer* renderer, DataWin* dataWin) { GLint size = 0; GLenum type = 0; glGetActiveUniform(gl->GMLShaders[i], b, LongestUniformName, &length, &size, &type, UniformName); - //glGetUniformIndices + gl->Sampler2DLookUpTable[i][b] = -1; if (type == GL_SAMPLER_2D) { - //if (UniformName == "gm_BaseTexture") { - // FoundBaseTexture = true; - //} GLint location = glGetUniformLocation(gl->GMLShaders[i], UniformName); glUseProgram(gl->GMLShaders[i]); glUniform1i(location, SamplerIndex); SamplerIndex += 1; gl->Sampler2DLookUpTable[i][b] = SamplerIndex; - //printf("GL: %s Should Be Texture Stage %d at %d\n", UniformName, SamplerIndex, location); - //printf("GL: Uniform Index %d is Sampler2D Index %d %s\n", b, gl->Sampler2DLookUpTable[i][b], UniformName); } - //printf("GL: Uniform Index %d is Sampler2D Index %d\n", b, gl->Sampler2DLookUpTable[i][b]); + } - //if (FoundBaseTexture == false) { - // printf("GL: gm_BaseTexture Not Used In Shader %s \n", shdr->name); - //} + free(UniformName); - //fprintf(stderr, "GL: Shader Uniform Count %u\n", UniformCount); } diff --git a/src/runner.c b/src/runner.c index faddb4f2..839c2559 100644 --- a/src/runner.c +++ b/src/runner.c @@ -2112,7 +2112,7 @@ void Runner_initFirstRoom(Runner* runner) { repeat(dataWin->glob.count, i) { int32_t codeId = dataWin->glob.codeIds[i]; if (codeId >= 0 && dataWin->code.count > (uint32_t) codeId) { - //fprintf(stderr, "Runner: Executing global init script: %s\n", dataWin->code.entries[codeId].name); + fprintf(stderr, "Runner: Executing global init script: %s\n", dataWin->code.entries[codeId].name); RValue result = VM_executeCode(runner->vmContext, codeId); RValue_free(&result); } From e05a8f166ad924ba68b1481107e1d433edf2d9e3 Mon Sep 17 00:00:00 2001 From: Classic0306 <190026317+Classic0306@users.noreply.github.com> Date: Mon, 25 May 2026 22:16:49 +0200 Subject: [PATCH 05/11] boring commit to rebaseeeeee --- src/gl/gl_renderer.c | 24 ++++++++++++++-- src/gl/gl_renderer.h | 1 + src/renderer.h | 2 ++ src/vm_builtins.c | 65 ++++++++++++++++++++++++++++++++++++++------ 4 files changed, 81 insertions(+), 11 deletions(-) diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index a00fefff..7e724ee3 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -187,6 +187,7 @@ static void glInit(Renderer* renderer, DataWin* dataWin) { glDeleteShader(vertShader); glDeleteShader(fragShader); //yeah find the way to get the shaders here!!! + gl->GMLShaderCompiled = safeMalloc(dataWin->shdr.count * sizeof(bool)); fprintf(stderr, "GL: %u Shaders Found\n", dataWin->shdr.count); for (uint32_t i = 0; dataWin->shdr.count > i; i++) { Shader* shdr = &dataWin->shdr.shaders[i]; @@ -200,8 +201,12 @@ static void glInit(Renderer* renderer, DataWin* dataWin) { gl->GMLShaders = safeRealloc(gl->GMLShaders, gl->GMLShaderCount * sizeof(GLuint)); gl->Sampler2DLookUpTable = safeRealloc(gl->Sampler2DLookUpTable, gl->GMLShaderCount * sizeof(int32_t*)); fprintf(stderr, "GL: Linking %s\n", shdr->name); + gl->GMLShaderCompiled[i] = false; + bool success = true; gl->GMLShaders[i] = linkProgramCompat(vertShaderT, fragShaderT); - + if (success) { + gl->GMLShaderCompiled[i] = true; + } //Texture Set Stage BS has to be done bruh :( int32_t SamplerIndex = 0; GLint UniformCount; @@ -1936,15 +1941,28 @@ static void glTextureSetStage(Renderer* renderer, int32_t slot, int32_t texID) { static float glTextureGetTexelWidth(Renderer* renderer, int16_t pageId) { GLRenderer* gl = (GLRenderer*) renderer; - ensureTextureLoaded(gl, (uint32_t) pageId); + if (!ensureTextureLoaded(gl, (uint32_t) pageId)) return 1.0; return (1.0 / (float) gl->textureWidths[pageId]); } static float glTextureGetTexelHeight(Renderer* renderer, int16_t pageId) { GLRenderer* gl = (GLRenderer*) renderer; - ensureTextureLoaded(gl, (uint32_t) pageId); + if (!ensureTextureLoaded(gl, (uint32_t) pageId)) return 1.0; return (1.0 / (float) gl->textureHeights[pageId]); } +/* +static float glTextureGetWidth(Renderer* renderer, int16_t pageId) { + GLRenderer* gl = (GLRenderer*) renderer; + if (!ensureTextureLoaded(gl, (uint32_t) pageId)) return 0.0; + return (float) gl->textureWidths[pageId]; +} + +static float glTextureGetHeight(Renderer* renderer, int16_t pageId) { + GLRenderer* gl = (GLRenderer*) renderer; + if (!ensureTextureLoaded(gl, (uint32_t) pageId)) return 0.0; + return (float) gl->textureHeights[pageId]; +} +*/ // ===[ Vtable ]=== static RendererVtable glVtable; diff --git a/src/gl/gl_renderer.h b/src/gl/gl_renderer.h index 0112a46c..a3df45e4 100644 --- a/src/gl/gl_renderer.h +++ b/src/gl/gl_renderer.h @@ -25,6 +25,7 @@ typedef struct { GLint uAlphaTestRef; GLint uFogColor; GLuint* GMLShaders; + bool* GMLShaderCompiled; uint32_t GMLShaderCount; int32_t** Sampler2DLookUpTable; GLint** Sampler2DLocationLookUpTable; diff --git a/src/renderer.h b/src/renderer.h index 702e130f..09031c62 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -128,6 +128,8 @@ typedef struct { int32_t (*spriteGetTexture)(Renderer* renderer, int32_t tpagIndex); float (*textureGetTexelWidth)(Renderer* renderer, int16_t pageId); float (*textureGetTexelHeight)(Renderer* renderer, int16_t pageId); + float (*textureGetWidth)(Renderer* renderer, int16_t pageId); + float (*textureGetHeight)(Renderer* renderer, int16_t pageId); void (*textureSetStage)(Renderer* renderer, int32_t slot, int32_t texID); } RendererVtable; diff --git a/src/vm_builtins.c b/src/vm_builtins.c index acd4eb89..a30ae262 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -13036,9 +13036,11 @@ static RValue builtin_shader_set_uniformF(VMContext* ctx, MAYBE_UNUSED RValue* a } static RValue builtin_sprite_get_uvs(VMContext* ctx, MAYBE_UNUSED RValue* args, MAYBE_UNUSED int32_t argCount) { - int32_t spriteIndex = (int32_t) RValue_toReal(args[0]); - int32_t subimg = RValue_toInt32(args[1]); + int32_t subimg = RValue_toInt32(args[1]); + if (0 > subimg && ctx->currentInstance != nullptr) { + subimg = (int32_t) ctx->currentInstance->imageIndex; + } int32_t TpagIndex = Renderer_resolveTPAGIndex(ctx->dataWin, spriteIndex, subimg); //I think default texture page size is 2048x2048? float DivW = 0.00048828125; //1.0/2048.0 @@ -13053,7 +13055,10 @@ static RValue builtin_sprite_get_uvs(VMContext* ctx, MAYBE_UNUSED RValue* args, float top = (float) ctx->dataWin->tpag.items[TpagIndex].sourceY * DivH; float right = (float) left + (ctx->dataWin->tpag.items[TpagIndex].sourceWidth * DivW); float bottom = (float) top + (ctx->dataWin->tpag.items[TpagIndex].sourceHeight * DivH); - + float trimmedLeft = (float) ctx->dataWin->tpag.items[TpagIndex].targetX; + float trimmedTop = (float) ctx->dataWin->tpag.items[TpagIndex].targetY; + float NormWidthS = (float) ctx->dataWin->tpag.items[TpagIndex].sourceWidth / (float) ctx->dataWin->tpag.items[TpagIndex].boundingWidth; + float NormHeightS = (float) ctx->dataWin->tpag.items[TpagIndex].sourceHeight / (float) ctx->dataWin->tpag.items[TpagIndex].boundingHeight; GMLArray* out = GMLArray_create(8); @@ -13061,22 +13066,65 @@ static RValue builtin_sprite_get_uvs(VMContext* ctx, MAYBE_UNUSED RValue* args, *GMLArray_slot(out, 1) = RValue_makeReal(top); *GMLArray_slot(out, 2) = RValue_makeReal(right); *GMLArray_slot(out, 3) = RValue_makeReal(bottom); - *GMLArray_slot(out, 4) = RValue_makeReal(0.0); - *GMLArray_slot(out, 5) = RValue_makeReal(0.0); - *GMLArray_slot(out, 6) = RValue_makeReal(0.0); - *GMLArray_slot(out, 7) = RValue_makeReal(0.0); + *GMLArray_slot(out, 4) = RValue_makeReal(trimmedLeft); + *GMLArray_slot(out, 5) = RValue_makeReal(trimmedTop); + *GMLArray_slot(out, 6) = RValue_makeReal(NormWidthS); + *GMLArray_slot(out, 7) = RValue_makeReal(NormHeightS); return RValue_makeArray(out); } static RValue builtin_sprite_get_texture(VMContext* ctx, MAYBE_UNUSED RValue* args, MAYBE_UNUSED int32_t argCount) { int32_t spriteIndex = (int32_t) RValue_toReal(args[0]); - int32_t subimg = RValue_toInt32(args[1]); + int32_t subimg = RValue_toInt32(args[1]); + if (0 > subimg && ctx->currentInstance != nullptr) { + subimg = (int32_t) ctx->currentInstance->imageIndex; + } int32_t TpagIndex = Renderer_resolveTPAGIndex(ctx->dataWin, spriteIndex, subimg); return RValue_makeInt32(ctx->runner->renderer->vtable->spriteGetTexture(ctx->runner->renderer, TpagIndex)); } +static RValue builtin_font_get_uvs(VMContext* ctx, MAYBE_UNUSED RValue* args, MAYBE_UNUSED int32_t argCount) { + int32_t fontIndex = (int32_t) RValue_toReal(args[0]); + + //if (0 > fontIndex || ctx->dataWin->font.count <= (uint32_t) fontIndex) return; + + Font* font = &ctx->runner->dataWin->font.fonts[fontIndex]; + + + int32_t TpagIndex = font->tpagIndex; + //I think default texture page size is 2048x2048? + float DivW = 0.00048828125; //1.0/2048.0 + float DivH = 0.00048828125; //1.0/2048.0 + + if (ctx->runner->renderer->vtable->textureGetTexelWidth != nullptr) { + DivW = ctx->runner->renderer->vtable->textureGetTexelWidth(ctx->runner->renderer, ctx->dataWin->tpag.items[TpagIndex].texturePageId); + DivH = ctx->runner->renderer->vtable->textureGetTexelHeight(ctx->runner->renderer, ctx->dataWin->tpag.items[TpagIndex].texturePageId); + } + + float left = (float) ctx->dataWin->tpag.items[TpagIndex].sourceX * DivW; + float top = (float) ctx->dataWin->tpag.items[TpagIndex].sourceY * DivH; + float right = (float) left + (ctx->dataWin->tpag.items[TpagIndex].sourceWidth * DivW); + float bottom = (float) top + (ctx->dataWin->tpag.items[TpagIndex].sourceHeight * DivH); + + GMLArray* out = GMLArray_create(4); + *GMLArray_slot(out, 0) = RValue_makeReal(left); + *GMLArray_slot(out, 1) = RValue_makeReal(top); + *GMLArray_slot(out, 2) = RValue_makeReal(right); + *GMLArray_slot(out, 3) = RValue_makeReal(bottom); + return RValue_makeArray(out); +} + +static RValue builtin_font_get_texture(VMContext* ctx, MAYBE_UNUSED RValue* args, MAYBE_UNUSED int32_t argCount) { + //see if it works + int32_t fontIndex = (int32_t) RValue_toReal(args[0]); + Font* font = &ctx->runner->dataWin->font.fonts[fontIndex]; + int32_t TpagIndex = font->tpagIndex; + + return RValue_makeInt32(ctx->runner->renderer->vtable->spriteGetTexture(ctx->runner->renderer, TpagIndex)); +} + static RValue builtin_texture_get_texel_width(VMContext* ctx, MAYBE_UNUSED RValue* args, MAYBE_UNUSED int32_t argCount) { int16_t TpagIndex = (int16_t) RValue_toReal(args[0]); @@ -13961,6 +14009,7 @@ void VMBuiltins_registerAll(VMContext* ctx) { VM_registerBuiltin(ctx, "shader_set_uniform_f", builtin_shader_set_uniformF); VM_registerBuiltin(ctx, "sprite_get_uvs", builtin_sprite_get_uvs); VM_registerBuiltin(ctx, "sprite_get_texture", builtin_sprite_get_texture); + VM_registerBuiltin(ctx, "font_get_uvs", builtin_font_get_uvs); VM_registerBuiltin(ctx, "texture_get_texel_width", builtin_texture_get_texel_width); VM_registerBuiltin(ctx, "texture_get_texel_height", builtin_texture_get_texel_height); VM_registerBuiltin(ctx, "texture_set_stage", builtin_texture_set_stage); From affa64b7f25266a02d0aadc210c3499bded34a5a Mon Sep 17 00:00:00 2001 From: Classic0306 <190026317+Classic0306@users.noreply.github.com> Date: Wed, 27 May 2026 17:27:25 +0200 Subject: [PATCH 06/11] I hope this is good enough for a PR --- src/gl/gl_renderer.c | 87 +++++++++++------------------- src/gl_legacy/gl_legacy_renderer.c | 51 +++++++----------- src/renderer.h | 2 - 3 files changed, 50 insertions(+), 90 deletions(-) diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index 7e724ee3..26bae380 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -103,7 +103,7 @@ static GLuint linkProgram(GLuint vertShader, GLuint fragShader) { return program; } -static GLuint linkProgramCompat(GLuint vertShader, GLuint fragShader) { +static GLuint linkProgramCompat(GLuint vertShader, GLuint fragShader, bool *success2) { GLuint program = glCreateProgram(); glAttachShader(program, vertShader); glAttachShader(program, fragShader); @@ -121,6 +121,8 @@ static GLuint linkProgramCompat(GLuint vertShader, GLuint fragShader) { glGetProgramInfoLog(program, sizeof(infoLog), nullptr, infoLog); fprintf(stderr, "GL: Shader linking failed: %s\n", infoLog); abort(); + } else { + *success2 = true; } return program; } @@ -180,7 +182,7 @@ static void glInit(Renderer* renderer, DataWin* dataWin) { GLRenderer* gl = (GLRenderer*) renderer; renderer->dataWin = dataWin; - //compile em shaders! + //compile shaders GLuint vertShader = compileShader(GL_VERTEX_SHADER, vertexShaderSource); GLuint fragShader = compileShader(GL_FRAGMENT_SHADER, fragmentShaderSource); gl->shaderProgram = linkProgram(vertShader, fragShader); @@ -201,38 +203,43 @@ static void glInit(Renderer* renderer, DataWin* dataWin) { gl->GMLShaders = safeRealloc(gl->GMLShaders, gl->GMLShaderCount * sizeof(GLuint)); gl->Sampler2DLookUpTable = safeRealloc(gl->Sampler2DLookUpTable, gl->GMLShaderCount * sizeof(int32_t*)); fprintf(stderr, "GL: Linking %s\n", shdr->name); - gl->GMLShaderCompiled[i] = false; - bool success = true; - gl->GMLShaders[i] = linkProgramCompat(vertShaderT, fragShaderT); - if (success) { - gl->GMLShaderCompiled[i] = true; - } + bool success = false; + gl->GMLShaders[i] = linkProgramCompat(vertShaderT, fragShaderT, &success); + gl->GMLShaderCompiled[i] = success; + glDeleteShader(vertShaderT); + glDeleteShader(fragShaderT); //Texture Set Stage BS has to be done bruh :( int32_t SamplerIndex = 0; GLint UniformCount; glGetProgramiv(gl->GMLShaders[i], GL_ACTIVE_UNIFORMS, &UniformCount); - + //I know it looks baddd.... butttt it works gl->Sampler2DLookUpTable[i] = safeMalloc(UniformCount * sizeof(int32_t)); GLint LongestUniformName = 0; glGetProgramiv(gl->GMLShaders[i], GL_ACTIVE_UNIFORM_MAX_LENGTH, &LongestUniformName); - char *UniformName = safeMalloc(LongestUniformName); - + char *UniformName = safeMalloc(LongestUniformName+1); + GLint gm_BaseTexture = glGetUniformLocation(gl->GMLShaders[i], "gm_BaseTexture"); + if (gm_BaseTexture == -1) //I assume "slot" 1 is always gm_BaseTexture, do tell me if I am wrong + { + SamplerIndex = 1; + fprintf(stderr, "GL: %s does not use gm_BaseTexture\n", shdr->name); + } for (GLint b = 0; b < UniformCount; b++) { + GLsizei length = 0; GLint size = 0; GLenum type = 0; glGetActiveUniform(gl->GMLShaders[i], b, LongestUniformName, &length, &size, &type, UniformName); - - gl->Sampler2DLookUpTable[i][b] = -1; - if (type == GL_SAMPLER_2D) - { - GLint location = glGetUniformLocation(gl->GMLShaders[i], UniformName); - glUseProgram(gl->GMLShaders[i]); - glUniform1i(location, SamplerIndex); - SamplerIndex += 1; - gl->Sampler2DLookUpTable[i][b] = SamplerIndex; - } + + gl->Sampler2DLookUpTable[i][b] = -1; + if (type == GL_SAMPLER_2D) + { + GLint location = glGetUniformLocation(gl->GMLShaders[i], UniformName); + glUseProgram(gl->GMLShaders[i]); + glUniform1i(location, SamplerIndex); + SamplerIndex += 1; + gl->Sampler2DLookUpTable[i][b] = SamplerIndex; + } } @@ -390,7 +397,6 @@ static void glGpuSetShader(Renderer* renderer, int32_t ShaderIndex) { glUniform1i(gm_FogColour, gl->fogColor); } - if (gm_AlphaTestEnabled != -1) { glUniform1i(gm_AlphaTestEnabled, gl->alphaTestEnable); } @@ -1638,32 +1644,12 @@ static int32_t glCreateSpriteFromSurface(Renderer* renderer, int32_t surfaceID, flushBatch(gl); glBindFramebuffer(GL_READ_FRAMEBUFFER, gl->surfaces[surfaceID]); - // OpenGL Y is bottom-up, GML Y is top-down; flip Y to the GL coordinate. - int32_t glY = gl->surfaceHeight[surfaceID] - y - h; - //if (surfaceID != APPLICATION_SURFACE_ID) { - glY = y; - //} uint8_t* pixels = safeMalloc((size_t) w * (size_t) h * 4); if (pixels == nullptr) return -1; + glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - glReadPixels(x, glY, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - /* - if (surfaceID == APPLICATION_SURFACE_ID) { - // Flip vertically (OpenGL reads bottom-to-top) - size_t rowBytes = (size_t) w * 4; - uint8_t* rowTemp = safeMalloc(rowBytes); - repeat(h / 2, row) { - uint8_t* top = pixels + row * rowBytes; - uint8_t* bot = pixels + (h - 1 - row) * rowBytes; - memcpy(rowTemp, top, rowBytes); - memcpy(top, bot, rowBytes); - memcpy(bot, rowTemp, rowBytes); - } - free(rowTemp); - } - */ // Create a new GL texture from the captured pixels GLuint newTexId; glGenTextures(1, &newTexId); @@ -1932,6 +1918,9 @@ static void glTextureSetStage(Renderer* renderer, int32_t slot, int32_t texID) { fprintf(stderr, "GL: SOMETHING WRONK\n"); return; } + if (slot == 0) { + gl->currentTextureId = texID; + } //return; glActiveTexture(GL_TEXTURE0 + (slot-1)); glBindTexture(GL_TEXTURE_2D, texID); @@ -1950,19 +1939,7 @@ static float glTextureGetTexelHeight(Renderer* renderer, int16_t pageId) { if (!ensureTextureLoaded(gl, (uint32_t) pageId)) return 1.0; return (1.0 / (float) gl->textureHeights[pageId]); } -/* -static float glTextureGetWidth(Renderer* renderer, int16_t pageId) { - GLRenderer* gl = (GLRenderer*) renderer; - if (!ensureTextureLoaded(gl, (uint32_t) pageId)) return 0.0; - return (float) gl->textureWidths[pageId]; -} -static float glTextureGetHeight(Renderer* renderer, int16_t pageId) { - GLRenderer* gl = (GLRenderer*) renderer; - if (!ensureTextureLoaded(gl, (uint32_t) pageId)) return 0.0; - return (float) gl->textureHeights[pageId]; -} -*/ // ===[ Vtable ]=== static RendererVtable glVtable; diff --git a/src/gl_legacy/gl_legacy_renderer.c b/src/gl_legacy/gl_legacy_renderer.c index 0968cee8..105afc1d 100644 --- a/src/gl_legacy/gl_legacy_renderer.c +++ b/src/gl_legacy/gl_legacy_renderer.c @@ -280,8 +280,8 @@ bool GLLegacyRenderer_ensureTextureLoaded(GLLegacyRenderer* gl, uint32_t pageId) // Nearest is mandatory for index textures, bilinear would interpolate palette indices into nonsense colors. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); free(pixels); #else @@ -302,8 +302,8 @@ bool GLLegacyRenderer_ensureTextureLoaded(GLLegacyRenderer* gl, uint32_t pageId) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); free(pixels); #endif @@ -1218,37 +1218,22 @@ static int32_t glCreateSpriteFromSurface(Renderer* renderer, int32_t surfaceID, if (gl->surfaces[surfaceID] == 0) return -1; glBindFramebuffer(GL_READ_FRAMEBUFFER, gl->surfaces[surfaceID]); - int32_t srcHeight = gl->surfaceHeight[surfaceID]; uint8_t* pixels = safeMalloc((size_t) w * (size_t) h * 4); if (pixels == nullptr) return -1; - // OpenGL Y is bottom-up, GML Y is top-down, so flip the Y coordinate - int32_t glY = srcHeight - y - h; - glReadPixels(x, glY, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - - // Flip vertically (OpenGL reads bottom-to-top) - size_t rowBytes = (size_t) w * 4; - uint8_t* rowTemp = safeMalloc(rowBytes); - repeat(h / 2, row) { - uint8_t* top = pixels + row * rowBytes; - uint8_t* bot = pixels + (h - 1 - row) * rowBytes; - memcpy(rowTemp, top, rowBytes); - memcpy(top, bot, rowBytes); - memcpy(bot, rowTemp, rowBytes); - } - free(rowTemp); + glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels); // Create a new GL texture from the captured pixels GLuint newTexId; glGenTextures(1, &newTexId); glBindTexture(GL_TEXTURE_2D, newTexId); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, smooth ? GL_LINEAR : GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, smooth ? GL_LINEAR : GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); free(pixels); @@ -1390,8 +1375,8 @@ static int32_t glLegacyCreateSurface(Renderer* renderer, int32_t width, int32_t glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glBindFramebuffer(GL_FRAMEBUFFER, gl->surfaces[surfaceIndex]); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gl->surfaceTexture[surfaceIndex], 0); @@ -1463,8 +1448,8 @@ static void glLegacySurfaceResize(Renderer* renderer, int32_t surfaceId, int32_t glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glBindFramebuffer(GL_FRAMEBUFFER, gl->surfaces[surfaceId]); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gl->surfaceTexture[surfaceId], 0); @@ -1515,7 +1500,7 @@ static bool glLegacySetRenderTarget(Renderer* renderer, int32_t surfaceId) { Matrix4f projection; Matrix4f_identity(&projection); - Matrix4f_ortho(&projection, 0.0f, (float) w, (float) h, 0.0f, -1.0f, 1.0f); + Matrix4f_ortho(&projection, 0.0f, (float) w, 0.0f, (float) h, -1.0f, 1.0f); glMatrixMode(GL_PROJECTION); glLoadMatrixf(projection.m); glMatrixMode(GL_MODELVIEW); @@ -1547,11 +1532,11 @@ static void glLegacyDrawSurface(Renderer* renderer, int32_t surfaceId, int32_t s float u0 = (float) srcLeft / (float) texW; float u1 = (float) (srcLeft + srcWidth) / (float) texW; #ifndef PLATFORM_PS3 - float v0 = 1.0f - (float) srcTop / (float) texH; - float v1 = 1.0f - (float) (srcTop + srcHeight) / (float) texH; + float v0 = (float) srcTop / (float) texH; + float v1 = (float) (srcTop + srcHeight) / (float) texH; #else - float v1 = 1.0f - (float) srcTop / (float) texH; - float v0 = 1.0f - (float) (srcTop + srcHeight) / (float) texH; + float v1 = (float) srcTop / (float) texH; + float v0 = (float) (srcTop + srcHeight) / (float) texH; #endif float r = (float) BGR_R(color) / 255.0f; diff --git a/src/renderer.h b/src/renderer.h index 09031c62..702e130f 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -128,8 +128,6 @@ typedef struct { int32_t (*spriteGetTexture)(Renderer* renderer, int32_t tpagIndex); float (*textureGetTexelWidth)(Renderer* renderer, int16_t pageId); float (*textureGetTexelHeight)(Renderer* renderer, int16_t pageId); - float (*textureGetWidth)(Renderer* renderer, int16_t pageId); - float (*textureGetHeight)(Renderer* renderer, int16_t pageId); void (*textureSetStage)(Renderer* renderer, int32_t slot, int32_t texID); } RendererVtable; From e550250a373d1b7ead0285ead4fe1490545c6c94 Mon Sep 17 00:00:00 2001 From: Classic0306 <190026317+Classic0306@users.noreply.github.com> Date: Thu, 4 Jun 2026 17:51:53 +0200 Subject: [PATCH 07/11] fix get texel width/height and other things I ain't bothered to name here --- src/gl/gl_renderer.c | 165 ++++++++++++++++++++++++------------------- src/gl/gl_renderer.h | 1 + src/renderer.h | 4 ++ src/vm_builtins.c | 46 +++++++++--- 4 files changed, 136 insertions(+), 80 deletions(-) diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index 26bae380..3dcb8ea5 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -40,8 +40,8 @@ static const char* vertexShaderSource = GLSL_VERSION_DIRECTIVE GLSL_VERTEX_PRECISION "layout(location = 0) in vec2 aPos;\n" - "layout(location = 1) in vec2 aTexCoord;\n" - "layout(location = 2) in vec4 aColor;\n" + "layout(location = 1) in vec4 aColor;\n" + "layout(location = 2) in vec2 aTexCoord;\n" "uniform mat4 uProjection;\n" "out vec2 vTexCoord;\n" "out vec4 vColor;\n" @@ -57,12 +57,16 @@ static const char* fragmentShaderSource = "in vec2 vTexCoord;\n" "in vec4 vColor;\n" "uniform sampler2D uTexture;\n" - "uniform float uAlphaTestRef;\n" // negative = disabled + "uniform float uAlphaTestRef;\n" + "uniform bool uAlphaTestEnabled;\n" "uniform vec4 uFogColor;\n" // rgb = fog color, a = enable flag (0 or 1) "out vec4 fragColor;\n" "void main() {\n" " vec4 c = texture(uTexture, vTexCoord) * vColor;\n" - " if (uAlphaTestRef >= c.a) discard;\n" + " if (uAlphaTestEnabled)" + " {" + " if (uAlphaTestRef >= c.a) discard;\n" + " }" " c.rgb = mix(c.rgb, uFogColor.rgb, uFogColor.a);\n" " fragColor = c;\n" "}\n"; @@ -103,15 +107,16 @@ static GLuint linkProgram(GLuint vertShader, GLuint fragShader) { return program; } -static GLuint linkProgramCompat(GLuint vertShader, GLuint fragShader, bool *success2) { +static GLuint linkProgramCompat(GLuint vertShader, GLuint fragShader, bool *success2, Shader *shdr) { GLuint program = glCreateProgram(); glAttachShader(program, vertShader); glAttachShader(program, fragShader); - glBindAttribLocation(program, 0, "in_Position"); - glBindAttribLocation(program, 1, "in_TexCoord"); - glBindAttribLocation(program, 2, "in_Colour"); - + uint32_t AttributeCount = shdr->vertexAttributeCount; + for (uint32_t i = 0; AttributeCount > i; i++) { + glBindAttribLocation(program, i, shdr->vertexAttributes[i]); + } + glLinkProgram(program); GLint success; @@ -119,10 +124,11 @@ static GLuint linkProgramCompat(GLuint vertShader, GLuint fragShader, bool *succ if (!success) { char infoLog[512]; glGetProgramInfoLog(program, sizeof(infoLog), nullptr, infoLog); - fprintf(stderr, "GL: Shader linking failed: %s\n", infoLog); + fprintf(stderr, "GL: %s Failed To Link: %s\n", shdr->name, infoLog); abort(); } else { *success2 = true; + fprintf(stderr, "GL: %s Linked!\n", shdr->name); } return program; } @@ -193,8 +199,6 @@ static void glInit(Renderer* renderer, DataWin* dataWin) { fprintf(stderr, "GL: %u Shaders Found\n", dataWin->shdr.count); for (uint32_t i = 0; dataWin->shdr.count > i; i++) { Shader* shdr = &dataWin->shdr.shaders[i]; - //fprintf(stderr, "GL: Shader %u %s Type %u\n", i, shdr->name, shdr->type); - //GLuint* GMLShaders; fprintf(stderr, "GL: Compiling %s Vertex Shader\n", shdr->name); GLuint vertShaderT = compileShader(GL_VERTEX_SHADER, shdr->glsl_Vertex); fprintf(stderr, "GL: Compiling %s Fragment Shader\n", shdr->name); @@ -202,9 +206,8 @@ static void glInit(Renderer* renderer, DataWin* dataWin) { gl->GMLShaderCount++; gl->GMLShaders = safeRealloc(gl->GMLShaders, gl->GMLShaderCount * sizeof(GLuint)); gl->Sampler2DLookUpTable = safeRealloc(gl->Sampler2DLookUpTable, gl->GMLShaderCount * sizeof(int32_t*)); - fprintf(stderr, "GL: Linking %s\n", shdr->name); - bool success = false; - gl->GMLShaders[i] = linkProgramCompat(vertShaderT, fragShaderT, &success); + bool success; + gl->GMLShaders[i] = linkProgramCompat(vertShaderT, fragShaderT, &success, shdr); gl->GMLShaderCompiled[i] = success; glDeleteShader(vertShaderT); glDeleteShader(fragShaderT); @@ -218,12 +221,7 @@ static void glInit(Renderer* renderer, DataWin* dataWin) { GLint LongestUniformName = 0; glGetProgramiv(gl->GMLShaders[i], GL_ACTIVE_UNIFORM_MAX_LENGTH, &LongestUniformName); char *UniformName = safeMalloc(LongestUniformName+1); - GLint gm_BaseTexture = glGetUniformLocation(gl->GMLShaders[i], "gm_BaseTexture"); - if (gm_BaseTexture == -1) //I assume "slot" 1 is always gm_BaseTexture, do tell me if I am wrong - { - SamplerIndex = 1; - fprintf(stderr, "GL: %s does not use gm_BaseTexture\n", shdr->name); - } + for (GLint b = 0; b < UniformCount; b++) { GLsizei length = 0; @@ -250,6 +248,7 @@ static void glInit(Renderer* renderer, DataWin* dataWin) { gl->uProjection = glGetUniformLocation(gl->shaderProgram, "uProjection"); gl->uTexture = glGetUniformLocation(gl->shaderProgram, "uTexture"); gl->uAlphaTestRef = glGetUniformLocation(gl->shaderProgram, "uAlphaTestRef"); + gl->uAlphaTestEnabled = glGetUniformLocation(gl->shaderProgram, "uAlphaTestEnabled"); gl->uFogColor = glGetUniformLocation(gl->shaderProgram, "uFogColor"); gl->alphaTestEnable = false; gl->alphaTestRef = 0.0f; @@ -295,9 +294,9 @@ static void glInit(Renderer* renderer, DataWin* dataWin) { int32_t stride = FLOATS_PER_VERTEX * (int32_t) sizeof(float); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, stride, (void*) 0); glEnableVertexAttribArray(0); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, stride, (void*) (2 * sizeof(float))); + glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, stride, (void*) (4 * sizeof(float))); glEnableVertexAttribArray(1); - glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, stride, (void*) (4 * sizeof(float))); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, stride, (void*) (2 * sizeof(float))); glEnableVertexAttribArray(2); glBindVertexArray(0); @@ -369,6 +368,8 @@ static void glGpuSetShader(Renderer* renderer, int32_t ShaderIndex) { GLint gm_FogColour = glGetUniformLocation(Shader, "gm_FogColour"); GLint gm_VS_FogEnabled = glGetUniformLocation(Shader, "gm_VS_FogEnabled"); + //Lights are for another time + GLint gm_AlphaTestEnabled = glGetUniformLocation(Shader, "gm_AlphaTestEnabled"); GLint gm_AlphaRefValue = glGetUniformLocation(Shader, "gm_AlphaRefValue"); @@ -407,6 +408,27 @@ static void glGpuSetShader(Renderer* renderer, int32_t ShaderIndex) { renderer->CurrentShader = ShaderIndex; } +static void glShaderSettingsRefresh(Renderer* renderer) { + GLRenderer* gl = (GLRenderer*) renderer; + flushBatch(gl); + if (renderer->CurrentShader != -1) { + glGpuSetShader(renderer, (int32_t) renderer->CurrentShader); + } else { + + float FogR = (float) BGR_R(gl->fogColor) / 255.0f; + float FoGG = (float) BGR_G(gl->fogColor) / 255.0f; + float FogB = (float) BGR_B(gl->fogColor) / 255.0f; + + glUseProgram(gl->shaderProgram); + glUniformMatrix4fv(gl->uProjection, 1, GL_FALSE, renderer->GML_Matrices[MATRIX_WORLD_VIEW_PROJECTION].m); + glUniform4f(gl->uFogColor, FogR, FoGG, FogB, gl->fogEnable ? 1.0f : 0.0f); + glUniform1f(gl->uAlphaTestRef, gl->alphaTestRef); + glUniform1i(gl->uAlphaTestEnabled, gl->alphaTestEnable); + glUniform1i(gl->uTexture, 0); + } +} + + static void glDestroy(Renderer* renderer) { GLRenderer* gl = (GLRenderer*) renderer; @@ -483,7 +505,7 @@ static void glBeginView(Renderer* renderer, int32_t viewX, int32_t viewY, int32_ glUseProgram(gl->shaderProgram); glUniformMatrix4fv(gl->uProjection, 1, GL_FALSE, projection.m); renderer->GML_Matrices[MATRIX_WORLD_VIEW_PROJECTION] = projection; - glUniform1i(gl->uTexture, 0); + glShaderSettingsRefresh(renderer); glActiveTexture(GL_TEXTURE0); glBindVertexArray(gl->vao); @@ -532,10 +554,8 @@ static void glBeginGUI(Renderer* renderer, int32_t guiW, int32_t guiH, int32_t p Matrix4f projection; Matrix4f_guiProjection(&projection, (float) guiW, (float) guiH, (float) portW, (float) portH); - glUseProgram(gl->shaderProgram); - glUniformMatrix4fv(gl->uProjection, 1, GL_FALSE, projection.m); renderer->GML_Matrices[MATRIX_WORLD_VIEW_PROJECTION] = projection; - glUniform1i(gl->uTexture, 0); + glShaderSettingsRefresh(renderer); glActiveTexture(GL_TEXTURE0); glBindVertexArray(gl->vao); @@ -1526,14 +1546,13 @@ static bool glSetRenderTarget(Renderer* renderer, int32_t surfaceId) { if (gl->surfaces[surfaceId] == 0) return false; glBindFramebuffer(GL_FRAMEBUFFER, gl->surfaces[surfaceId]); - glUseProgram(gl->shaderProgram); - glUniform1i(gl->uTexture, 0); + if (surfaceId == renderer->runner->applicationSurfaceId) { - glUniformMatrix4fv(gl->uProjection, 1, GL_FALSE, renderer->PreviousViewMatrix.m); glViewport(gl->base.CPortX, gl->base.CPortY, gl->base.CPortW, gl->base.CPortH); glEnable(GL_SCISSOR_TEST); renderer->GML_Matrices[MATRIX_WORLD_VIEW_PROJECTION] = renderer->PreviousViewMatrix; + glShaderSettingsRefresh(renderer); return true; } @@ -1541,18 +1560,11 @@ static bool glSetRenderTarget(Renderer* renderer, int32_t surfaceId) { Matrix4f projection; Matrix4f_identity(&projection); Matrix4f_ortho(&projection, 0.0f, (float) gl->surfaceWidth[surfaceId], 0.0f, (float) gl->surfaceHeight[surfaceId], -1.0f, 1.0f); - glUniformMatrix4fv(gl->uProjection, 1, GL_FALSE, projection.m); glViewport(0, 0, gl->surfaceWidth[surfaceId], gl->surfaceHeight[surfaceId]); glDisable(GL_SCISSOR_TEST); renderer->GML_Matrices[MATRIX_WORLD_VIEW_PROJECTION] = projection; - if (renderer->CurrentShader != -1) - { - glGpuSetShader(renderer, (int32_t) renderer->CurrentShader); - } else { - glUseProgram(gl->shaderProgram); - glUniform1i(gl->uTexture, 0); - glUniformMatrix4fv(gl->uProjection, 1, GL_FALSE, projection.m); - } + glShaderSettingsRefresh(renderer); + return true; } @@ -1766,8 +1778,7 @@ static void glGpuSetAlphaTestEnable(Renderer* renderer, bool enable) { if (gl->alphaTestEnable == enable) return; flushBatch(gl); gl->alphaTestEnable = enable; - glUseProgram(gl->shaderProgram); - glUniform1f(gl->uAlphaTestRef, enable ? gl->alphaTestRef : -1.0f); + glShaderSettingsRefresh(renderer); } static void glGpuSetAlphaTestRef(Renderer* renderer, uint8_t ref) { @@ -1776,10 +1787,7 @@ static void glGpuSetAlphaTestRef(Renderer* renderer, uint8_t ref) { if (gl->alphaTestRef == refF) return; flushBatch(gl); gl->alphaTestRef = refF; - if (gl->alphaTestEnable) { - glUseProgram(gl->shaderProgram); - glUniform1f(gl->uAlphaTestRef, refF); - } + glShaderSettingsRefresh(renderer); } static void glGpuSetColorWriteEnable(Renderer* renderer, bool red, bool green, bool blue, bool alpha) { @@ -1806,21 +1814,13 @@ static void glGpuSetFog(Renderer* renderer, bool enable, uint32_t color) { flushBatch(gl); gl->fogEnable = enable; gl->fogColor = color; - float r = (float) BGR_R(color) / 255.0f; - float g = (float) BGR_G(color) / 255.0f; - float b = (float) BGR_B(color) / 255.0f; - glUseProgram(gl->shaderProgram); - glUniform4f(gl->uFogColor, r, g, b, enable ? 1.0f : 0.0f); + glShaderSettingsRefresh(renderer); } static int32_t glShaderGetUniform(Renderer* renderer, int32_t shaderIndex, char* uniform) { GLRenderer* gl = (GLRenderer*) renderer; flushBatch(gl); - if (renderer->CurrentShader != -1) { - glUseProgram(gl->GMLShaders[renderer->CurrentShader]); //tf you mean this fixed the invalid location thing shouldn't GML code assume the same shader is still bound??? why was it even changed what the fu - } GLuint Shader = gl->GMLShaders[shaderIndex]; - //fprintf(stderr, "GL: Uniform Get Location %u\n", glGetUniformLocation(Shader, uniform)); return glGetUniformLocation(Shader, uniform); } @@ -1846,14 +1846,12 @@ static int32_t glShaderGetSamplerIndex(Renderer* renderer, int32_t shaderIndex, return gl->Sampler2DLookUpTable[shaderIndex][index]; } - static void glShaderSetUniformF(Renderer* renderer, int32_t handle, int32_t count, float value1, float value2, float value3, float value4) { GLRenderer* gl = (GLRenderer*) renderer; flushBatch(gl); int32_t RealCount = count; if (renderer->CurrentShader != -1) { GLuint Shader = gl->GMLShaders[renderer->CurrentShader]; - glUseProgram(Shader); //tf you mean this fixed the invalid location thing shouldn't GML code assume the same shader is still bound??? why was it even changed what the fu GLint UniformCount; glGetProgramiv(Shader, GL_ACTIVE_UNIFORMS, &UniformCount); @@ -1870,19 +1868,13 @@ static void glShaderSetUniformF(Renderer* renderer, int32_t handle, int32_t coun int32_t location = glGetUniformLocation(Shader, UniformName); if (location == handle) { - //fprintf(stderr, "GL: TF BRO IS RIGHT?\n"); if (type == GL_FLOAT) RealCount = 1; if (type == GL_FLOAT_VEC2) RealCount = 2; if (type == GL_FLOAT_VEC3) RealCount = 3; if (type == GL_FLOAT_VEC4) RealCount = 4; } - - } free(UniformName); - - - } if (RealCount == 1) { @@ -1905,7 +1897,6 @@ static int32_t glSpriteGetTexture(Renderer* renderer, int32_t tpagIndex) { if (!resolveSpriteTexture(gl, tpagIndex, &tpag, &texId, &texW, &texH)) return -1; return texId; - } static void glTextureSetStage(Renderer* renderer, int32_t slot, int32_t texID) { @@ -1915,29 +1906,59 @@ static void glTextureSetStage(Renderer* renderer, int32_t slot, int32_t texID) { return; } if (slot == -1) { - fprintf(stderr, "GL: SOMETHING WRONK\n"); + fprintf(stderr, "GL: Invalid Texture Stage\n"); return; } if (slot == 0) { gl->currentTextureId = texID; } - //return; + if (slot > MAX_TEXTURE_STAGES) { + fprintf(stderr, "GL: Texture Stage Higher Than Max\n"); + return; + } glActiveTexture(GL_TEXTURE0 + (slot-1)); glBindTexture(GL_TEXTURE_2D, texID); glActiveTexture(GL_TEXTURE0); } -static float glTextureGetTexelWidth(Renderer* renderer, int16_t pageId) { +static float glTextureGetTexelWidth(Renderer* renderer, int16_t texID) { GLRenderer* gl = (GLRenderer*) renderer; - if (!ensureTextureLoaded(gl, (uint32_t) pageId)) return 1.0; - return (1.0 / (float) gl->textureWidths[pageId]); + flushBatch(gl); + GLint width = 0; + GLint prev; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &prev); + glBindTexture(GL_TEXTURE_2D, texID); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width); + glBindTexture(GL_TEXTURE_2D, prev); + + if (width == 0) return 1.0; + return (1.0 / (float) width); } -static float glTextureGetTexelHeight(Renderer* renderer, int16_t pageId) { +static float glTextureGetTexelHeight(Renderer* renderer, int16_t texID) { GLRenderer* gl = (GLRenderer*) renderer; - if (!ensureTextureLoaded(gl, (uint32_t) pageId)) return 1.0; - return (1.0 / (float) gl->textureHeights[pageId]); + flushBatch(gl); + GLint height = 0; + GLint prev; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &prev); + glBindTexture(GL_TEXTURE_2D, texID); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height); + glBindTexture(GL_TEXTURE_2D, prev); + + if (height == 0) return 1.0; + return (1.0 / (float) height); +} + +static bool glShaderIsCompiled(Renderer* renderer, int32_t shaderID) { + GLRenderer* gl = (GLRenderer*) renderer; + DataWin* dw = gl->base.dataWin; + if (0 > shaderID || shaderID >= dw->shdr.count) return false; + return gl->GMLShaderCompiled[shaderID]; +} + +static bool glShadersSupported(Renderer* renderer) { + return true; } // ===[ Vtable ]=== @@ -2003,6 +2024,8 @@ Renderer* GLRenderer_create(void) { glVtable.textureGetTexelHeight = glTextureGetTexelHeight, glVtable.shaderGetSamplerIndex = glShaderGetSamplerIndex, glVtable.textureSetStage = glTextureSetStage, + glVtable.shaderIsCompiled = glShaderIsCompiled, + glVtable.shadersSupported = glShadersSupported, gl->base.drawColor = 0xFFFFFF; // white (BGR) gl->base.drawAlpha = 1.0f; diff --git a/src/gl/gl_renderer.h b/src/gl/gl_renderer.h index a3df45e4..5eabc199 100644 --- a/src/gl/gl_renderer.h +++ b/src/gl/gl_renderer.h @@ -24,6 +24,7 @@ typedef struct { GLint uTexture; GLint uAlphaTestRef; GLint uFogColor; + GLint uAlphaTestEnabled; GLuint* GMLShaders; bool* GMLShaderCompiled; uint32_t GMLShaderCount; diff --git a/src/renderer.h b/src/renderer.h index 702e130f..aa14cd71 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -37,6 +37,8 @@ #define MATRIX_WORLD_VIEW_PROJECTION 4 #define MATRICES_MAX 5 +#define MAX_VS_LIGHTS 8 + #define MAX_TEXTURE_STAGES 8 // Sentinel returned by ensureApplicationSurface on platforms that don't back the application_surface with a real entry in the renderer's surface table. @@ -129,6 +131,8 @@ typedef struct { float (*textureGetTexelWidth)(Renderer* renderer, int16_t pageId); float (*textureGetTexelHeight)(Renderer* renderer, int16_t pageId); void (*textureSetStage)(Renderer* renderer, int32_t slot, int32_t texID); + bool (*shaderIsCompiled)(Renderer* renderer, int32_t shader); + bool (*shadersSupported)(Renderer* renderer); } RendererVtable; // ===[ Renderer Base Struct ]=== diff --git a/src/vm_builtins.c b/src/vm_builtins.c index a30ae262..5c7aeab9 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -12971,7 +12971,32 @@ static RValue builtin_shader_current(VMContext* ctx, MAYBE_UNUSED RValue* args, return RValue_makeReal(-1); } +static RValue builtin_shader_is_compiled(VMContext* ctx, MAYBE_UNUSED RValue* args, MAYBE_UNUSED int32_t argCount) { + + int32_t ShaderID = (int32_t) RValue_toReal(args[0]); + if (ctx->runner->renderer->vtable->shaderIsCompiled != nullptr) { + return RValue_makeBool(ctx->runner->renderer->vtable->shaderIsCompiled(ctx->runner->renderer, ShaderID)); + } + + return RValue_makeBool(false); +} + +static RValue builtin_shader_get_name(VMContext* ctx, RValue* args, MAYBE_UNUSED int32_t argCount) { + int32_t shaderIndex = (int32_t) RValue_toReal(args[0]); + Shader* shdr = &ctx->dataWin->shdr.shaders[shaderIndex]; + if (0 > shaderIndex || (uint32_t) shaderIndex >= ctx->dataWin->shdr.count) return RValue_makeString(""); + const char* name = shdr->name; + return RValue_makeString(name != nullptr ? name : ""); +} + +static RValue builtin_shaders_are_supported(VMContext* ctx, MAYBE_UNUSED RValue* args, MAYBE_UNUSED int32_t argCount) { + + if (ctx->runner->renderer->vtable->shadersSupported != nullptr) { + return RValue_makeBool(ctx->runner->renderer->vtable->shadersSupported(ctx->runner->renderer)); + } + return RValue_makeBool(false); +} static RValue builtin_shader_get_uniform(VMContext* ctx, MAYBE_UNUSED RValue* args, MAYBE_UNUSED int32_t argCount) { @@ -13045,10 +13070,10 @@ static RValue builtin_sprite_get_uvs(VMContext* ctx, MAYBE_UNUSED RValue* args, //I think default texture page size is 2048x2048? float DivW = 0.00048828125; //1.0/2048.0 float DivH = 0.00048828125; //1.0/2048.0 - + if (ctx->runner->renderer->vtable->textureGetTexelWidth != nullptr) { - DivW = ctx->runner->renderer->vtable->textureGetTexelWidth(ctx->runner->renderer, ctx->dataWin->tpag.items[TpagIndex].texturePageId); - DivH = ctx->runner->renderer->vtable->textureGetTexelHeight(ctx->runner->renderer, ctx->dataWin->tpag.items[TpagIndex].texturePageId); + DivW = ctx->runner->renderer->vtable->textureGetTexelWidth(ctx->runner->renderer, ctx->runner->renderer->vtable->spriteGetTexture(ctx->runner->renderer, TpagIndex)); + DivH = ctx->runner->renderer->vtable->textureGetTexelHeight(ctx->runner->renderer, ctx->runner->renderer->vtable->spriteGetTexture(ctx->runner->renderer, TpagIndex)); } float left = (float) ctx->dataWin->tpag.items[TpagIndex].sourceX * DivW; @@ -13099,8 +13124,8 @@ static RValue builtin_font_get_uvs(VMContext* ctx, MAYBE_UNUSED RValue* args, MA float DivH = 0.00048828125; //1.0/2048.0 if (ctx->runner->renderer->vtable->textureGetTexelWidth != nullptr) { - DivW = ctx->runner->renderer->vtable->textureGetTexelWidth(ctx->runner->renderer, ctx->dataWin->tpag.items[TpagIndex].texturePageId); - DivH = ctx->runner->renderer->vtable->textureGetTexelHeight(ctx->runner->renderer, ctx->dataWin->tpag.items[TpagIndex].texturePageId); + DivW = ctx->runner->renderer->vtable->textureGetTexelWidth(ctx->runner->renderer, ctx->runner->renderer->vtable->spriteGetTexture(ctx->runner->renderer, TpagIndex)); + DivH = ctx->runner->renderer->vtable->textureGetTexelHeight(ctx->runner->renderer, ctx->runner->renderer->vtable->spriteGetTexture(ctx->runner->renderer, TpagIndex)); } float left = (float) ctx->dataWin->tpag.items[TpagIndex].sourceX * DivW; @@ -13127,14 +13152,14 @@ static RValue builtin_font_get_texture(VMContext* ctx, MAYBE_UNUSED RValue* args static RValue builtin_texture_get_texel_width(VMContext* ctx, MAYBE_UNUSED RValue* args, MAYBE_UNUSED int32_t argCount) { - int16_t TpagIndex = (int16_t) RValue_toReal(args[0]); - return RValue_makeReal(ctx->runner->renderer->vtable->textureGetTexelWidth(ctx->runner->renderer, ctx->dataWin->tpag.items[TpagIndex].texturePageId)); + int16_t texID = (int16_t) RValue_toReal(args[0]); + return RValue_makeReal(ctx->runner->renderer->vtable->textureGetTexelWidth(ctx->runner->renderer, texID)); } static RValue builtin_texture_get_texel_height(VMContext* ctx, MAYBE_UNUSED RValue* args, MAYBE_UNUSED int32_t argCount) { - int16_t TpagIndex = (int16_t) RValue_toReal(args[0]); - return RValue_makeReal(ctx->runner->renderer->vtable->textureGetTexelHeight(ctx->runner->renderer, ctx->dataWin->tpag.items[TpagIndex].texturePageId)); + int16_t texID = (int16_t) RValue_toReal(args[0]); + return RValue_makeReal(ctx->runner->renderer->vtable->textureGetTexelHeight(ctx->runner->renderer, texID)); } // ===[ REGISTRATION ]=== @@ -14004,6 +14029,9 @@ void VMBuiltins_registerAll(VMContext* ctx) { VM_registerBuiltin(ctx, "shader_set", builtin_shader_set); VM_registerBuiltin(ctx, "shader_reset", builtin_shader_reset); VM_registerBuiltin(ctx, "shader_current", builtin_shader_current); + VM_registerBuiltin(ctx, "shader_is_compiled", builtin_shader_is_compiled); + VM_registerBuiltin(ctx, "shader_get_name", builtin_shader_get_name); + VM_registerBuiltin(ctx, "shaders_are_supported", builtin_shaders_are_supported); VM_registerBuiltin(ctx, "shader_get_uniform", builtin_shader_get_uniform); VM_registerBuiltin(ctx, "shader_get_sampler_index", builtin_shader_get_sampler_index); VM_registerBuiltin(ctx, "shader_set_uniform_f", builtin_shader_set_uniformF); From 9906639bf460a9e55e23e250598a498e0e6baf21 Mon Sep 17 00:00:00 2001 From: Classic0306 <190026317+Classic0306@users.noreply.github.com> Date: Thu, 4 Jun 2026 20:10:13 +0200 Subject: [PATCH 08/11] rebase and resolve conflicts hopefully good enough --- src/gl/gl_renderer.c | 2 -- src/matrix_math.h | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index 3dcb8ea5..4872131f 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -502,8 +502,6 @@ static void glBeginView(Renderer* renderer, int32_t viewX, int32_t viewY, int32_ Matrix4f projection; Matrix4f_viewProjection(&projection, (float) viewX, (float) viewY, (float) viewW, (float) viewH, viewAngle); - glUseProgram(gl->shaderProgram); - glUniformMatrix4fv(gl->uProjection, 1, GL_FALSE, projection.m); renderer->GML_Matrices[MATRIX_WORLD_VIEW_PROJECTION] = projection; glShaderSettingsRefresh(renderer); glActiveTexture(GL_TEXTURE0); diff --git a/src/matrix_math.h b/src/matrix_math.h index 9c92bae8..451622f1 100644 --- a/src/matrix_math.h +++ b/src/matrix_math.h @@ -149,7 +149,7 @@ static inline Matrix4f* Matrix4f_setTransform2D(Matrix4f* dest, float x, float y // Y-down coordinate space, optionally rotated by angleDeg counter-clockwise about the view center (matching GML view_angle). static inline Matrix4f* Matrix4f_viewProjection(Matrix4f* dest, float left, float top, float width, float height, float angleDeg) { Matrix4f_identity(dest); - Matrix4f_ortho(dest, left, left + width, top + height, top, -1.0f, 1.0f); + Matrix4f_ortho(dest, left, left + width, top, top + height, -1.0f, 1.0f); if (angleDeg != 0.0f) { // Rotate the world opposite the camera, about the view center, to spin the camera by angleDeg. From 56a30c77331a4726011b8a043f291d49240b0a60 Mon Sep 17 00:00:00 2001 From: Classic0306 <190026317+Classic0306@users.noreply.github.com> Date: Fri, 5 Jun 2026 13:00:47 +0200 Subject: [PATCH 09/11] fix little mistakes with value types --- src/gl/gl_renderer.c | 15 ++++++++------- src/renderer.h | 8 ++++---- src/vm_builtins.c | 4 ++-- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index 4872131f..9acf1c64 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -1887,27 +1887,28 @@ static void glShaderSetUniformF(Renderer* renderer, int32_t handle, int32_t coun } -static int32_t glSpriteGetTexture(Renderer* renderer, int32_t tpagIndex) { +static uint32_t glSpriteGetTexture(Renderer* renderer, int32_t tpagIndex) { GLRenderer* gl = (GLRenderer*) renderer; TexturePageItem* tpag; GLuint texId; int32_t texW, texH; - if (!resolveSpriteTexture(gl, tpagIndex, &tpag, &texId, &texW, &texH)) return -1; + if (!resolveSpriteTexture(gl, tpagIndex, &tpag, &texId, &texW, &texH)) return 0; return texId; } -static void glTextureSetStage(Renderer* renderer, int32_t slot, int32_t texID) { +static void glTextureSetStage(Renderer* renderer, int32_t slot, uint32_t texID) { GLRenderer* gl = (GLRenderer*) renderer; flushBatch(gl); if (slot < 0) { + fprintf(stderr, "GL: Invalid Texture Stage\n"); return; } - if (slot == -1) { + if (slot == 0) { fprintf(stderr, "GL: Invalid Texture Stage\n"); return; } - if (slot == 0) { + if (slot == 1) { gl->currentTextureId = texID; } if (slot > MAX_TEXTURE_STAGES) { @@ -1920,7 +1921,7 @@ static void glTextureSetStage(Renderer* renderer, int32_t slot, int32_t texID) { } -static float glTextureGetTexelWidth(Renderer* renderer, int16_t texID) { +static float glTextureGetTexelWidth(Renderer* renderer, uint32_t texID) { GLRenderer* gl = (GLRenderer*) renderer; flushBatch(gl); GLint width = 0; @@ -1934,7 +1935,7 @@ static float glTextureGetTexelWidth(Renderer* renderer, int16_t texID) { return (1.0 / (float) width); } -static float glTextureGetTexelHeight(Renderer* renderer, int16_t texID) { +static float glTextureGetTexelHeight(Renderer* renderer, uint32_t texID) { GLRenderer* gl = (GLRenderer*) renderer; flushBatch(gl); GLint height = 0; diff --git a/src/renderer.h b/src/renderer.h index aa14cd71..cf417fd3 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -127,10 +127,10 @@ typedef struct { int32_t (*shaderGetUniform)(Renderer* renderer, int32_t shaderIndex, char* uniform); int32_t (*shaderGetSamplerIndex)(Renderer* renderer, int32_t shaderIndex, char* uniform); void (*shaderSetUniformF)(Renderer* renderer, int32_t handle, int32_t count, float value1, float value2, float value3, float value4); - int32_t (*spriteGetTexture)(Renderer* renderer, int32_t tpagIndex); - float (*textureGetTexelWidth)(Renderer* renderer, int16_t pageId); - float (*textureGetTexelHeight)(Renderer* renderer, int16_t pageId); - void (*textureSetStage)(Renderer* renderer, int32_t slot, int32_t texID); + uint32_t (*spriteGetTexture)(Renderer* renderer, int32_t tpagIndex); + float (*textureGetTexelWidth)(Renderer* renderer, uint32_t texID); + float (*textureGetTexelHeight)(Renderer* renderer, uint32_t texID); + void (*textureSetStage)(Renderer* renderer, int32_t slot, uint32_t texID); bool (*shaderIsCompiled)(Renderer* renderer, int32_t shader); bool (*shadersSupported)(Renderer* renderer); } RendererVtable; diff --git a/src/vm_builtins.c b/src/vm_builtins.c index 5c7aeab9..2a3a68d7 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -13152,13 +13152,13 @@ static RValue builtin_font_get_texture(VMContext* ctx, MAYBE_UNUSED RValue* args static RValue builtin_texture_get_texel_width(VMContext* ctx, MAYBE_UNUSED RValue* args, MAYBE_UNUSED int32_t argCount) { - int16_t texID = (int16_t) RValue_toReal(args[0]); + uint32_t texID = (uint32_t) RValue_toReal(args[0]); return RValue_makeReal(ctx->runner->renderer->vtable->textureGetTexelWidth(ctx->runner->renderer, texID)); } static RValue builtin_texture_get_texel_height(VMContext* ctx, MAYBE_UNUSED RValue* args, MAYBE_UNUSED int32_t argCount) { - int16_t texID = (int16_t) RValue_toReal(args[0]); + uint32_t texID = (uint32_t) RValue_toReal(args[0]); return RValue_makeReal(ctx->runner->renderer->vtable->textureGetTexelHeight(ctx->runner->renderer, texID)); } From d9bcd6fd2e37a40189cddf0d40662b50243a0601 Mon Sep 17 00:00:00 2001 From: Classic0306 <190026317+Classic0306@users.noreply.github.com> Date: Fri, 5 Jun 2026 15:36:19 +0200 Subject: [PATCH 10/11] fix wrong assumption about sampler indexes --- src/gl/gl_renderer.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index 9acf1c64..c3c517ce 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -235,8 +235,8 @@ static void glInit(Renderer* renderer, DataWin* dataWin) { GLint location = glGetUniformLocation(gl->GMLShaders[i], UniformName); glUseProgram(gl->GMLShaders[i]); glUniform1i(location, SamplerIndex); - SamplerIndex += 1; gl->Sampler2DLookUpTable[i][b] = SamplerIndex; + SamplerIndex += 1; } } @@ -1905,17 +1905,13 @@ static void glTextureSetStage(Renderer* renderer, int32_t slot, uint32_t texID) return; } if (slot == 0) { - fprintf(stderr, "GL: Invalid Texture Stage\n"); - return; - } - if (slot == 1) { gl->currentTextureId = texID; } if (slot > MAX_TEXTURE_STAGES) { fprintf(stderr, "GL: Texture Stage Higher Than Max\n"); return; } - glActiveTexture(GL_TEXTURE0 + (slot-1)); + glActiveTexture(GL_TEXTURE0 + slot); glBindTexture(GL_TEXTURE_2D, texID); glActiveTexture(GL_TEXTURE0); From 59d13da9133d4d5f20bdb7bc8f95114e29478ad1 Mon Sep 17 00:00:00 2001 From: Classic0306 <190026317+Classic0306@users.noreply.github.com> Date: Fri, 5 Jun 2026 20:30:19 +0200 Subject: [PATCH 11/11] hopefully fix texture stage bullshattery --- src/gl/gl_renderer.c | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index c3c517ce..5155c0cf 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -138,6 +138,29 @@ static GLuint linkProgramCompat(GLuint vertShader, GLuint fragShader, bool *succ static void flushBatch(GLRenderer* gl) { if (gl->batchCount == 0) return; + if (gl->base.CurrentShader != -1) { + GLuint Shader = gl->GMLShaders[gl->base.CurrentShader]; + + GLint UniformCount; + glGetProgramiv(Shader, GL_ACTIVE_UNIFORMS, &UniformCount); + + const GLchar* name = "gm_BaseTexture"; + GLuint index; + + glGetUniformIndices(Shader, 1, &name, &index); + + if (index != GL_INVALID_INDEX) + { + int32_t slot = gl->Sampler2DLookUpTable[gl->base.CurrentShader][index]; + glActiveTexture(GL_TEXTURE0 + slot); + glBindTexture(GL_TEXTURE_2D, gl->currentTextureId); + } + + } else { + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, gl->currentTextureId); + } + int32_t singleVertexCount = 0; if (gl->batchType == BATCHTYPE_QUAD) { singleVertexCount = VERTICES_PER_QUAD; @@ -157,7 +180,7 @@ static void flushBatch(GLRenderer* gl) { glBindBuffer(GL_ARRAY_BUFFER, gl->vbo); glBufferSubData(GL_ARRAY_BUFFER, 0, vertexCount * FLOATS_PER_VERTEX * sizeof(float), gl->vertexData); - glBindTexture(GL_TEXTURE_2D, gl->currentTextureId); + if (gl->batchType == BATCHTYPE_QUAD) { glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, nullptr); @@ -360,7 +383,7 @@ static void glGpuSetShader(Renderer* renderer, int32_t ShaderIndex) { GLint gm_Matrices2 = glGetUniformLocation(Shader, "gm_Matrices[2]"); GLint gm_Matrices3 = glGetUniformLocation(Shader, "gm_Matrices[3]"); GLint gm_Matrices4 = glGetUniformLocation(Shader, "gm_Matrices[4]"); - GLint gm_BaseTexture = glGetUniformLocation(Shader, "gm_BaseTexture"); + GLint gm_FogStart = glGetUniformLocation(Shader, "gm_FogStart"); GLint gm_RcpFogRange = glGetUniformLocation(Shader, "gm_RcpFogRange"); @@ -373,9 +396,7 @@ static void glGpuSetShader(Renderer* renderer, int32_t ShaderIndex) { GLint gm_AlphaTestEnabled = glGetUniformLocation(Shader, "gm_AlphaTestEnabled"); GLint gm_AlphaRefValue = glGetUniformLocation(Shader, "gm_AlphaRefValue"); - if (gm_BaseTexture != -1) { - glUniform1i(gm_BaseTexture, 0); - } + if (gm_Matrices0 != -1) { glUniformMatrix4fv(gm_Matrices0, 1, GL_FALSE, renderer->GML_Matrices[MATRIX_VIEW].m); @@ -424,7 +445,7 @@ static void glShaderSettingsRefresh(Renderer* renderer) { glUniform4f(gl->uFogColor, FogR, FoGG, FogB, gl->fogEnable ? 1.0f : 0.0f); glUniform1f(gl->uAlphaTestRef, gl->alphaTestRef); glUniform1i(gl->uAlphaTestEnabled, gl->alphaTestEnable); - glUniform1i(gl->uTexture, 0); + glUniform1i(gl->uTexture, 1); } } @@ -504,7 +525,7 @@ static void glBeginView(Renderer* renderer, int32_t viewX, int32_t viewY, int32_ renderer->GML_Matrices[MATRIX_WORLD_VIEW_PROJECTION] = projection; glShaderSettingsRefresh(renderer); - glActiveTexture(GL_TEXTURE0); + glActiveTexture(GL_TEXTURE1); glBindVertexArray(gl->vao); renderer->PreviousViewMatrix = projection; @@ -554,7 +575,7 @@ static void glBeginGUI(Renderer* renderer, int32_t guiW, int32_t guiH, int32_t p renderer->GML_Matrices[MATRIX_WORLD_VIEW_PROJECTION] = projection; glShaderSettingsRefresh(renderer); - glActiveTexture(GL_TEXTURE0); + glActiveTexture(GL_TEXTURE1); glBindVertexArray(gl->vao); } @@ -1825,7 +1846,6 @@ static int32_t glShaderGetUniform(Renderer* renderer, int32_t shaderIndex, char* static int32_t glShaderGetSamplerIndex(Renderer* renderer, int32_t shaderIndex, char* uniform) { GLRenderer* gl = (GLRenderer*) renderer; - flushBatch(gl); GLuint Shader = gl->GMLShaders[shaderIndex]; GLint UniformCount; @@ -1913,7 +1933,7 @@ static void glTextureSetStage(Renderer* renderer, int32_t slot, uint32_t texID) } glActiveTexture(GL_TEXTURE0 + slot); glBindTexture(GL_TEXTURE_2D, texID); - glActiveTexture(GL_TEXTURE0); + glActiveTexture(GL_TEXTURE1); }