From 7b751ca67aec2aecbc6f3a0d71759ce1dc74c5f1 Mon Sep 17 00:00:00 2001 From: Classic0306 <190026317+Classic0306@users.noreply.github.com> Date: Thu, 11 Jun 2026 23:59:17 +0200 Subject: [PATCH 01/16] actually use the Camera's matricies and fix mistake with the matrix lookat thingy --- src/gl/gl_renderer.c | 2 ++ src/runner.h | 2 ++ src/vm_builtins.c | 48 +++++++++++++++++++++++++++++++++----------- 3 files changed, 40 insertions(+), 12 deletions(-) diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index accb6efe..143ae8f9 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -558,6 +558,7 @@ static void glEndView(Renderer* renderer) { // camera_apply: swap the active world->clip projection on the current target without touching its viewport. static void glApplyProjection(Renderer* renderer, const Matrix4f* worldToClip) { GLRenderer* gl = (GLRenderer*) renderer; + // Flush first so pending quads draw under the projection they were issued with. flushBatch(gl); Matrix4f projection = *worldToClip; @@ -565,6 +566,7 @@ static void glApplyProjection(Renderer* renderer, const Matrix4f* worldToClip) { renderer->gmlMatrices[MATRIX_WORLD_VIEW_PROJECTION] = projection; glShaderSettingsRefresh(renderer); renderer->previousViewMatrix = projection; + } static void glBeginGUI(Renderer* renderer, int32_t guiW, int32_t guiH, int32_t portX, int32_t portY, int32_t portW, int32_t portH, int32_t targetSurfaceId) { diff --git a/src/runner.h b/src/runner.h index 1f5ce8b0..b1fa5df1 100644 --- a/src/runner.h +++ b/src/runner.h @@ -158,6 +158,8 @@ typedef struct { // Center derived from camera_set_view_mat; kept so set_view_mat / set_proj_mat (which arrive in either order) can both recompute the top-left viewX/viewY once the size from the proj matrix is known. int32_t viewMatCenterX; int32_t viewMatCenterY; + Matrix4f ViewMatrix; + Matrix4f ProjectionMatrix; } GMLCamera; typedef struct { diff --git a/src/vm_builtins.c b/src/vm_builtins.c index ac69a957..0f0b5e0d 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -2953,20 +2953,20 @@ static RValue builtin_matrix_build_lookat(MAYBE_UNUSED VMContext *ctx, RValue *a Matrix4f_identity(&matrix); matrix.m[Matrix_getIndex(0, 0)] = xRight; - matrix.m[Matrix_getIndex(0, 1)] = xUp; - matrix.m[Matrix_getIndex(0, 2)] = xLook; + matrix.m[Matrix_getIndex(1, 0)] = xUp; + matrix.m[Matrix_getIndex(2, 0)] = xLook; - matrix.m[Matrix_getIndex(1, 0)] = yRight; + matrix.m[Matrix_getIndex(0, 1)] = yRight; matrix.m[Matrix_getIndex(1, 1)] = yUp; - matrix.m[Matrix_getIndex(1, 2)] = yLook; + matrix.m[Matrix_getIndex(2, 1)] = yLook; - matrix.m[Matrix_getIndex(2, 0)] = zRight; - matrix.m[Matrix_getIndex(2, 1)] = zUp; + matrix.m[Matrix_getIndex(0, 2)] = zRight; + matrix.m[Matrix_getIndex(1, 2)] = zUp; matrix.m[Matrix_getIndex(2, 2)] = zLook; - matrix.m[Matrix_getIndex(3, 0)] = -x; - matrix.m[Matrix_getIndex(3, 1)] = -y; - matrix.m[Matrix_getIndex(3, 2)] = -z; + matrix.m[Matrix_getIndex(0, 3)] = -x; + matrix.m[Matrix_getIndex(1, 3)] = -y; + matrix.m[Matrix_getIndex(2, 3)] = -z; bool toPrevMatrix = argCount == 10; GMLArray *destArray = toPrevMatrix ? args[9].array : nullptr; @@ -3488,9 +3488,24 @@ static RValue builtin_camera_set_view_mat(VMContext* ctx, RValue* args, int32_t camera->viewMatCenterY = (int32_t) lround(-m.m[Matrix_getIndex(3, 1)]); camera->viewX = camera->viewMatCenterX - camera->viewWidth / 2; camera->viewY = camera->viewMatCenterY - camera->viewHeight / 2; + camera->ViewMatrix = m; return RValue_makeUndefined(); } +static RValue builtin_camera_get_view_mat(VMContext* ctx, RValue* args, int32_t argCount) { + Runner* runner = ctx->runner; + GMLCamera* camera = Runner_getCameraById(runner, RValue_toInt32(args[0])); + if (camera == nullptr) return RValue_makeUndefined(); + return RValue_makeArray(matrixToGml(&camera->ViewMatrix)); +} + +static RValue builtin_camera_get_proj_mat(VMContext* ctx, RValue* args, int32_t argCount) { + Runner* runner = ctx->runner; + GMLCamera* camera = Runner_getCameraById(runner, RValue_toInt32(args[0])); + if (camera == nullptr) return RValue_makeUndefined(); + return RValue_makeArray(matrixToGml(&camera->ProjectionMatrix)); +} + static RValue builtin_camera_set_proj_mat(VMContext* ctx, RValue* args, int32_t argCount) { if (2 > argCount) return RValue_makeUndefined(); Runner* runner = ctx->runner; @@ -3505,6 +3520,8 @@ static RValue builtin_camera_set_proj_mat(VMContext* ctx, RValue* args, int32_t if (m11 != 0.0) camera->viewHeight = (int32_t) lround(GMLReal_fabs(2.0 / m11)); camera->viewX = camera->viewMatCenterX - camera->viewWidth / 2; camera->viewY = camera->viewMatCenterY - camera->viewHeight / 2; + camera->ProjectionMatrix = m; + camera->ProjectionMatrix.m[Matrix_getIndex(1, 1)] = -m.m[Matrix_getIndex(1, 1)]; return RValue_makeUndefined(); } @@ -3692,9 +3709,14 @@ static RValue builtin_camera_apply(VMContext* ctx, RValue* args, int32_t argCoun Runner* runner = ctx->runner; GMLCamera* camera = Runner_getCameraById(runner, RValue_toInt32(args[0])); if (camera != nullptr) { - Matrix4f worldToClip; - Matrix4f_viewProjection(&worldToClip, (float) camera->viewX, (float) camera->viewY, (float) camera->viewWidth, (float) camera->viewHeight, camera->viewAngle); - runner->renderer->vtable->applyProjection(runner->renderer, &worldToClip); + + Matrix4f ViewMatrix = camera->ViewMatrix; + Matrix4f ProjectionMatrix = camera->ProjectionMatrix; + Matrix4f FinalProjection; + Matrix4f_multiply(&FinalProjection, &ProjectionMatrix, &ViewMatrix); + + runner->renderer->vtable->applyProjection(runner->renderer, &FinalProjection); + } return RValue_makeUndefined(); } @@ -15445,7 +15467,9 @@ void VMBuiltins_registerAll(VMContext* ctx) { VM_registerBuiltin(ctx, "camera_get_view_height", builtin_camera_get_view_height); VM_registerBuiltin(ctx, "camera_set_view_pos", builtin_camera_set_view_pos); VM_registerBuiltin(ctx, "camera_set_view_mat", builtin_camera_set_view_mat); + VM_registerBuiltin(ctx, "camera_get_view_mat", builtin_camera_get_view_mat); VM_registerBuiltin(ctx, "camera_set_proj_mat", builtin_camera_set_proj_mat); + VM_registerBuiltin(ctx, "camera_get_proj_mat", builtin_camera_get_proj_mat); VM_registerBuiltin(ctx, "camera_get_view_target", builtin_camera_get_view_target); VM_registerBuiltin(ctx, "camera_set_view_target", builtin_camera_set_view_target); VM_registerBuiltin(ctx, "camera_get_view_border_x", builtin_camera_get_view_border_x); From 5d36b62c353df95f27f01792ecfbfa199fbdc31b Mon Sep 17 00:00:00 2001 From: Classic0306 <190026317+Classic0306@users.noreply.github.com> Date: Fri, 12 Jun 2026 13:15:02 +0200 Subject: [PATCH 02/16] remove ViewMatCenter --- src/runner.h | 4 +--- src/vm_builtins.c | 5 ----- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/src/runner.h b/src/runner.h index b1fa5df1..873b7efd 100644 --- a/src/runner.h +++ b/src/runner.h @@ -155,9 +155,7 @@ typedef struct { int32_t speedY; int32_t objectId; // follow target (object index), -1 = none float viewAngle; - // Center derived from camera_set_view_mat; kept so set_view_mat / set_proj_mat (which arrive in either order) can both recompute the top-left viewX/viewY once the size from the proj matrix is known. - int32_t viewMatCenterX; - int32_t viewMatCenterY; + Matrix4f ViewMatrix; Matrix4f ProjectionMatrix; } GMLCamera; diff --git a/src/vm_builtins.c b/src/vm_builtins.c index 0f0b5e0d..c80d5edb 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -3483,11 +3483,6 @@ static RValue builtin_camera_set_view_mat(VMContext* ctx, RValue* args, int32_t if (camera == nullptr || !rvalueIsMatrix(args[1])) return RValue_makeUndefined(); Matrix4f m; matrixFromGml(&m, args[1].array); - // For an axis-aligned 2D camera the view-matrix translation encodes -(camera center). - camera->viewMatCenterX = (int32_t) lround(-m.m[Matrix_getIndex(3, 0)]); - camera->viewMatCenterY = (int32_t) lround(-m.m[Matrix_getIndex(3, 1)]); - camera->viewX = camera->viewMatCenterX - camera->viewWidth / 2; - camera->viewY = camera->viewMatCenterY - camera->viewHeight / 2; camera->ViewMatrix = m; return RValue_makeUndefined(); } From 7df32dfd4b222f8f4a198ddd8d49c3b78499a6eb Mon Sep 17 00:00:00 2001 From: Classic0306 <190026317+Classic0306@users.noreply.github.com> Date: Fri, 12 Jun 2026 13:17:21 +0200 Subject: [PATCH 03/16] fix tiny mistake --- src/vm_builtins.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/vm_builtins.c b/src/vm_builtins.c index c80d5edb..bd78e0f8 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -3513,8 +3513,6 @@ static RValue builtin_camera_set_proj_mat(VMContext* ctx, RValue* args, int32_t GMLReal m11 = m.m[Matrix_getIndex(1, 1)]; if (m00 != 0.0) camera->viewWidth = (int32_t) lround(GMLReal_fabs(2.0 / m00)); if (m11 != 0.0) camera->viewHeight = (int32_t) lround(GMLReal_fabs(2.0 / m11)); - camera->viewX = camera->viewMatCenterX - camera->viewWidth / 2; - camera->viewY = camera->viewMatCenterY - camera->viewHeight / 2; camera->ProjectionMatrix = m; camera->ProjectionMatrix.m[Matrix_getIndex(1, 1)] = -m.m[Matrix_getIndex(1, 1)]; return RValue_makeUndefined(); From f53f540cf162ebeda1a2c0e70dba364c6be06909 Mon Sep 17 00:00:00 2001 From: Classic0306 <190026317+Classic0306@users.noreply.github.com> Date: Sat, 13 Jun 2026 00:45:19 +0200 Subject: [PATCH 04/16] change more things to use matricies! I kinda forgor what else I did --- src/gl/gl_renderer.c | 44 +++++++++--- src/gl/gl_renderer.h | 2 + src/gl_legacy/gl_legacy_renderer.c | 4 +- src/renderer.h | 3 +- src/runner.c | 11 ++- src/vm_builtins.c | 110 +++++++++++++++++++++++++++-- 6 files changed, 152 insertions(+), 22 deletions(-) diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index 143ae8f9..8b12e6d0 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -42,11 +42,11 @@ static const char* defaultVertexShaderSource = "layout(location = 0) in vec2 aPos;\n" "layout(location = 1) in vec4 aColor;\n" "layout(location = 2) in vec2 aTexCoord;\n" - "uniform mat4 uProjection;\n" + "uniform mat4 uWorldViewProjection;\n" "out vec2 vTexCoord;\n" "out vec4 vColor;\n" "void main() {\n" - " gl_Position = uProjection * vec4(aPos, 0.0, 1.0);\n" + " gl_Position = uWorldViewProjection * vec4(aPos, 0.0, 1.0);\n" " vTexCoord = aTexCoord;\n" " vColor = aColor;\n" "}\n"; @@ -59,7 +59,7 @@ static const char* defaultFragmentShaderSource = "uniform sampler2D uTexture;\n" "uniform float uAlphaTestRef;\n" "uniform bool uAlphaTestEnabled;\n" - "uniform vec4 uFogColor;\n" // rgb = fog color, a = enable flag (0 or 1) +"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" @@ -538,7 +538,7 @@ static void glBeginView(Renderer* renderer, int32_t viewX, int32_t viewY, int32_ // World -> clip transform for this view. Matrix4f projection; Matrix4f_viewProjection(&projection, (float) viewX, (float) viewY, (float) viewW, (float) viewH, viewAngle); - Matrix4f_flipClipY(&projection); + renderer->gmlMatrices[MATRIX_WORLD_VIEW_PROJECTION] = projection; glShaderSettingsRefresh(renderer); @@ -556,16 +556,30 @@ static void glEndView(Renderer* renderer) { } // camera_apply: swap the active world->clip projection on the current target without touching its viewport. -static void glApplyProjection(Renderer* renderer, const Matrix4f* worldToClip) { +static void glApplyProjection(Renderer* renderer, const Matrix4f* ViewMatrix,const Matrix4f* ProjectionMatrix) { GLRenderer* gl = (GLRenderer*) renderer; // Flush first so pending quads draw under the projection they were issued with. flushBatch(gl); - Matrix4f projection = *worldToClip; - Matrix4f_flipClipY(&projection); - renderer->gmlMatrices[MATRIX_WORLD_VIEW_PROJECTION] = projection; + + Matrix4f World = renderer->gmlMatrices[MATRIX_WORLD]; + Matrix4f View = *ViewMatrix; + Matrix4f Projection = *ProjectionMatrix; + + Matrix4f WorldView; + Matrix4f_multiply(&WorldView, &View, &World); + + Matrix4f WorldViewProjection; + Matrix4f_multiply(&WorldViewProjection, &View, &World); + Matrix4f_multiply(&WorldViewProjection, &Projection, &WorldViewProjection); + + renderer->gmlMatrices[MATRIX_VIEW] = View; + renderer->gmlMatrices[MATRIX_PROJECTION] = Projection; + renderer->gmlMatrices[MATRIX_WORLD_VIEW] = WorldView; + renderer->gmlMatrices[MATRIX_WORLD_VIEW_PROJECTION] = WorldViewProjection; + //oh my I hope it's good enough. glShaderSettingsRefresh(renderer); - renderer->previousViewMatrix = projection; + renderer->previousViewMatrix = WorldViewProjection; } @@ -592,7 +606,7 @@ 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); - + Matrix4f_flipClipY(&projection); renderer->gmlMatrices[MATRIX_WORLD_VIEW_PROJECTION] = projection; glShaderSettingsRefresh(renderer); glActiveTexture(GL_TEXTURE1); @@ -1990,7 +2004,7 @@ static bool glSetRenderTarget(Renderer* renderer, int32_t surfaceId, bool implic // 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], 0.0f, (float) gl->surfaceHeight[surfaceId], -1.0f, 1.0f); + Matrix4f_ortho(&projection, 0.0f, (float) gl->surfaceWidth[surfaceId], (float) gl->surfaceHeight[surfaceId], 0.0f, -1.0f, 1.0f); glViewport(0, 0, gl->surfaceWidth[surfaceId], gl->surfaceHeight[surfaceId]); glDisable(GL_SCISSOR_TEST); renderer->gmlMatrices[MATRIX_WORLD_VIEW_PROJECTION] = projection; @@ -2482,6 +2496,13 @@ static bool glShadersSupported(void) { return true; } +static void glSetMatrix(Renderer* renderer, int32_t MatrixType, Matrix4f Matrix) { + GLRenderer* gl = (GLRenderer*) renderer; + flushBatch(gl); + renderer->gmlMatrices[MatrixType] = Matrix; + glShaderSettingsRefresh(renderer); +} + // ===[ Vtable ]=== static RendererVtable glVtable; @@ -2554,6 +2575,7 @@ Renderer* GLRenderer_create(void) { glVtable.textureSetStage = glTextureSetStage, glVtable.shaderIsCompiled = glShaderIsCompiled, glVtable.shadersSupported = glShadersSupported, + glVtable.setMatrix = glSetMatrix, 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 7e3b13db..71909234 100644 --- a/src/gl/gl_renderer.h +++ b/src/gl/gl_renderer.h @@ -42,6 +42,8 @@ typedef struct { bool colorWriteR, colorWriteG, colorWriteB, colorWriteA; bool fogEnable; uint32_t fogColor; // BGR + float fogStart; + float fogEnd; GLuint vao, vbo, ebo; float* vertexData; // MAX_QUADS * VERTICES_PER_QUAD * FLOATS_PER_VERTEX floats diff --git a/src/gl_legacy/gl_legacy_renderer.c b/src/gl_legacy/gl_legacy_renderer.c index cbba9f0a..9be5f228 100644 --- a/src/gl_legacy/gl_legacy_renderer.c +++ b/src/gl_legacy/gl_legacy_renderer.c @@ -186,8 +186,8 @@ static void glEndView(MAYBE_UNUSED Renderer* renderer) { } // camera_apply: swap the active world->clip projection on the current target without touching its viewport. -static void glApplyProjection(Renderer* renderer, const Matrix4f* worldToClip) { - Matrix4f projection = *worldToClip; +static void glApplyProjection(Renderer* renderer, const Matrix4f* ViewMatrix,const Matrix4f* ProjectionMatrix) { + Matrix4f projection = *ProjectionMatrix; //fix it later Matrix4f_flipClipY(&projection); glMatrixMode(GL_PROJECTION); glLoadMatrixf(projection.m); diff --git a/src/renderer.h b/src/renderer.h index a7f39023..f9cb3a30 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -72,7 +72,7 @@ typedef struct { void (*endFrameEnd)(Renderer* renderer); void (*beginView)(Renderer* renderer, int32_t viewX, int32_t viewY, int32_t viewW, int32_t viewH, int32_t portX, int32_t portY, int32_t portW, int32_t portH, float viewAngle); void (*endView)(Renderer* renderer); - void (*applyProjection)(Renderer* renderer, const Matrix4f* worldToClip); + void (*applyProjection)(Renderer* renderer, const Matrix4f* ViewMatrix,const Matrix4f* ProjectionMatrix); // GUI pass: coordinates are (0,0)..(guiW,guiH) mapped to the current view's port rect. Called after endView. // targetSurfaceId is the surface the pass renders into, or RENDER_TARGET_HOST_FRAMEBUFFER. void (*beginGUI)(Renderer* renderer, int32_t guiW, int32_t guiH, int32_t portX, int32_t portY, int32_t portW, int32_t portH, int32_t targetSurfaceId); @@ -149,6 +149,7 @@ typedef struct { void (*textureSetStage)(Renderer* renderer, int32_t slot, uint32_t texID); bool (*shaderIsCompiled)(Renderer* renderer, int32_t shader); bool (*shadersSupported)(void); + void (*setMatrix)(Renderer* renderer, int32_t MatrixType, Matrix4f Matrix); } RendererVtable; // ===[ Renderer Base Struct ]=== diff --git a/src/runner.c b/src/runner.c index 941c5d54..01ae04b8 100644 --- a/src/runner.c +++ b/src/runner.c @@ -1131,9 +1131,14 @@ void Runner_drawViews(Runner* runner, int32_t gameW, int32_t gameH, bool debugSh Runner_surfaceSetTarget(runner, view->surfaceId); - Matrix4f proj; - Matrix4f_viewProjection(&proj, (float) camera->viewX, (float) camera->viewY, (float) camera->viewWidth, (float) camera->viewHeight, camera->viewAngle); - renderer->vtable->applyProjection(renderer, &proj); + //Matrix4f proj; + //Matrix4f_viewProjection(&proj, (float) camera->viewX, (float) camera->viewY, (float) camera->viewWidth, (float) camera->viewHeight, camera->viewAngle); + //renderer->vtable->applyProjection(renderer, &proj); + + Matrix4f ViewMatrix = camera->ViewMatrix; + Matrix4f ProjectionMatrix = camera->ProjectionMatrix; + + runner->renderer->vtable->applyProjection(runner->renderer, &ViewMatrix, &ProjectionMatrix); runner->viewCurrent = (int32_t) vi; Runner_draw(runner); diff --git a/src/vm_builtins.c b/src/vm_builtins.c index bd78e0f8..39f4785a 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -2898,6 +2898,23 @@ static RValue builtin_matrix_build_projection_perspective_fov(MAYBE_UNUSED VMCon return RValue_makeArrayWeak(destArray); } } +static RValue builtin_matrix_get(MAYBE_UNUSED VMContext *ctx, RValue *args, int32_t argCount) { + int32_t Matrix = RValue_toInt32(args[0]); + return RValue_makeArray(matrixToGml(&ctx->runner->renderer->gmlMatrices[Matrix])); +} + +static RValue builtin_matrix_set(MAYBE_UNUSED VMContext *ctx, RValue *args, int32_t argCount) { + int32_t Matrix = RValue_toInt32(args[0]); + Matrix4f m; + matrixFromGml(&m, args[1].array); + //return RValue_makeArray(matrixToGml(&ctx->runner->renderer->gmlMatrices[Matrix])); + if (ctx->runner->renderer != nullptr) { + ctx->runner->renderer->vtable->setMatrix(ctx->runner->renderer, Matrix, m); + } + + return RValue_makeUndefined(); +} + static RValue builtin_matrix_build_lookat(MAYBE_UNUSED VMContext *ctx, RValue *args, int32_t argCount) { if (argCount < 9 || argCount > 10) return RValue_makeUndefined(); @@ -3650,6 +3667,90 @@ static RValue builtin_camera_create_view(VMContext* ctx, RValue* args, int32_t a if (argCount > 7) camera->speedY = RValue_toInt32(args[7]); if (argCount > 8) camera->borderX = (uint32_t) RValue_toInt32(args[8]); if (argCount > 9) camera->borderY = (uint32_t) RValue_toInt32(args[9]); + + //what have I done. + Matrix4f Projection; + + memset(Projection.m, 0, sizeof(Projection.m)); + Projection.m[Matrix_getIndex(0,0)] = 2.0f / RValue_toReal(args[2]); + Projection.m[Matrix_getIndex(1,1)] = 2.0f / RValue_toReal(args[3]); + Projection.m[Matrix_getIndex(2,2)] = 1.0f / (32000.0 - 0.0); + Projection.m[Matrix_getIndex(3,3)] = 1.0f; + Projection.m[Matrix_getIndex(2,3)] = 0.0 / (0.0 - 32000.0); + camera->ProjectionMatrix = Projection; + + + GMLReal xFrom = RValue_toReal(args[0]) + RValue_toReal(args[2])/2.0f; + GMLReal yFrom = RValue_toReal(args[1]) + RValue_toReal(args[3])/2.0f; + GMLReal zFrom = -16000.0; + + GMLReal xTo = RValue_toReal(args[0]) + RValue_toReal(args[2])/2.0f; + GMLReal yTo = RValue_toReal(args[1]) + RValue_toReal(args[3])/2.0f; + GMLReal zTo = 16000.0; + + GMLReal xUp = 0.0; + GMLReal yUp = 1.0; + GMLReal zUp = 0.0; + GMLReal magUp = GMLReal_sqrt(xUp * xUp + yUp * yUp + zUp * zUp); + xUp /= magUp; + yUp /= magUp; + zUp /= magUp; + + GMLReal xLook = xTo - xFrom; + GMLReal yLook = yTo - yFrom; + GMLReal zLook = zTo - zFrom; + GMLReal magLook = GMLReal_sqrt(xLook * xLook + yLook * yLook + zLook * zLook); + xLook /= magLook; + yLook /= magLook; + zLook /= magLook; + + // normalised cross product between Up and Look + GMLReal xRight = yUp * zLook - zUp * yLook; + GMLReal yRight = zUp * xLook - xUp * zLook; + GMLReal zRight = xUp * yLook - yUp * xLook; + GMLReal magRight = GMLReal_sqrt(xRight * xRight + yRight * yRight + zRight * zRight); + xRight /= magRight; + yRight /= magRight; + zRight /= magRight; + + // normalised cross product between Look and Right + xUp = yLook * zRight - zLook * yRight; + yUp = zLook * xRight - xLook * zRight; + zUp = xLook * yRight - yLook * xRight; + magUp = GMLReal_sqrt(xUp * xUp + yUp * yUp + zUp * zUp); + xUp /= magUp; + yUp /= magUp; + zUp /= magUp; + + GMLReal x, y, z; + x = xFrom * xRight + yFrom * yRight + zFrom * zRight; + y = xFrom * xUp + yFrom * yUp + zFrom * zUp; + z = xFrom * xLook + yFrom * yLook + zFrom * zLook; + + Matrix4f ViewMatrix; + Matrix4f_identity(&ViewMatrix); + + ViewMatrix.m[Matrix_getIndex(0, 0)] = xRight; + ViewMatrix.m[Matrix_getIndex(1, 0)] = xUp; + ViewMatrix.m[Matrix_getIndex(2, 0)] = xLook; + + ViewMatrix.m[Matrix_getIndex(0, 1)] = yRight; + ViewMatrix.m[Matrix_getIndex(1, 1)] = yUp; + ViewMatrix.m[Matrix_getIndex(2, 1)] = yLook; + + ViewMatrix.m[Matrix_getIndex(0, 2)] = zRight; + ViewMatrix.m[Matrix_getIndex(1, 2)] = zUp; + ViewMatrix.m[Matrix_getIndex(2, 2)] = zLook; + + ViewMatrix.m[Matrix_getIndex(0, 3)] = -x; + ViewMatrix.m[Matrix_getIndex(1, 3)] = -y; + ViewMatrix.m[Matrix_getIndex(2, 3)] = -z; + camera->ViewMatrix = ViewMatrix; + + //builtin_matrix_build_lookat(ctx,args[0],args[1],RValue_makeReal(-16000.0),args[0],args[1],RValue_makeReal(16000.0), RValue_makeReal(0.0),RValue_makeReal(1.0),RValue_makeReal(0.0)) + //builtin_matrix_build_projection_ortho(ctx,args[2], args[3], RValue_makeReal(0.0), RValue_makeReal(32000.0)); + + return RValue_makeReal(id); } @@ -3705,10 +3806,8 @@ static RValue builtin_camera_apply(VMContext* ctx, RValue* args, int32_t argCoun Matrix4f ViewMatrix = camera->ViewMatrix; Matrix4f ProjectionMatrix = camera->ProjectionMatrix; - Matrix4f FinalProjection; - Matrix4f_multiply(&FinalProjection, &ProjectionMatrix, &ViewMatrix); - - runner->renderer->vtable->applyProjection(runner->renderer, &FinalProjection); + + runner->renderer->vtable->applyProjection(runner->renderer, &ViewMatrix, &ProjectionMatrix); } return RValue_makeUndefined(); @@ -15417,7 +15516,8 @@ void VMBuiltins_registerAll(VMContext* ctx) { VM_registerBuiltin(ctx, "matrix_build_lookat", builtin_matrix_build_lookat); VM_registerBuiltin(ctx, "matrix_build_projection_ortho", builtin_matrix_build_projection_ortho); VM_registerBuiltin(ctx, "matrix_build_projection_perspective_fov", builtin_matrix_build_projection_perspective_fov); - + VM_registerBuiltin(ctx, "matrix_get", builtin_matrix_get); + VM_registerBuiltin(ctx, "matrix_set", builtin_matrix_set); // Random VM_registerBuiltin(ctx, "random", builtin_random); VM_registerBuiltin(ctx, "random_range", builtin_random_range); From a4464f0c363af58849e24a41008c5d6c596952cb Mon Sep 17 00:00:00 2001 From: Classic0306 <190026317+Classic0306@users.noreply.github.com> Date: Sat, 13 Jun 2026 18:57:17 +0200 Subject: [PATCH 05/16] I somehow already forgor what else I did --- src/gl/gl_renderer.c | 33 ++++--- src/matrix_math.h | 81 +++++++++++++++++ src/runner.c | 51 ++++++++++- src/runner.h | 4 +- src/vm_builtins.c | 210 +++++++++++++++---------------------------- 5 files changed, 221 insertions(+), 158 deletions(-) diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index 8b12e6d0..affdfed7 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -524,29 +524,21 @@ static void glBeginView(Renderer* renderer, int32_t viewX, int32_t viewY, int32_ // Set viewport and scissor to the port rectangle within the FBO // FBO uses game resolution, port coordinates are in game space // OpenGL viewport Y is bottom-up, game Y is top-down - int32_t glPortY = gl->gameH - portY - portH; - glViewport(portX, glPortY, portW, portH); + + glViewport(portX, portY, portW, portH); gl->base.CPortX = portX; - gl->base.CPortY = glPortY; + gl->base.CPortY = portY; gl->base.CPortW = portW; gl->base.CPortH = portH; glEnable(GL_SCISSOR_TEST); - glScissor(portX, glPortY, portW, portH); - - // World -> clip transform for this view. - Matrix4f projection; - Matrix4f_viewProjection(&projection, (float) viewX, (float) viewY, (float) viewW, (float) viewH, viewAngle); + glScissor(portX, portY, portW, portH); - - renderer->gmlMatrices[MATRIX_WORLD_VIEW_PROJECTION] = projection; glShaderSettingsRefresh(renderer); glActiveTexture(GL_TEXTURE1); glBindVertexArray(gl->vao); - renderer->previousViewMatrix = projection; - } static void glEndView(Renderer* renderer) { @@ -2500,6 +2492,23 @@ static void glSetMatrix(Renderer* renderer, int32_t MatrixType, Matrix4f Matrix) GLRenderer* gl = (GLRenderer*) renderer; flushBatch(gl); renderer->gmlMatrices[MatrixType] = Matrix; + //yeah just recalculate everything when we change a matrix + //TODO LATR: only allow these 3 to be changed directly, other ones should only be allowed to be calculated by the rest of the function + Matrix4f World = renderer->gmlMatrices[MATRIX_WORLD]; + Matrix4f View = renderer->gmlMatrices[MATRIX_VIEW]; + Matrix4f Projection = renderer->gmlMatrices[MATRIX_PROJECTION]; + + Matrix4f WorldView; + Matrix4f_multiply(&WorldView, &View, &World); + + Matrix4f WorldViewProjection; + Matrix4f_multiply(&WorldViewProjection, &View, &World); + Matrix4f_multiply(&WorldViewProjection, &Projection, &WorldViewProjection); + + renderer->gmlMatrices[MATRIX_WORLD_VIEW] = WorldView; + renderer->gmlMatrices[MATRIX_WORLD_VIEW_PROJECTION] = WorldViewProjection; + + glShaderSettingsRefresh(renderer); } diff --git a/src/matrix_math.h b/src/matrix_math.h index ad8acd77..7c15807a 100644 --- a/src/matrix_math.h +++ b/src/matrix_math.h @@ -51,6 +51,87 @@ static inline Matrix4f* Matrix4f_multiply(Matrix4f* dest, const Matrix4f* a, con return dest; } +static inline Matrix4f* Matrix4f_LookAt(Matrix4f* dest, float x_from, float y_from, float z_from, float x_to, float y_to, float z_to, float x_up, float y_up, float z_up) { + + double xFrom = x_from; + double yFrom = y_from; + double zFrom = z_from; + + double xTo = x_to; + double yTo = y_to; + double zTo = z_to; + + double xUp = x_up; + double yUp = y_up; + double zUp = z_up; + double magUp = sqrt(xUp * xUp + yUp * yUp + zUp * zUp); + xUp /= magUp; + yUp /= magUp; + zUp /= magUp; + + double xLook = xTo - xFrom; + double yLook = yTo - yFrom; + double zLook = zTo - zFrom; + double magLook = sqrt(xLook * xLook + yLook * yLook + zLook * zLook); + xLook /= magLook; + yLook /= magLook; + zLook /= magLook; + + // normalised cross product between Up and Look + double xRight = yUp * zLook - zUp * yLook; + double yRight = zUp * xLook - xUp * zLook; + double zRight = xUp * yLook - yUp * xLook; + double magRight = sqrt(xRight * xRight + yRight * yRight + zRight * zRight); + xRight /= magRight; + yRight /= magRight; + zRight /= magRight; + + // normalised cross product between Look and Right + xUp = yLook * zRight - zLook * yRight; + yUp = zLook * xRight - xLook * zRight; + zUp = xLook * yRight - yLook * xRight; + magUp = sqrt(xUp * xUp + yUp * yUp + zUp * zUp); + xUp /= magUp; + yUp /= magUp; + zUp /= magUp; + + double x, y, z; + x = xFrom * xRight + yFrom * yRight + zFrom * zRight; + y = xFrom * xUp + yFrom * yUp + zFrom * zUp; + z = xFrom * xLook + yFrom * yLook + zFrom * zLook; + + dest->m[Matrix_getIndex(0, 0)] = xRight; + dest->m[Matrix_getIndex(1, 0)] = xUp; + dest->m[Matrix_getIndex(2, 0)] = xLook; + + dest->m[Matrix_getIndex(0, 1)] = yRight; + dest->m[Matrix_getIndex(1, 1)] = yUp; + dest->m[Matrix_getIndex(2, 1)] = yLook; + + dest->m[Matrix_getIndex(0, 2)] = zRight; + dest->m[Matrix_getIndex(1, 2)] = zUp; + dest->m[Matrix_getIndex(2, 2)] = zLook; + + dest->m[Matrix_getIndex(0, 3)] = -x; + dest->m[Matrix_getIndex(1, 3)] = -y; + dest->m[Matrix_getIndex(2, 3)] = -z; + + return dest; +} + +static inline Matrix4f* Matrix4f_Orthographic(Matrix4f* dest, float width, float height, float zfar, float znear) { + + memset(dest->m, 0, sizeof(dest->m)); + dest->m[Matrix_getIndex(0,0)] = 2.0f / width; + dest->m[Matrix_getIndex(1,1)] = 2.0f / height; + dest->m[Matrix_getIndex(2,2)] = 1.0f / (zfar - znear); + dest->m[Matrix_getIndex(3,3)] = 1.0f; + + dest->m[Matrix_getIndex(2,3)] = znear / (znear - zfar); + + return dest; +} + // ===[ Orthographic Projection ]=== // Post-multiply orthographic projection onto dest: dest = dest * ortho(l, r, b, t, n, f) diff --git a/src/runner.c b/src/runner.c index 01ae04b8..d4e63e0f 100644 --- a/src/runner.c +++ b/src/runner.c @@ -1022,6 +1022,19 @@ void Runner_drawGUI(Runner* runner, int32_t windowW, int32_t windowH, int32_t ta int32_t guiW = runner->guiWidth > 0 ? runner->guiWidth : targetW; int32_t guiH = runner->guiHeight > 0 ? runner->guiHeight : targetH; beginGuiPass(runner, guiW, guiH, windowW, windowH, RENDER_TARGET_HOST_FRAMEBUFFER); + + //make default projection + Matrix4f Projection; + Matrix4f_Orthographic(&Projection, (float) guiW, (float) guiH, 32000.0, 0.0); + + Matrix4f View; + float x = (float) guiW / 2; + float y = (float) guiH / 2; + Matrix4f_identity(&View); + Matrix4f_LookAt(&View, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0); + + runner->renderer->vtable->applyProjection(runner->renderer, &View, &Projection); + fireDrawSubtype(runner, drawables, drawableCount, DRAW_GUI_BEGIN); fireDrawSubtype(runner, drawables, drawableCount, DRAW_GUI); fireDrawSubtype(runner, drawables, drawableCount, DRAW_GUI_END); @@ -1130,10 +1143,6 @@ void Runner_drawViews(Runner* runner, int32_t gameW, int32_t gameH, bool debugSh continue; Runner_surfaceSetTarget(runner, view->surfaceId); - - //Matrix4f proj; - //Matrix4f_viewProjection(&proj, (float) camera->viewX, (float) camera->viewY, (float) camera->viewWidth, (float) camera->viewHeight, camera->viewAngle); - //renderer->vtable->applyProjection(renderer, &proj); Matrix4f ViewMatrix = camera->ViewMatrix; Matrix4f ProjectionMatrix = camera->ProjectionMatrix; @@ -1163,6 +1172,11 @@ void Runner_drawViews(Runner* runner, int32_t gameW, int32_t gameH, bool debugSh runner->viewCurrent = (int32_t) vi; renderer->vtable->beginView(renderer, viewX, viewY, viewW, viewH, portX, portY, portW, portH, viewAngle); + Matrix4f ViewMatrix = camera->ViewMatrix; + Matrix4f ProjectionMatrix = camera->ProjectionMatrix; + //what am I even doing. + runner->renderer->vtable->applyProjection(runner->renderer, &ViewMatrix, &ProjectionMatrix); + Runner_draw(runner); if (debugShowCollisionMasks) DebugOverlay_drawCollisionMasks(runner); @@ -1181,6 +1195,18 @@ void Runner_drawViews(Runner* runner, int32_t gameW, int32_t gameH, bool debugSh expandViewAxis(0, (int32_t) runner->currentRoom->height, gameH, widescreenBaseH, &viewY, &viewH); applyFreeCamera(runner, &viewX, &viewY, &viewW, &viewH); renderer->vtable->beginView(renderer, viewX, viewY, viewW, viewH, 0, 0, gameW, gameH, 0); + + //make default projection + Matrix4f Projection; + Matrix4f_Orthographic(&Projection, (float) gameW, (float) -gameH, 32000.0, 0.0); + + Matrix4f View; + float x = (float) gameW /2; + float y = (float) gameH /2; + Matrix4f_identity(&View); + Matrix4f_LookAt(&View, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0); + + runner->renderer->vtable->applyProjection(runner->renderer, &View, &Projection); Runner_draw(runner); if (debugShowCollisionMasks) DebugOverlay_drawCollisionMasks(runner); @@ -1315,6 +1341,23 @@ static void initDefaultCameraFromRoomView(GMLCamera* camera, RoomView* roomView) camera->speedY = roomView->speedY; camera->objectId = roomView->objectId; camera->viewAngle = 0; + //make default projection + Matrix4f Projection; + Matrix4f_Orthographic(&Projection, (float) camera->viewWidth, (float) -camera->viewHeight, 32000.0, 0.0); + + Matrix4f View; + float x = camera->viewX + camera->viewWidth/2; + float y = camera->viewY + camera->viewHeight/2; + Matrix4f_identity(&View); + Matrix4f_LookAt(&View, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0); + Matrix4f_translate(&View, x, y, 0.0f); + Matrix4f_rotateZ(&View, -camera->viewAngle * (float) M_PI / 180.0f); + Matrix4f_translate(&View, -x, -y, 0.0f); + + + + camera->ProjectionMatrix = Projection; + camera->ViewMatrix = View; } // Copies the viewport (port) properties and enabled flag from parsed room data. diff --git a/src/runner.h b/src/runner.h index 873b7efd..7cb2b7a1 100644 --- a/src/runner.h +++ b/src/runner.h @@ -145,8 +145,8 @@ typedef struct { typedef struct { bool allocated; // slot in use (default cameras: set when the room enables the view; user cameras: camera_create/destroy) - int32_t viewX; - int32_t viewY; + float viewX; + float viewY; int32_t viewWidth; int32_t viewHeight; uint32_t borderX; diff --git a/src/vm_builtins.c b/src/vm_builtins.c index 39f4785a..93877618 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -216,6 +216,21 @@ static DsStack* dsStackGet(Runner* runner, int32_t id) { return &runner->dsStackPool[id]; } +static void UpdateCamera(GMLCamera* camera) { + + float x = camera->viewX + camera->viewWidth/2; + float y = camera->viewY + camera->viewHeight/2; + Matrix4f ViewMatrix; + Matrix4f_identity(&ViewMatrix); + Matrix4f_LookAt(&ViewMatrix, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0); + Matrix4f_translate(&ViewMatrix, x, y, 0.0f); + Matrix4f_rotateZ(&ViewMatrix, -camera->viewAngle * (float) M_PI / 180.0f); + Matrix4f_translate(&ViewMatrix, -x, -y, 0.0f); + camera->ViewMatrix = ViewMatrix; + +} + + // ===[ BUILT-IN VARIABLE GET/SET ]=== static bool isValidAlarmIndex(int alarmIndex) { @@ -1551,22 +1566,34 @@ void VMBuiltins_setVariable(VMContext* ctx, Instance* inst, int16_t builtinVarId // View properties case BUILTIN_VAR_VIEW_XVIEW: { GMLCamera* camera = Runner_getCameraForView(runner, arrayIndex); - if (camera != nullptr) camera->viewX = RValue_toInt32(val); + if (camera != nullptr) { + camera->viewX = RValue_toReal(val); + UpdateCamera(camera); + } return; } case BUILTIN_VAR_VIEW_YVIEW: { GMLCamera* camera = Runner_getCameraForView(runner, arrayIndex); - if (camera != nullptr) camera->viewY = RValue_toInt32(val); + if (camera != nullptr) { + camera->viewY = RValue_toInt32(val); + UpdateCamera(camera); + } return; } case BUILTIN_VAR_VIEW_WVIEW: { GMLCamera* camera = Runner_getCameraForView(runner, arrayIndex); - if (camera != nullptr) camera->viewWidth = RValue_toInt32(val); + if (camera != nullptr) { + camera->viewWidth = RValue_toInt32(val); + UpdateCamera(camera); + } return; } case BUILTIN_VAR_VIEW_HVIEW: { GMLCamera* camera = Runner_getCameraForView(runner, arrayIndex); - if (camera != nullptr) camera->viewHeight = RValue_toInt32(val); + if (camera != nullptr) { + camera->viewHeight = RValue_toInt32(val); + UpdateCamera(camera); + } return; } case BUILTIN_VAR_VIEW_XPORT: @@ -1592,7 +1619,10 @@ void VMBuiltins_setVariable(VMContext* ctx, Instance* inst, int16_t builtinVarId return; case BUILTIN_VAR_VIEW_ANGLE: { GMLCamera* camera = Runner_getCameraForView(runner, arrayIndex); - if (camera != nullptr) camera->viewAngle = (float) RValue_toReal(val); + if (camera != nullptr) { + camera->viewAngle = (float) RValue_toReal(val); + UpdateCamera(camera); + } return; } case BUILTIN_VAR_VIEW_HBORDER: { @@ -2847,14 +2877,7 @@ static RValue builtin_matrix_build_projection_ortho(MAYBE_UNUSED VMContext *ctx, if (toPrevMatrix && !rvalueIsMatrix(args[4])) return RValue_makeUndefined(); Matrix4f mat; - - memset(mat.m, 0, sizeof(mat.m)); - mat.m[Matrix_getIndex(0,0)] = 2.0f / width; - mat.m[Matrix_getIndex(1,1)] = 2.0f / height; - mat.m[Matrix_getIndex(2,2)] = 1.0f / (zfar - znear); - mat.m[Matrix_getIndex(3,3)] = 1.0f; - - mat.m[Matrix_getIndex(2,3)] = znear / (znear - zfar); + Matrix4f_Orthographic(&mat, width, height, zfar, znear); if (!toPrevMatrix) { return RValue_makeArray(matrixToGml(&mat)); @@ -2907,7 +2930,7 @@ static RValue builtin_matrix_set(MAYBE_UNUSED VMContext *ctx, RValue *args, int3 int32_t Matrix = RValue_toInt32(args[0]); Matrix4f m; matrixFromGml(&m, args[1].array); - //return RValue_makeArray(matrixToGml(&ctx->runner->renderer->gmlMatrices[Matrix])); + //add safe guards or whatever itis if (ctx->runner->renderer != nullptr) { ctx->runner->renderer->vtable->setMatrix(ctx->runner->renderer, Matrix, m); } @@ -2915,7 +2938,6 @@ static RValue builtin_matrix_set(MAYBE_UNUSED VMContext *ctx, RValue *args, int3 return RValue_makeUndefined(); } - static RValue builtin_matrix_build_lookat(MAYBE_UNUSED VMContext *ctx, RValue *args, int32_t argCount) { if (argCount < 9 || argCount > 10) return RValue_makeUndefined(); @@ -2930,60 +2952,11 @@ static RValue builtin_matrix_build_lookat(MAYBE_UNUSED VMContext *ctx, RValue *a GMLReal xUp = RValue_toReal(args[6]); GMLReal yUp = RValue_toReal(args[7]); GMLReal zUp = RValue_toReal(args[8]); - GMLReal magUp = GMLReal_sqrt(xUp * xUp + yUp * yUp + zUp * zUp); - xUp /= magUp; - yUp /= magUp; - zUp /= magUp; - - GMLReal xLook = xTo - xFrom; - GMLReal yLook = yTo - yFrom; - GMLReal zLook = zTo - zFrom; - GMLReal magLook = GMLReal_sqrt(xLook * xLook + yLook * yLook + zLook * zLook); - xLook /= magLook; - yLook /= magLook; - zLook /= magLook; - - // normalised cross product between Up and Look - GMLReal xRight = yUp * zLook - zUp * yLook; - GMLReal yRight = zUp * xLook - xUp * zLook; - GMLReal zRight = xUp * yLook - yUp * xLook; - GMLReal magRight = GMLReal_sqrt(xRight * xRight + yRight * yRight + zRight * zRight); - xRight /= magRight; - yRight /= magRight; - zRight /= magRight; - - // normalised cross product between Look and Right - xUp = yLook * zRight - zLook * yRight; - yUp = zLook * xRight - xLook * zRight; - zUp = xLook * yRight - yLook * xRight; - magUp = GMLReal_sqrt(xUp * xUp + yUp * yUp + zUp * zUp); - xUp /= magUp; - yUp /= magUp; - zUp /= magUp; - - GMLReal x, y, z; - x = xFrom * xRight + yFrom * yRight + zFrom * zRight; - y = xFrom * xUp + yFrom * yUp + zFrom * zUp; - z = xFrom * xLook + yFrom * yLook + zFrom * zLook; Matrix4f matrix; Matrix4f_identity(&matrix); - matrix.m[Matrix_getIndex(0, 0)] = xRight; - matrix.m[Matrix_getIndex(1, 0)] = xUp; - matrix.m[Matrix_getIndex(2, 0)] = xLook; - - matrix.m[Matrix_getIndex(0, 1)] = yRight; - matrix.m[Matrix_getIndex(1, 1)] = yUp; - matrix.m[Matrix_getIndex(2, 1)] = yLook; - - matrix.m[Matrix_getIndex(0, 2)] = zRight; - matrix.m[Matrix_getIndex(1, 2)] = zUp; - matrix.m[Matrix_getIndex(2, 2)] = zLook; - - matrix.m[Matrix_getIndex(0, 3)] = -x; - matrix.m[Matrix_getIndex(1, 3)] = -y; - matrix.m[Matrix_getIndex(2, 3)] = -z; + Matrix4f_LookAt(&matrix, xFrom, yFrom, zFrom, xTo, yTo, zTo, xUp, yUp, zUp); bool toPrevMatrix = argCount == 10; GMLArray *destArray = toPrevMatrix ? args[9].array : nullptr; @@ -3486,8 +3459,17 @@ static RValue builtin_camera_set_view_pos(VMContext* ctx, RValue* args, int32_t Runner* runner = ctx->runner; GMLCamera* camera = Runner_getCameraById(runner, RValue_toInt32(args[0])); if (camera != nullptr) { - camera->viewX = RValue_toInt32(args[1]); - camera->viewY = RValue_toInt32(args[2]); + camera->viewX = RValue_toReal(args[1]); + camera->viewY = RValue_toReal(args[2]); + float x = camera->viewX + camera->viewWidth/2; + float y = camera->viewY + camera->viewHeight/2; + Matrix4f ViewMatrix; + Matrix4f_identity(&ViewMatrix); + Matrix4f_LookAt(&ViewMatrix, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0); + Matrix4f_translate(&ViewMatrix, x, y, 0.0f); + Matrix4f_rotateZ(&ViewMatrix, -camera->viewAngle * (float) M_PI / 180.0f); + Matrix4f_translate(&ViewMatrix, -x, -y, 0.0f); + camera->ViewMatrix = ViewMatrix; } return RValue_makeUndefined(); } @@ -3604,7 +3586,19 @@ static RValue builtin_camera_set_view_angle(VMContext* ctx, RValue* args, int32_ if (2 > argCount) return RValue_makeUndefined(); Runner* runner = ctx->runner; GMLCamera* camera = Runner_getCameraById(runner, RValue_toInt32(args[0])); - if (camera != nullptr) camera->viewAngle = (float) RValue_toReal(args[1]); + if (camera != nullptr) + { + camera->viewAngle = (float) RValue_toReal(args[1]); + float x = camera->viewX + camera->viewWidth/2; + float y = camera->viewY + camera->viewHeight/2; + Matrix4f ViewMatrix; + Matrix4f_identity(&ViewMatrix); + Matrix4f_LookAt(&ViewMatrix, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0); + Matrix4f_translate(&ViewMatrix, x, y, 0.0f); + Matrix4f_rotateZ(&ViewMatrix, -camera->viewAngle * (float) M_PI / 180.0f); + Matrix4f_translate(&ViewMatrix, -x, -y, 0.0f); + camera->ViewMatrix = ViewMatrix; + } return RValue_makeUndefined(); } @@ -3657,8 +3651,8 @@ static RValue builtin_camera_create_view(VMContext* ctx, RValue* args, int32_t a if (0 > id) return RValue_makeReal(-1); GMLCamera* camera = Runner_getCameraById(runner, id); // camera_create_view(room_x, room_y, room_w, room_h, [angle, object, x_speed, y_speed, x_border, y_border]) - if (argCount > 0) camera->viewX = RValue_toInt32(args[0]); - if (argCount > 1) camera->viewY = RValue_toInt32(args[1]); + if (argCount > 0) camera->viewX = RValue_toReal(args[0]); + if (argCount > 1) camera->viewY = RValue_toReal(args[1]); if (argCount > 2) camera->viewWidth = RValue_toInt32(args[2]); if (argCount > 3) camera->viewHeight = RValue_toInt32(args[3]); if (argCount > 4) camera->viewAngle = (float) RValue_toReal(args[4]); @@ -3668,83 +3662,19 @@ static RValue builtin_camera_create_view(VMContext* ctx, RValue* args, int32_t a if (argCount > 8) camera->borderX = (uint32_t) RValue_toInt32(args[8]); if (argCount > 9) camera->borderY = (uint32_t) RValue_toInt32(args[9]); - //what have I done. - Matrix4f Projection; - memset(Projection.m, 0, sizeof(Projection.m)); - Projection.m[Matrix_getIndex(0,0)] = 2.0f / RValue_toReal(args[2]); - Projection.m[Matrix_getIndex(1,1)] = 2.0f / RValue_toReal(args[3]); - Projection.m[Matrix_getIndex(2,2)] = 1.0f / (32000.0 - 0.0); - Projection.m[Matrix_getIndex(3,3)] = 1.0f; - Projection.m[Matrix_getIndex(2,3)] = 0.0 / (0.0 - 32000.0); + Matrix4f Projection; + Matrix4f_Orthographic(&Projection, camera->viewWidth, -camera->viewHeight, 32000.0, 0.0); camera->ProjectionMatrix = Projection; + //we will look at the center, okay? + float x = RValue_toReal(args[0]) + RValue_toReal(args[2])/2; + float y = RValue_toReal(args[1]) + RValue_toReal(args[3])/2; - GMLReal xFrom = RValue_toReal(args[0]) + RValue_toReal(args[2])/2.0f; - GMLReal yFrom = RValue_toReal(args[1]) + RValue_toReal(args[3])/2.0f; - GMLReal zFrom = -16000.0; - - GMLReal xTo = RValue_toReal(args[0]) + RValue_toReal(args[2])/2.0f; - GMLReal yTo = RValue_toReal(args[1]) + RValue_toReal(args[3])/2.0f; - GMLReal zTo = 16000.0; - - GMLReal xUp = 0.0; - GMLReal yUp = 1.0; - GMLReal zUp = 0.0; - GMLReal magUp = GMLReal_sqrt(xUp * xUp + yUp * yUp + zUp * zUp); - xUp /= magUp; - yUp /= magUp; - zUp /= magUp; - - GMLReal xLook = xTo - xFrom; - GMLReal yLook = yTo - yFrom; - GMLReal zLook = zTo - zFrom; - GMLReal magLook = GMLReal_sqrt(xLook * xLook + yLook * yLook + zLook * zLook); - xLook /= magLook; - yLook /= magLook; - zLook /= magLook; - - // normalised cross product between Up and Look - GMLReal xRight = yUp * zLook - zUp * yLook; - GMLReal yRight = zUp * xLook - xUp * zLook; - GMLReal zRight = xUp * yLook - yUp * xLook; - GMLReal magRight = GMLReal_sqrt(xRight * xRight + yRight * yRight + zRight * zRight); - xRight /= magRight; - yRight /= magRight; - zRight /= magRight; - - // normalised cross product between Look and Right - xUp = yLook * zRight - zLook * yRight; - yUp = zLook * xRight - xLook * zRight; - zUp = xLook * yRight - yLook * xRight; - magUp = GMLReal_sqrt(xUp * xUp + yUp * yUp + zUp * zUp); - xUp /= magUp; - yUp /= magUp; - zUp /= magUp; - - GMLReal x, y, z; - x = xFrom * xRight + yFrom * yRight + zFrom * zRight; - y = xFrom * xUp + yFrom * yUp + zFrom * zUp; - z = xFrom * xLook + yFrom * yLook + zFrom * zLook; - Matrix4f ViewMatrix; Matrix4f_identity(&ViewMatrix); - ViewMatrix.m[Matrix_getIndex(0, 0)] = xRight; - ViewMatrix.m[Matrix_getIndex(1, 0)] = xUp; - ViewMatrix.m[Matrix_getIndex(2, 0)] = xLook; - - ViewMatrix.m[Matrix_getIndex(0, 1)] = yRight; - ViewMatrix.m[Matrix_getIndex(1, 1)] = yUp; - ViewMatrix.m[Matrix_getIndex(2, 1)] = yLook; - - ViewMatrix.m[Matrix_getIndex(0, 2)] = zRight; - ViewMatrix.m[Matrix_getIndex(1, 2)] = zUp; - ViewMatrix.m[Matrix_getIndex(2, 2)] = zLook; - - ViewMatrix.m[Matrix_getIndex(0, 3)] = -x; - ViewMatrix.m[Matrix_getIndex(1, 3)] = -y; - ViewMatrix.m[Matrix_getIndex(2, 3)] = -z; + Matrix4f_LookAt(&ViewMatrix, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0); camera->ViewMatrix = ViewMatrix; //builtin_matrix_build_lookat(ctx,args[0],args[1],RValue_makeReal(-16000.0),args[0],args[1],RValue_makeReal(16000.0), RValue_makeReal(0.0),RValue_makeReal(1.0),RValue_makeReal(0.0)) From 004208021bdbc8f19168dd0a1d154af1aca518e2 Mon Sep 17 00:00:00 2001 From: Classic0306 <190026317+Classic0306@users.noreply.github.com> Date: Sat, 13 Jun 2026 20:09:53 +0200 Subject: [PATCH 06/16] clean up a little bit --- src/gl/gl_renderer.c | 2 +- src/runner.h | 1 - src/vm_builtins.c | 23 ++--------------------- 3 files changed, 3 insertions(+), 23 deletions(-) diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index affdfed7..d8b9454d 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -59,7 +59,7 @@ static const char* defaultFragmentShaderSource = "uniform sampler2D uTexture;\n" "uniform float uAlphaTestRef;\n" "uniform bool uAlphaTestEnabled;\n" -"uniform vec4 uFogColor;\n" // rgb = fog color, a = enable flag (0 or 1) + "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" diff --git a/src/runner.h b/src/runner.h index 7cb2b7a1..3790c4f5 100644 --- a/src/runner.h +++ b/src/runner.h @@ -155,7 +155,6 @@ typedef struct { int32_t speedY; int32_t objectId; // follow target (object index), -1 = none float viewAngle; - Matrix4f ViewMatrix; Matrix4f ProjectionMatrix; } GMLCamera; diff --git a/src/vm_builtins.c b/src/vm_builtins.c index 93877618..8f15c2db 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -3461,15 +3461,7 @@ static RValue builtin_camera_set_view_pos(VMContext* ctx, RValue* args, int32_t if (camera != nullptr) { camera->viewX = RValue_toReal(args[1]); camera->viewY = RValue_toReal(args[2]); - float x = camera->viewX + camera->viewWidth/2; - float y = camera->viewY + camera->viewHeight/2; - Matrix4f ViewMatrix; - Matrix4f_identity(&ViewMatrix); - Matrix4f_LookAt(&ViewMatrix, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0); - Matrix4f_translate(&ViewMatrix, x, y, 0.0f); - Matrix4f_rotateZ(&ViewMatrix, -camera->viewAngle * (float) M_PI / 180.0f); - Matrix4f_translate(&ViewMatrix, -x, -y, 0.0f); - camera->ViewMatrix = ViewMatrix; + UpdateCamera(camera); } return RValue_makeUndefined(); } @@ -3591,13 +3583,7 @@ static RValue builtin_camera_set_view_angle(VMContext* ctx, RValue* args, int32_ camera->viewAngle = (float) RValue_toReal(args[1]); float x = camera->viewX + camera->viewWidth/2; float y = camera->viewY + camera->viewHeight/2; - Matrix4f ViewMatrix; - Matrix4f_identity(&ViewMatrix); - Matrix4f_LookAt(&ViewMatrix, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0); - Matrix4f_translate(&ViewMatrix, x, y, 0.0f); - Matrix4f_rotateZ(&ViewMatrix, -camera->viewAngle * (float) M_PI / 180.0f); - Matrix4f_translate(&ViewMatrix, -x, -y, 0.0f); - camera->ViewMatrix = ViewMatrix; + UpdateCamera(camera); } return RValue_makeUndefined(); } @@ -3673,14 +3659,9 @@ static RValue builtin_camera_create_view(VMContext* ctx, RValue* args, int32_t a Matrix4f ViewMatrix; Matrix4f_identity(&ViewMatrix); - Matrix4f_LookAt(&ViewMatrix, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0); camera->ViewMatrix = ViewMatrix; - //builtin_matrix_build_lookat(ctx,args[0],args[1],RValue_makeReal(-16000.0),args[0],args[1],RValue_makeReal(16000.0), RValue_makeReal(0.0),RValue_makeReal(1.0),RValue_makeReal(0.0)) - //builtin_matrix_build_projection_ortho(ctx,args[2], args[3], RValue_makeReal(0.0), RValue_makeReal(32000.0)); - - return RValue_makeReal(id); } From c14c882278accd35ef72f628dff6830627c4b08e Mon Sep 17 00:00:00 2001 From: Classic0306 <190026317+Classic0306@users.noreply.github.com> Date: Sun, 14 Jun 2026 11:43:40 +0200 Subject: [PATCH 07/16] make rendering to surfaces work in a hacky way --- src/gl/gl_renderer.c | 46 +++++++++++++++++++++++++++------------- src/renderer.h | 4 ++++ src/runner.c | 50 +++++++++++++++++++++++++++++++------------- src/vm_builtins.c | 13 +----------- 4 files changed, 71 insertions(+), 42 deletions(-) diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index d8b9454d..8dff402b 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -570,9 +570,7 @@ static void glApplyProjection(Renderer* renderer, const Matrix4f* ViewMatrix,con renderer->gmlMatrices[MATRIX_WORLD_VIEW] = WorldView; renderer->gmlMatrices[MATRIX_WORLD_VIEW_PROJECTION] = WorldViewProjection; //oh my I hope it's good enough. - glShaderSettingsRefresh(renderer); - renderer->previousViewMatrix = WorldViewProjection; - + glShaderSettingsRefresh(renderer); } static void glBeginGUI(Renderer* renderer, int32_t guiW, int32_t guiH, int32_t portX, int32_t portY, int32_t portW, int32_t portH, int32_t targetSurfaceId) { @@ -596,10 +594,10 @@ static void glBeginGUI(Renderer* renderer, int32_t guiW, int32_t guiH, int32_t p glEnable(GL_SCISSOR_TEST); - Matrix4f projection; - Matrix4f_guiProjection(&projection, (float) guiW, (float) guiH, (float) portW, (float) portH); - Matrix4f_flipClipY(&projection); - renderer->gmlMatrices[MATRIX_WORLD_VIEW_PROJECTION] = projection; + //Matrix4f projection; + //Matrix4f_guiProjection(&projection, (float) guiW, (float) guiH, (float) portW, (float) portH); + //Matrix4f_flipClipY(&projection); + //renderer->gmlMatrices[MATRIX_WORLD_VIEW_PROJECTION] = projection; glShaderSettingsRefresh(renderer); glActiveTexture(GL_TEXTURE1); @@ -660,11 +658,11 @@ static void glClearScreen(Renderer* renderer, uint32_t color, float alpha) { float b = (float) BGR_B(color) / 255.0f; // GML draw_clear ignores the active scissor and clears the whole target. Disable scissor for the clear and restore it after. - GLboolean scissorWasEnabled = glIsEnabled(GL_SCISSOR_TEST); - if (scissorWasEnabled) glDisable(GL_SCISSOR_TEST); + //GLboolean scissorWasEnabled = glIsEnabled(GL_SCISSOR_TEST); + //if (scissorWasEnabled) glDisable(GL_SCISSOR_TEST); glClearColor(r, g, b, alpha); glClear(GL_COLOR_BUFFER_BIT); - if (scissorWasEnabled) glEnable(GL_SCISSOR_TEST); + //if (scissorWasEnabled) glEnable(GL_SCISSOR_TEST); } // Lazily decodes and uploads a TXTR page on first access. @@ -1988,18 +1986,36 @@ static bool glSetRenderTarget(Renderer* renderer, int32_t surfaceId, bool implic if (surfaceId == renderer->runner->applicationSurfaceId && implicitApplicationSurface) { glViewport(gl->base.CPortX, gl->base.CPortY, gl->base.CPortW, gl->base.CPortH); glEnable(GL_SCISSOR_TEST); - renderer->gmlMatrices[MATRIX_WORLD_VIEW_PROJECTION] = renderer->previousViewMatrix; + glApplyProjection(renderer, &renderer->V_ViewMatrix,&renderer->V_ProjectionMatrix); glShaderSettingsRefresh(renderer); 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 projection; + //Matrix4f_identity(&projection); + //Matrix4f_ortho(&projection, 0.0f, (float) gl->surfaceWidth[surfaceId], (float) gl->surfaceHeight[surfaceId], 0.0f, -1.0f, 1.0f); + //glViewport(0, 0, gl->surfaceWidth[surfaceId], gl->surfaceHeight[surfaceId]); + //glDisable(GL_SCISSOR_TEST); + //renderer->gmlMatrices[MATRIX_WORLD_VIEW_PROJECTION] = projection; + if (surfaceId == renderer->V_SurfaceID) { + glApplyProjection(renderer, &renderer->V_ViewMatrix,&renderer->V_ProjectionMatrix); + + } else { + Matrix4f ProjectionMatrix; + Matrix4f_Orthographic(&ProjectionMatrix, (float) gl->surfaceWidth[surfaceId], (float) -gl->surfaceHeight[surfaceId], 32000.0, 0.0); + + Matrix4f ViewMatrix; + float x = (float) gl->surfaceWidth[surfaceId] /2; + float y = (float) gl->surfaceHeight[surfaceId] /2; + Matrix4f_identity(&ViewMatrix); + Matrix4f_LookAt(&ViewMatrix, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0); + glApplyProjection(renderer, &ViewMatrix,&ProjectionMatrix); + } + + glViewport(0, 0, gl->surfaceWidth[surfaceId], gl->surfaceHeight[surfaceId]); glDisable(GL_SCISSOR_TEST); - renderer->gmlMatrices[MATRIX_WORLD_VIEW_PROJECTION] = projection; glShaderSettingsRefresh(renderer); return true; diff --git a/src/renderer.h b/src/renderer.h index f9cb3a30..4e321c1c 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -8,6 +8,7 @@ #include "data_win.h" #include "instance.h" + // GameMaker Blend Modes #define bm_complex -1 @@ -172,6 +173,9 @@ struct Renderer { Runner* runner; Matrix4f gmlMatrices[MATRICES_MAX]; int32_t currentShader; + Matrix4f V_ViewMatrix; + Matrix4f V_ProjectionMatrix; + int32_t V_SurfaceID; }; // ===[ Shared Helpers (platform-agnostic) ]=== diff --git a/src/runner.c b/src/runner.c index d4e63e0f..54fcf62e 100644 --- a/src/runner.c +++ b/src/runner.c @@ -1024,16 +1024,19 @@ void Runner_drawGUI(Runner* runner, int32_t windowW, int32_t windowH, int32_t ta beginGuiPass(runner, guiW, guiH, windowW, windowH, RENDER_TARGET_HOST_FRAMEBUFFER); //make default projection - Matrix4f Projection; - Matrix4f_Orthographic(&Projection, (float) guiW, (float) guiH, 32000.0, 0.0); + Matrix4f ProjectionMatrix; + Matrix4f_Orthographic(&ProjectionMatrix, (float) guiW, (float) guiH, 32000.0, 0.0); - Matrix4f View; + Matrix4f ViewMatrix; float x = (float) guiW / 2; float y = (float) guiH / 2; - Matrix4f_identity(&View); - Matrix4f_LookAt(&View, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0); + Matrix4f_identity(&ViewMatrix); + Matrix4f_LookAt(&ViewMatrix, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0); - runner->renderer->vtable->applyProjection(runner->renderer, &View, &Projection); + runner->renderer->vtable->applyProjection(runner->renderer, &ViewMatrix, &ProjectionMatrix); + runner->renderer->V_ViewMatrix = ViewMatrix; + runner->renderer->V_ProjectionMatrix = ProjectionMatrix; + runner->renderer->V_SurfaceID = -1; fireDrawSubtype(runner, drawables, drawableCount, DRAW_GUI_BEGIN); fireDrawSubtype(runner, drawables, drawableCount, DRAW_GUI); @@ -1146,7 +1149,9 @@ void Runner_drawViews(Runner* runner, int32_t gameW, int32_t gameH, bool debugSh Matrix4f ViewMatrix = camera->ViewMatrix; Matrix4f ProjectionMatrix = camera->ProjectionMatrix; - + renderer->V_ViewMatrix = ViewMatrix; + renderer->V_ProjectionMatrix = ProjectionMatrix; + renderer->V_SurfaceID = view->surfaceId; runner->renderer->vtable->applyProjection(runner->renderer, &ViewMatrix, &ProjectionMatrix); runner->viewCurrent = (int32_t) vi; @@ -1174,7 +1179,9 @@ void Runner_drawViews(Runner* runner, int32_t gameW, int32_t gameH, bool debugSh Matrix4f ViewMatrix = camera->ViewMatrix; Matrix4f ProjectionMatrix = camera->ProjectionMatrix; - //what am I even doing. + renderer->V_ViewMatrix = ViewMatrix; + renderer->V_ProjectionMatrix = ProjectionMatrix; + renderer->V_SurfaceID = -1; runner->renderer->vtable->applyProjection(runner->renderer, &ViewMatrix, &ProjectionMatrix); Runner_draw(runner); @@ -1197,16 +1204,23 @@ void Runner_drawViews(Runner* runner, int32_t gameW, int32_t gameH, bool debugSh renderer->vtable->beginView(renderer, viewX, viewY, viewW, viewH, 0, 0, gameW, gameH, 0); //make default projection - Matrix4f Projection; - Matrix4f_Orthographic(&Projection, (float) gameW, (float) -gameH, 32000.0, 0.0); + Matrix4f ProjectionMatrix; + Matrix4f_Orthographic(&ProjectionMatrix, (float) gameW, (float) -gameH, 32000.0, 0.0); - Matrix4f View; + Matrix4f ViewMatrix; float x = (float) gameW /2; float y = (float) gameH /2; - Matrix4f_identity(&View); - Matrix4f_LookAt(&View, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0); - - runner->renderer->vtable->applyProjection(runner->renderer, &View, &Projection); + Matrix4f_identity(&ViewMatrix); + Matrix4f_LookAt(&ViewMatrix, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0); + renderer->V_ViewMatrix = ViewMatrix; + renderer->V_ProjectionMatrix = ProjectionMatrix; + if (camera != nullptr) { + camera->ViewMatrix = ViewMatrix; + camera->ProjectionMatrix = ProjectionMatrix; + } + + renderer->V_SurfaceID = -1; + runner->renderer->vtable->applyProjection(runner->renderer, &ViewMatrix, &ProjectionMatrix); Runner_draw(runner); if (debugShowCollisionMasks) DebugOverlay_drawCollisionMasks(runner); @@ -3920,6 +3934,9 @@ bool Runner_surfaceSetTarget(Runner* runner, int32_t surfaceID) { runner->surfaceStack[slot] = surfaceID; runner->renderer->vtable->flush(runner->renderer); + GMLCamera* camera = Runner_getCameraForView(runner, (int32_t) runner->viewCurrent); + runner->renderer->V_ProjectionMatrix = camera->ProjectionMatrix; + runner->renderer->V_ViewMatrix = camera->ViewMatrix; return runner->renderer->vtable->setRenderTarget(runner->renderer, surfaceID, false); } @@ -3934,6 +3951,9 @@ bool Runner_surfaceResetTarget(Runner* runner) { int32_t newTop = findStackTop(runner); int32_t newTarget = newTop == -1 ? runner->applicationSurfaceId : runner->surfaceStack[newTop]; + GMLCamera* camera = Runner_getCameraForView(runner, (int32_t) runner->viewCurrent); + runner->renderer->V_ProjectionMatrix = camera->ProjectionMatrix; + runner->renderer->V_ViewMatrix = camera->ViewMatrix; runner->renderer->vtable->setRenderTarget(runner->renderer, newTarget, newTop == -1); if (newTop == -1 && runner->inGuiPass) { // Inside Pre Draw / Post Draw / Draw GUI the base target is the GUI pass target with the GUI projection, not the room view. diff --git a/src/vm_builtins.c b/src/vm_builtins.c index 8f15c2db..57e6aee8 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -3649,18 +3649,7 @@ static RValue builtin_camera_create_view(VMContext* ctx, RValue* args, int32_t a if (argCount > 9) camera->borderY = (uint32_t) RValue_toInt32(args[9]); - Matrix4f Projection; - Matrix4f_Orthographic(&Projection, camera->viewWidth, -camera->viewHeight, 32000.0, 0.0); - camera->ProjectionMatrix = Projection; - //we will look at the center, okay? - float x = RValue_toReal(args[0]) + RValue_toReal(args[2])/2; - float y = RValue_toReal(args[1]) + RValue_toReal(args[3])/2; - - - Matrix4f ViewMatrix; - Matrix4f_identity(&ViewMatrix); - Matrix4f_LookAt(&ViewMatrix, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0); - camera->ViewMatrix = ViewMatrix; + UpdateCamera(camera); return RValue_makeReal(id); } From 7fe2725b5be0311b768e35362dee4d1a27998d68 Mon Sep 17 00:00:00 2001 From: Classic0306 <190026317+Classic0306@users.noreply.github.com> Date: Sun, 14 Jun 2026 15:04:47 +0200 Subject: [PATCH 08/16] add and remove some comments --- src/gl/gl_renderer.c | 10 ++-------- src/renderer.h | 2 +- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index 8dff402b..fab73045 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -1991,16 +1991,10 @@ static bool glSetRenderTarget(Renderer* renderer, int32_t surfaceId, bool implic 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); - //glViewport(0, 0, gl->surfaceWidth[surfaceId], gl->surfaceHeight[surfaceId]); - //glDisable(GL_SCISSOR_TEST); - //renderer->gmlMatrices[MATRIX_WORLD_VIEW_PROJECTION] = projection; + if (surfaceId == renderer->V_SurfaceID) { + //we go back to the camera's settings for this glApplyProjection(renderer, &renderer->V_ViewMatrix,&renderer->V_ProjectionMatrix); - } else { Matrix4f ProjectionMatrix; Matrix4f_Orthographic(&ProjectionMatrix, (float) gl->surfaceWidth[surfaceId], (float) -gl->surfaceHeight[surfaceId], 32000.0, 0.0); diff --git a/src/renderer.h b/src/renderer.h index 4e321c1c..4325322e 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -165,7 +165,7 @@ struct Renderer { int32_t drawValign; // 0=top, 1=middle, 2=bottom int32_t circlePrecision; // segments used by draw_circle/draw_ellipse, clamped to [4, 64] and rounded down to multiple of 4. Default 24. //It's The Simplest Way I Found To Restore Previous Thingies For Rendering SORRY - Matrix4f previousViewMatrix; + Matrix4f previousViewMatrix; //when you go fix the Legacy OpenGL renderer, please remove this, as we don't need this anymore I hope int32_t CPortX; int32_t CPortY; int32_t CPortW; From 61ad399221ab22e28e7f687870a281d94fd5e08f Mon Sep 17 00:00:00 2001 From: Classic0306 <190026317+Classic0306@users.noreply.github.com> Date: Sun, 14 Jun 2026 20:47:16 +0200 Subject: [PATCH 09/16] I think I've made spaghetti --- src/gl/gl_renderer.c | 22 ++++++++++++++++++++++ src/renderer.h | 3 +++ src/runner.c | 4 ++++ src/runner.h | 1 + src/vm_builtins.c | 9 ++++++++- 5 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index fab73045..08641b10 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -1987,6 +1987,7 @@ static bool glSetRenderTarget(Renderer* renderer, int32_t surfaceId, bool implic glViewport(gl->base.CPortX, gl->base.CPortY, gl->base.CPortW, gl->base.CPortH); glEnable(GL_SCISSOR_TEST); glApplyProjection(renderer, &renderer->V_ViewMatrix,&renderer->V_ProjectionMatrix); + gl->base.CameraCurrent = renderer->runner->viewCurrent; glShaderSettingsRefresh(renderer); return true; } @@ -1995,6 +1996,7 @@ static bool glSetRenderTarget(Renderer* renderer, int32_t surfaceId, bool implic if (surfaceId == renderer->V_SurfaceID) { //we go back to the camera's settings for this glApplyProjection(renderer, &renderer->V_ViewMatrix,&renderer->V_ProjectionMatrix); + gl->base.CameraCurrent = renderer->runner->viewCurrent; } else { Matrix4f ProjectionMatrix; Matrix4f_Orthographic(&ProjectionMatrix, (float) gl->surfaceWidth[surfaceId], (float) -gl->surfaceHeight[surfaceId], 32000.0, 0.0); @@ -2005,6 +2007,24 @@ static bool glSetRenderTarget(Renderer* renderer, int32_t surfaceId, bool implic Matrix4f_identity(&ViewMatrix); Matrix4f_LookAt(&ViewMatrix, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0); glApplyProjection(renderer, &ViewMatrix,&ProjectionMatrix); + gl->base.CameraCurrent = SURFACE_CAMERA; + + GMLCamera* camera = &renderer->runner->surfaceCamera; + + camera->allocated = true; + camera->viewX = 0.0; + camera->viewY = 0.0; + camera->viewWidth = gl->surfaceWidth[surfaceId]; + camera->viewHeight = gl->surfaceHeight[surfaceId]; + camera->borderX = 0; + camera->borderY = 0; + camera->speedX = 0; + camera->speedY = 0; + camera->objectId = -1; + camera->viewAngle = 0; + + camera->ProjectionMatrix = ProjectionMatrix; + camera->ViewMatrix = ViewMatrix; } @@ -2603,5 +2623,7 @@ Renderer* GLRenderer_create(void) { gl->base.drawValign = 0; gl->base.circlePrecision = 24; gl->base.currentShader = -1; + gl->base.V_SurfaceID = -1; + gl->base.CameraCurrent = 0; return (Renderer*) gl; } diff --git a/src/renderer.h b/src/renderer.h index 4325322e..1c6b07e7 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -42,6 +42,8 @@ #define MAX_TEXTURE_STAGES 8 +#define SURFACE_CAMERA 8192 + // 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. @@ -176,6 +178,7 @@ struct Renderer { Matrix4f V_ViewMatrix; Matrix4f V_ProjectionMatrix; int32_t V_SurfaceID; + int32_t CameraCurrent; }; // ===[ Shared Helpers (platform-agnostic) ]=== diff --git a/src/runner.c b/src/runner.c index 54fcf62e..9293094c 100644 --- a/src/runner.c +++ b/src/runner.c @@ -1155,6 +1155,7 @@ void Runner_drawViews(Runner* runner, int32_t gameW, int32_t gameH, bool debugSh runner->renderer->vtable->applyProjection(runner->renderer, &ViewMatrix, &ProjectionMatrix); runner->viewCurrent = (int32_t) vi; + runner->renderer->CameraCurrent = runner->viewCurrent; Runner_draw(runner); renderer->vtable->flush(renderer); @@ -1175,6 +1176,7 @@ void Runner_drawViews(Runner* runner, int32_t gameW, int32_t gameH, bool debugSh float viewAngle = camera->viewAngle; runner->viewCurrent = (int32_t) vi; + runner->renderer->CameraCurrent = runner->viewCurrent; renderer->vtable->beginView(renderer, viewX, viewY, viewW, viewH, portX, portY, portW, portH, viewAngle); Matrix4f ViewMatrix = camera->ViewMatrix; @@ -1231,6 +1233,7 @@ void Runner_drawViews(Runner* runner, int32_t gameW, int32_t gameH, bool debugSh // Reset view_current to 0 so non-Draw events (Step, Alarm, Create) see view_current = 0 runner->viewCurrent = 0; + runner->renderer->CameraCurrent = runner->viewCurrent; } // ===[ Instance Creation Helper ]=== @@ -1332,6 +1335,7 @@ GMLCamera* Runner_getCameraById(Runner* runner, int32_t id) { if (0 > id) return nullptr; else if (MAX_DEFAULT_ROOM_CAMERAS > id) camera = &runner->defaultCameras[id]; else if (MAX_CAMERAS > id) camera = &runner->userCameras[id - MAX_DEFAULT_ROOM_CAMERAS]; + else if (id == 8192) camera = &runner->surfaceCamera; else return nullptr; if (!camera->allocated) return nullptr; return camera; diff --git a/src/runner.h b/src/runner.h index 3790c4f5..d76cdc09 100644 --- a/src/runner.h +++ b/src/runner.h @@ -472,6 +472,7 @@ struct Runner { RuntimeView views[MAX_VIEWS]; GMLCamera defaultCameras[MAX_DEFAULT_ROOM_CAMERAS]; GMLCamera userCameras[MAX_USER_CAMERAS]; + GMLCamera surfaceCamera; RunnerGamepadState* gamepads; RuntimeBackground backgrounds[8]; uint32_t backgroundColor; // runtime-mutable (BGR format) diff --git a/src/vm_builtins.c b/src/vm_builtins.c index 57e6aee8..a449f910 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -226,7 +226,13 @@ static void UpdateCamera(GMLCamera* camera) { Matrix4f_translate(&ViewMatrix, x, y, 0.0f); Matrix4f_rotateZ(&ViewMatrix, -camera->viewAngle * (float) M_PI / 180.0f); Matrix4f_translate(&ViewMatrix, -x, -y, 0.0f); + + Matrix4f ProjectionMatrix; + Matrix4f_Orthographic(&ProjectionMatrix, (float) camera->viewWidth, (float) -camera->viewHeight, 32000.0, 0.0); + + camera->ViewMatrix = ViewMatrix; + camera->ProjectionMatrix = ProjectionMatrix; } @@ -3685,7 +3691,8 @@ static RValue builtin_view_set_camera(VMContext* ctx, RValue* args, int32_t argC static RValue builtin_camera_get_active(VMContext* ctx, MAYBE_UNUSED RValue* args, MAYBE_UNUSED int32_t argCount) { Runner* runner = ctx->runner; if (runner->viewCurrent >= 0 && MAX_VIEWS > runner->viewCurrent) { - return RValue_makeReal(runner->views[runner->viewCurrent].cameraId); + //return RValue_makeReal(runner->views[runner->viewCurrent].cameraId); + return RValue_makeReal(runner->renderer->CameraCurrent); } return RValue_makeReal(-1); } From 7c4f0f06c18cbc282a82354791cae55617160a70 Mon Sep 17 00:00:00 2001 From: Classic0306 <190026317+Classic0306@users.noreply.github.com> Date: Sun, 14 Jun 2026 22:34:50 +0200 Subject: [PATCH 10/16] clean up a little bit --- src/gl/gl_renderer.c | 5 ++--- src/gl/gl_renderer.h | 2 -- src/renderer.h | 1 - src/runner.c | 6 +++--- src/vm_builtins.c | 16 ++-------------- 5 files changed, 7 insertions(+), 23 deletions(-) diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index 08641b10..16e89603 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -658,11 +658,10 @@ static void glClearScreen(Renderer* renderer, uint32_t color, float alpha) { float b = (float) BGR_B(color) / 255.0f; // GML draw_clear ignores the active scissor and clears the whole target. Disable scissor for the clear and restore it after. - //GLboolean scissorWasEnabled = glIsEnabled(GL_SCISSOR_TEST); - //if (scissorWasEnabled) glDisable(GL_SCISSOR_TEST); + //No it doesn't? glClearColor(r, g, b, alpha); glClear(GL_COLOR_BUFFER_BIT); - //if (scissorWasEnabled) glEnable(GL_SCISSOR_TEST); + } // Lazily decodes and uploads a TXTR page on first access. diff --git a/src/gl/gl_renderer.h b/src/gl/gl_renderer.h index 71909234..7e3b13db 100644 --- a/src/gl/gl_renderer.h +++ b/src/gl/gl_renderer.h @@ -42,8 +42,6 @@ typedef struct { bool colorWriteR, colorWriteG, colorWriteB, colorWriteA; bool fogEnable; uint32_t fogColor; // BGR - float fogStart; - float fogEnd; GLuint vao, vbo, ebo; float* vertexData; // MAX_QUADS * VERTICES_PER_QUAD * FLOATS_PER_VERTEX floats diff --git a/src/renderer.h b/src/renderer.h index 1c6b07e7..aba16625 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -8,7 +8,6 @@ #include "data_win.h" #include "instance.h" - // GameMaker Blend Modes #define bm_complex -1 diff --git a/src/runner.c b/src/runner.c index 9293094c..50e3e390 100644 --- a/src/runner.c +++ b/src/runner.c @@ -1155,7 +1155,7 @@ void Runner_drawViews(Runner* runner, int32_t gameW, int32_t gameH, bool debugSh runner->renderer->vtable->applyProjection(runner->renderer, &ViewMatrix, &ProjectionMatrix); runner->viewCurrent = (int32_t) vi; - runner->renderer->CameraCurrent = runner->viewCurrent; + runner->renderer->CameraCurrent = runner->views[runner->viewCurrent].cameraId; Runner_draw(runner); renderer->vtable->flush(renderer); @@ -1176,7 +1176,7 @@ void Runner_drawViews(Runner* runner, int32_t gameW, int32_t gameH, bool debugSh float viewAngle = camera->viewAngle; runner->viewCurrent = (int32_t) vi; - runner->renderer->CameraCurrent = runner->viewCurrent; + runner->renderer->CameraCurrent = runner->views[runner->viewCurrent].cameraId; renderer->vtable->beginView(renderer, viewX, viewY, viewW, viewH, portX, portY, portW, portH, viewAngle); Matrix4f ViewMatrix = camera->ViewMatrix; @@ -1233,7 +1233,7 @@ void Runner_drawViews(Runner* runner, int32_t gameW, int32_t gameH, bool debugSh // Reset view_current to 0 so non-Draw events (Step, Alarm, Create) see view_current = 0 runner->viewCurrent = 0; - runner->renderer->CameraCurrent = runner->viewCurrent; + runner->renderer->CameraCurrent = runner->views[runner->viewCurrent].cameraId; } // ===[ Instance Creation Helper ]=== diff --git a/src/vm_builtins.c b/src/vm_builtins.c index a449f910..223681d9 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -3505,11 +3505,6 @@ static RValue builtin_camera_set_proj_mat(VMContext* ctx, RValue* args, int32_t if (camera == nullptr || !rvalueIsMatrix(args[1])) return RValue_makeUndefined(); Matrix4f m; matrixFromGml(&m, args[1].array); - // Orthographic projection: m[0,0] = 2/width, m[1,1] = 2/height. - GMLReal m00 = m.m[Matrix_getIndex(0, 0)]; - GMLReal m11 = m.m[Matrix_getIndex(1, 1)]; - if (m00 != 0.0) camera->viewWidth = (int32_t) lround(GMLReal_fabs(2.0 / m00)); - if (m11 != 0.0) camera->viewHeight = (int32_t) lround(GMLReal_fabs(2.0 / m11)); camera->ProjectionMatrix = m; camera->ProjectionMatrix.m[Matrix_getIndex(1, 1)] = -m.m[Matrix_getIndex(1, 1)]; return RValue_makeUndefined(); @@ -3587,8 +3582,6 @@ static RValue builtin_camera_set_view_angle(VMContext* ctx, RValue* args, int32_ if (camera != nullptr) { camera->viewAngle = (float) RValue_toReal(args[1]); - float x = camera->viewX + camera->viewWidth/2; - float y = camera->viewY + camera->viewHeight/2; UpdateCamera(camera); } return RValue_makeUndefined(); @@ -3709,13 +3702,8 @@ static RValue builtin_camera_apply(VMContext* ctx, RValue* args, int32_t argCoun if (1 > argCount) return RValue_makeUndefined(); Runner* runner = ctx->runner; GMLCamera* camera = Runner_getCameraById(runner, RValue_toInt32(args[0])); - if (camera != nullptr) { - - Matrix4f ViewMatrix = camera->ViewMatrix; - Matrix4f ProjectionMatrix = camera->ProjectionMatrix; - - runner->renderer->vtable->applyProjection(runner->renderer, &ViewMatrix, &ProjectionMatrix); - + if (camera != nullptr) { + runner->renderer->vtable->applyProjection(runner->renderer, &camera->ViewMatrix, &camera->ProjectionMatrix); } return RValue_makeUndefined(); } From b1c591d2453dc95fe897bf7d368efaa2b8767e5f Mon Sep 17 00:00:00 2001 From: Classic0306 <190026317+Classic0306@users.noreply.github.com> Date: Mon, 15 Jun 2026 22:28:24 +0200 Subject: [PATCH 11/16] remove hacks and hopefully it's good enough --- src/gl/gl_renderer.c | 32 ++++++++++++++++++++++---------- src/renderer.h | 3 --- src/runner.c | 40 +++++++++++----------------------------- src/vm_builtins.c | 23 +++++++++++------------ 4 files changed, 44 insertions(+), 54 deletions(-) diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index 16e89603..e5e94c37 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -1976,6 +1976,15 @@ static bool glSurfaceGetPixels(Renderer* renderer, int32_t surfaceId, uint8_t* o static bool glSetRenderTarget(Renderer* renderer, int32_t surfaceId, bool implicitApplicationSurface) { GLRenderer* gl = (GLRenderer*) renderer; + flushBatch(gl); + + int32_t ViewCurrent = 0; + if (renderer->runner->viewsEnabled) { + ViewCurrent = renderer->runner->viewCurrent; + } + RuntimeView* view = &renderer->runner->views[ViewCurrent]; + gl->base.CameraCurrent = view->cameraId; + GMLCamera* camera = Runner_getCameraById(renderer->runner, gl->base.CameraCurrent); if (0 > surfaceId || (uint32_t) surfaceId >= gl->surfaceCount) return false; if (gl->surfaces[surfaceId] == 0) return false; @@ -1985,17 +1994,19 @@ static bool glSetRenderTarget(Renderer* renderer, int32_t surfaceId, bool implic if (surfaceId == renderer->runner->applicationSurfaceId && implicitApplicationSurface) { glViewport(gl->base.CPortX, gl->base.CPortY, gl->base.CPortW, gl->base.CPortH); glEnable(GL_SCISSOR_TEST); - glApplyProjection(renderer, &renderer->V_ViewMatrix,&renderer->V_ProjectionMatrix); - gl->base.CameraCurrent = renderer->runner->viewCurrent; - glShaderSettingsRefresh(renderer); + + glApplyProjection(renderer,&camera->ViewMatrix,&camera->ProjectionMatrix); + return true; } - if (surfaceId == renderer->V_SurfaceID) { - //we go back to the camera's settings for this - glApplyProjection(renderer, &renderer->V_ViewMatrix,&renderer->V_ProjectionMatrix); - gl->base.CameraCurrent = renderer->runner->viewCurrent; + if (surfaceId == view->surfaceId) { + //the surface belongs to the view we are rending, we use the view's camera. + glViewport(0, 0, gl->surfaceWidth[surfaceId], gl->surfaceHeight[surfaceId]); + glDisable(GL_SCISSOR_TEST); + glApplyProjection(renderer,&camera->ViewMatrix,&camera->ProjectionMatrix); + return true; } else { Matrix4f ProjectionMatrix; Matrix4f_Orthographic(&ProjectionMatrix, (float) gl->surfaceWidth[surfaceId], (float) -gl->surfaceHeight[surfaceId], 32000.0, 0.0); @@ -2005,7 +2016,6 @@ static bool glSetRenderTarget(Renderer* renderer, int32_t surfaceId, bool implic float y = (float) gl->surfaceHeight[surfaceId] /2; Matrix4f_identity(&ViewMatrix); Matrix4f_LookAt(&ViewMatrix, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0); - glApplyProjection(renderer, &ViewMatrix,&ProjectionMatrix); gl->base.CameraCurrent = SURFACE_CAMERA; GMLCamera* camera = &renderer->runner->surfaceCamera; @@ -2024,12 +2034,15 @@ static bool glSetRenderTarget(Renderer* renderer, int32_t surfaceId, bool implic camera->ProjectionMatrix = ProjectionMatrix; camera->ViewMatrix = ViewMatrix; + glViewport(0, 0, gl->surfaceWidth[surfaceId], gl->surfaceHeight[surfaceId]); + glDisable(GL_SCISSOR_TEST); + glApplyProjection(renderer, &ViewMatrix,&ProjectionMatrix); + return true; } glViewport(0, 0, gl->surfaceWidth[surfaceId], gl->surfaceHeight[surfaceId]); glDisable(GL_SCISSOR_TEST); - glShaderSettingsRefresh(renderer); return true; } @@ -2622,7 +2635,6 @@ Renderer* GLRenderer_create(void) { gl->base.drawValign = 0; gl->base.circlePrecision = 24; gl->base.currentShader = -1; - gl->base.V_SurfaceID = -1; gl->base.CameraCurrent = 0; return (Renderer*) gl; } diff --git a/src/renderer.h b/src/renderer.h index aba16625..4da9d52e 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -174,9 +174,6 @@ struct Renderer { Runner* runner; Matrix4f gmlMatrices[MATRICES_MAX]; int32_t currentShader; - Matrix4f V_ViewMatrix; - Matrix4f V_ProjectionMatrix; - int32_t V_SurfaceID; int32_t CameraCurrent; }; diff --git a/src/runner.c b/src/runner.c index 50e3e390..66b53104 100644 --- a/src/runner.c +++ b/src/runner.c @@ -1034,9 +1034,6 @@ void Runner_drawGUI(Runner* runner, int32_t windowW, int32_t windowH, int32_t ta Matrix4f_LookAt(&ViewMatrix, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0); runner->renderer->vtable->applyProjection(runner->renderer, &ViewMatrix, &ProjectionMatrix); - runner->renderer->V_ViewMatrix = ViewMatrix; - runner->renderer->V_ProjectionMatrix = ProjectionMatrix; - runner->renderer->V_SurfaceID = -1; fireDrawSubtype(runner, drawables, drawableCount, DRAW_GUI_BEGIN); fireDrawSubtype(runner, drawables, drawableCount, DRAW_GUI); @@ -1149,9 +1146,6 @@ void Runner_drawViews(Runner* runner, int32_t gameW, int32_t gameH, bool debugSh Matrix4f ViewMatrix = camera->ViewMatrix; Matrix4f ProjectionMatrix = camera->ProjectionMatrix; - renderer->V_ViewMatrix = ViewMatrix; - renderer->V_ProjectionMatrix = ProjectionMatrix; - renderer->V_SurfaceID = view->surfaceId; runner->renderer->vtable->applyProjection(runner->renderer, &ViewMatrix, &ProjectionMatrix); runner->viewCurrent = (int32_t) vi; @@ -1181,9 +1175,6 @@ void Runner_drawViews(Runner* runner, int32_t gameW, int32_t gameH, bool debugSh Matrix4f ViewMatrix = camera->ViewMatrix; Matrix4f ProjectionMatrix = camera->ProjectionMatrix; - renderer->V_ViewMatrix = ViewMatrix; - renderer->V_ProjectionMatrix = ProjectionMatrix; - renderer->V_SurfaceID = -1; runner->renderer->vtable->applyProjection(runner->renderer, &ViewMatrix, &ProjectionMatrix); Runner_draw(runner); @@ -1214,14 +1205,11 @@ void Runner_drawViews(Runner* runner, int32_t gameW, int32_t gameH, bool debugSh float y = (float) gameH /2; Matrix4f_identity(&ViewMatrix); Matrix4f_LookAt(&ViewMatrix, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0); - renderer->V_ViewMatrix = ViewMatrix; - renderer->V_ProjectionMatrix = ProjectionMatrix; if (camera != nullptr) { camera->ViewMatrix = ViewMatrix; camera->ProjectionMatrix = ProjectionMatrix; } - renderer->V_SurfaceID = -1; runner->renderer->vtable->applyProjection(runner->renderer, &ViewMatrix, &ProjectionMatrix); Runner_draw(runner); @@ -1335,7 +1323,7 @@ GMLCamera* Runner_getCameraById(Runner* runner, int32_t id) { if (0 > id) return nullptr; else if (MAX_DEFAULT_ROOM_CAMERAS > id) camera = &runner->defaultCameras[id]; else if (MAX_CAMERAS > id) camera = &runner->userCameras[id - MAX_DEFAULT_ROOM_CAMERAS]; - else if (id == 8192) camera = &runner->surfaceCamera; + else if (id == SURFACE_CAMERA) camera = &runner->surfaceCamera; else return nullptr; if (!camera->allocated) return nullptr; return camera; @@ -1360,22 +1348,22 @@ static void initDefaultCameraFromRoomView(GMLCamera* camera, RoomView* roomView) camera->objectId = roomView->objectId; camera->viewAngle = 0; //make default projection - Matrix4f Projection; - Matrix4f_Orthographic(&Projection, (float) camera->viewWidth, (float) -camera->viewHeight, 32000.0, 0.0); + Matrix4f ProjectionMatrix; + Matrix4f_Orthographic(&ProjectionMatrix, (float) camera->viewWidth, (float) -camera->viewHeight, 32000.0, 0.0); - Matrix4f View; + Matrix4f ViewMatrix; float x = camera->viewX + camera->viewWidth/2; float y = camera->viewY + camera->viewHeight/2; - Matrix4f_identity(&View); - Matrix4f_LookAt(&View, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0); - Matrix4f_translate(&View, x, y, 0.0f); - Matrix4f_rotateZ(&View, -camera->viewAngle * (float) M_PI / 180.0f); - Matrix4f_translate(&View, -x, -y, 0.0f); + Matrix4f_identity(&ViewMatrix); + Matrix4f_LookAt(&ViewMatrix, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0); + Matrix4f_translate(&ViewMatrix, x, y, 0.0f); + Matrix4f_rotateZ(&ViewMatrix, -camera->viewAngle * (float) M_PI / 180.0f); + Matrix4f_translate(&ViewMatrix, -x, -y, 0.0f); - camera->ProjectionMatrix = Projection; - camera->ViewMatrix = View; + camera->ProjectionMatrix = ProjectionMatrix; + camera->ViewMatrix = ViewMatrix; } // Copies the viewport (port) properties and enabled flag from parsed room data. @@ -3938,9 +3926,6 @@ bool Runner_surfaceSetTarget(Runner* runner, int32_t surfaceID) { runner->surfaceStack[slot] = surfaceID; runner->renderer->vtable->flush(runner->renderer); - GMLCamera* camera = Runner_getCameraForView(runner, (int32_t) runner->viewCurrent); - runner->renderer->V_ProjectionMatrix = camera->ProjectionMatrix; - runner->renderer->V_ViewMatrix = camera->ViewMatrix; return runner->renderer->vtable->setRenderTarget(runner->renderer, surfaceID, false); } @@ -3955,9 +3940,6 @@ bool Runner_surfaceResetTarget(Runner* runner) { int32_t newTop = findStackTop(runner); int32_t newTarget = newTop == -1 ? runner->applicationSurfaceId : runner->surfaceStack[newTop]; - GMLCamera* camera = Runner_getCameraForView(runner, (int32_t) runner->viewCurrent); - runner->renderer->V_ProjectionMatrix = camera->ProjectionMatrix; - runner->renderer->V_ViewMatrix = camera->ViewMatrix; runner->renderer->vtable->setRenderTarget(runner->renderer, newTarget, newTop == -1); if (newTop == -1 && runner->inGuiPass) { // Inside Pre Draw / Post Draw / Draw GUI the base target is the GUI pass target with the GUI projection, not the room view. diff --git a/src/vm_builtins.c b/src/vm_builtins.c index 223681d9..30337d04 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -216,7 +216,7 @@ static DsStack* dsStackGet(Runner* runner, int32_t id) { return &runner->dsStackPool[id]; } -static void UpdateCamera(GMLCamera* camera) { +static void UpdateCameraViewSimple(GMLCamera* camera) { float x = camera->viewX + camera->viewWidth/2; float y = camera->viewY + camera->viewHeight/2; @@ -1574,7 +1574,7 @@ void VMBuiltins_setVariable(VMContext* ctx, Instance* inst, int16_t builtinVarId GMLCamera* camera = Runner_getCameraForView(runner, arrayIndex); if (camera != nullptr) { camera->viewX = RValue_toReal(val); - UpdateCamera(camera); + UpdateCameraViewSimple(camera); } return; } @@ -1582,23 +1582,23 @@ void VMBuiltins_setVariable(VMContext* ctx, Instance* inst, int16_t builtinVarId GMLCamera* camera = Runner_getCameraForView(runner, arrayIndex); if (camera != nullptr) { camera->viewY = RValue_toInt32(val); - UpdateCamera(camera); + UpdateCameraViewSimple(camera); } return; } case BUILTIN_VAR_VIEW_WVIEW: { GMLCamera* camera = Runner_getCameraForView(runner, arrayIndex); if (camera != nullptr) { - camera->viewWidth = RValue_toInt32(val); - UpdateCamera(camera); - } + camera->viewWidth = RValue_toInt32(val); + UpdateCameraViewSimple(camera); + } return; } case BUILTIN_VAR_VIEW_HVIEW: { GMLCamera* camera = Runner_getCameraForView(runner, arrayIndex); if (camera != nullptr) { camera->viewHeight = RValue_toInt32(val); - UpdateCamera(camera); + UpdateCameraViewSimple(camera); } return; } @@ -1627,7 +1627,7 @@ void VMBuiltins_setVariable(VMContext* ctx, Instance* inst, int16_t builtinVarId GMLCamera* camera = Runner_getCameraForView(runner, arrayIndex); if (camera != nullptr) { camera->viewAngle = (float) RValue_toReal(val); - UpdateCamera(camera); + UpdateCameraViewSimple(camera); } return; } @@ -3467,7 +3467,7 @@ static RValue builtin_camera_set_view_pos(VMContext* ctx, RValue* args, int32_t if (camera != nullptr) { camera->viewX = RValue_toReal(args[1]); camera->viewY = RValue_toReal(args[2]); - UpdateCamera(camera); + UpdateCameraViewSimple(camera); } return RValue_makeUndefined(); } @@ -3582,7 +3582,7 @@ static RValue builtin_camera_set_view_angle(VMContext* ctx, RValue* args, int32_ if (camera != nullptr) { camera->viewAngle = (float) RValue_toReal(args[1]); - UpdateCamera(camera); + UpdateCameraViewSimple(camera); } return RValue_makeUndefined(); } @@ -3648,7 +3648,7 @@ static RValue builtin_camera_create_view(VMContext* ctx, RValue* args, int32_t a if (argCount > 9) camera->borderY = (uint32_t) RValue_toInt32(args[9]); - UpdateCamera(camera); + UpdateCameraViewSimple(camera); return RValue_makeReal(id); } @@ -3684,7 +3684,6 @@ static RValue builtin_view_set_camera(VMContext* ctx, RValue* args, int32_t argC static RValue builtin_camera_get_active(VMContext* ctx, MAYBE_UNUSED RValue* args, MAYBE_UNUSED int32_t argCount) { Runner* runner = ctx->runner; if (runner->viewCurrent >= 0 && MAX_VIEWS > runner->viewCurrent) { - //return RValue_makeReal(runner->views[runner->viewCurrent].cameraId); return RValue_makeReal(runner->renderer->CameraCurrent); } return RValue_makeReal(-1); From e5b5a6a3e51be6c01ec41266b9d592760bfd0d27 Mon Sep 17 00:00:00 2001 From: Classic0306 <190026317+Classic0306@users.noreply.github.com> Date: Tue, 16 Jun 2026 20:55:59 +0200 Subject: [PATCH 12/16] remove more hacks and smth else I forgor --- src/gl/gl_renderer.c | 70 ++++++++++++++++++------------ src/gl_legacy/gl_legacy_renderer.c | 2 +- src/runner.c | 24 +++++++--- src/vm_builtins.c | 3 +- 4 files changed, 64 insertions(+), 35 deletions(-) diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index e5e94c37..01d597ec 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -442,6 +442,32 @@ static void glShaderSettingsRefresh(Renderer* renderer) { } } +// camera_apply: swap the active world->clip projection on the current target without touching its viewport. +static void glApplyProjection(Renderer* renderer, const Matrix4f* ViewMatrix,const Matrix4f* ProjectionMatrix) { + GLRenderer* gl = (GLRenderer*) renderer; + + // Flush first so pending quads draw under the projection they were issued with. + flushBatch(gl); + + Matrix4f World = renderer->gmlMatrices[MATRIX_WORLD]; + Matrix4f View = *ViewMatrix; + Matrix4f Projection = *ProjectionMatrix; + + Matrix4f WorldView; + Matrix4f_multiply(&WorldView, &View, &World); + + Matrix4f WorldViewProjection; + Matrix4f_multiply(&WorldViewProjection, &View, &World); + Matrix4f_multiply(&WorldViewProjection, &Projection, &WorldViewProjection); + + renderer->gmlMatrices[MATRIX_VIEW] = View; + renderer->gmlMatrices[MATRIX_PROJECTION] = Projection; + renderer->gmlMatrices[MATRIX_WORLD_VIEW] = WorldView; + renderer->gmlMatrices[MATRIX_WORLD_VIEW_PROJECTION] = WorldViewProjection; + //oh my I hope it's good enough. + glShaderSettingsRefresh(renderer); +} + static void glGpuResetShader(Renderer* renderer) { GLRenderer* gl = (GLRenderer*) renderer; flushBatch(gl); @@ -515,7 +541,7 @@ static void glBeginFrame(Renderer* renderer, int32_t gameW, int32_t gameH, int32 gl->base.CPortH = gameH; } -static void glBeginView(Renderer* renderer, int32_t viewX, int32_t viewY, int32_t viewW, int32_t viewH, int32_t portX, int32_t portY, int32_t portW, int32_t portH, float viewAngle) { +static void glBeginView(Renderer* renderer, MAYBE_UNUSED int32_t viewX, MAYBE_UNUSED int32_t viewY, MAYBE_UNUSED int32_t viewW, MAYBE_UNUSED int32_t viewH, int32_t portX, int32_t portY, int32_t portW, int32_t portH, MAYBE_UNUSED float viewAngle) { GLRenderer* gl = (GLRenderer*) renderer; gl->batchCount = 0; @@ -535,6 +561,20 @@ static void glBeginView(Renderer* renderer, int32_t viewX, int32_t viewY, int32_ glEnable(GL_SCISSOR_TEST); glScissor(portX, portY, portW, portH); + int32_t ViewCurrent = 0; + if (renderer->runner->viewsEnabled) { + ViewCurrent = renderer->runner->viewCurrent; + } + RuntimeView* view = &renderer->runner->views[ViewCurrent]; + gl->base.CameraCurrent = view->cameraId; + GMLCamera* camera = Runner_getCameraById(renderer->runner, gl->base.CameraCurrent); + glApplyProjection(renderer,&camera->ViewMatrix,&camera->ProjectionMatrix); + + //Matrix4f ViewMatrix = camera->ViewMatrix; + //Matrix4f ProjectionMatrix = camera->ProjectionMatrix; + //runner->renderer->vtable->applyProjection(runner->renderer, &ViewMatrix, &ProjectionMatrix); + + glShaderSettingsRefresh(renderer); glActiveTexture(GL_TEXTURE1); @@ -547,33 +587,7 @@ static void glEndView(Renderer* renderer) { glDisable(GL_SCISSOR_TEST); } -// camera_apply: swap the active world->clip projection on the current target without touching its viewport. -static void glApplyProjection(Renderer* renderer, const Matrix4f* ViewMatrix,const Matrix4f* ProjectionMatrix) { - GLRenderer* gl = (GLRenderer*) renderer; - - // Flush first so pending quads draw under the projection they were issued with. - flushBatch(gl); - - Matrix4f World = renderer->gmlMatrices[MATRIX_WORLD]; - Matrix4f View = *ViewMatrix; - Matrix4f Projection = *ProjectionMatrix; - - Matrix4f WorldView; - Matrix4f_multiply(&WorldView, &View, &World); - - Matrix4f WorldViewProjection; - Matrix4f_multiply(&WorldViewProjection, &View, &World); - Matrix4f_multiply(&WorldViewProjection, &Projection, &WorldViewProjection); - - renderer->gmlMatrices[MATRIX_VIEW] = View; - renderer->gmlMatrices[MATRIX_PROJECTION] = Projection; - renderer->gmlMatrices[MATRIX_WORLD_VIEW] = WorldView; - renderer->gmlMatrices[MATRIX_WORLD_VIEW_PROJECTION] = WorldViewProjection; - //oh my I hope it's good enough. - glShaderSettingsRefresh(renderer); -} - -static void glBeginGUI(Renderer* renderer, int32_t guiW, int32_t guiH, int32_t portX, int32_t portY, int32_t portW, int32_t portH, int32_t targetSurfaceId) { +static void glBeginGUI(Renderer* renderer, MAYBE_UNUSED int32_t guiW, MAYBE_UNUSED int32_t guiH, int32_t portX, int32_t portY, int32_t portW, int32_t portH, int32_t targetSurfaceId) { GLRenderer* gl = (GLRenderer*) renderer; gl->batchCount = 0; diff --git a/src/gl_legacy/gl_legacy_renderer.c b/src/gl_legacy/gl_legacy_renderer.c index 9be5f228..b7437eae 100644 --- a/src/gl_legacy/gl_legacy_renderer.c +++ b/src/gl_legacy/gl_legacy_renderer.c @@ -186,7 +186,7 @@ static void glEndView(MAYBE_UNUSED Renderer* renderer) { } // camera_apply: swap the active world->clip projection on the current target without touching its viewport. -static void glApplyProjection(Renderer* renderer, const Matrix4f* ViewMatrix,const Matrix4f* ProjectionMatrix) { +static void glApplyProjection(Renderer* renderer, MAYBE_UNUSED const Matrix4f* ViewMatrix, MAYBE_UNUSED const Matrix4f* ProjectionMatrix) { Matrix4f projection = *ProjectionMatrix; //fix it later Matrix4f_flipClipY(&projection); glMatrixMode(GL_PROJECTION); diff --git a/src/runner.c b/src/runner.c index 66b53104..925c488f 100644 --- a/src/runner.c +++ b/src/runner.c @@ -1173,10 +1173,6 @@ void Runner_drawViews(Runner* runner, int32_t gameW, int32_t gameH, bool debugSh runner->renderer->CameraCurrent = runner->views[runner->viewCurrent].cameraId; renderer->vtable->beginView(renderer, viewX, viewY, viewW, viewH, portX, portY, portW, portH, viewAngle); - Matrix4f ViewMatrix = camera->ViewMatrix; - Matrix4f ProjectionMatrix = camera->ProjectionMatrix; - runner->renderer->vtable->applyProjection(runner->renderer, &ViewMatrix, &ProjectionMatrix); - Runner_draw(runner); if (debugShowCollisionMasks) DebugOverlay_drawCollisionMasks(runner); @@ -1206,6 +1202,11 @@ void Runner_drawViews(Runner* runner, int32_t gameW, int32_t gameH, bool debugSh Matrix4f_identity(&ViewMatrix); Matrix4f_LookAt(&ViewMatrix, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0); if (camera != nullptr) { + camera->viewX = 0; + camera->viewY = 0; + camera->viewWidth = gameW; + camera->viewHeight = gameH; + camera->viewAngle = 0.0; camera->ViewMatrix = ViewMatrix; camera->ProjectionMatrix = ProjectionMatrix; } @@ -3915,7 +3916,20 @@ void Runner_guiSizeChanged(Runner* runner) { runner->guiPassH = guiH; int32_t top = findStackTop(runner); bool renderingToUserSurface = (top != -1 && runner->surfaceStack[top] != runner->applicationSurfaceId); - runner->renderer->vtable->setGuiProjection(runner->renderer, guiW, guiH, runner->guiPassPortW, runner->guiPassPortH, renderingToUserSurface); + float MULT = 1.0; + if (renderingToUserSurface == true) { + MULT = -1.0; + } + Matrix4f ProjectionMatrix; + Matrix4f_Orthographic(&ProjectionMatrix, (float) runner->guiPassW, (float) runner->guiPassH*MULT, 32000.0, 0.0); + + Matrix4f ViewMatrix; + float x = (float) runner->guiPassW /2; + float y = (float) runner->guiPassH /2; + Matrix4f_identity(&ViewMatrix); + Matrix4f_LookAt(&ViewMatrix, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0); + + runner->renderer->vtable->applyProjection(runner->renderer, &ViewMatrix, &ProjectionMatrix); } bool Runner_surfaceSetTarget(Runner* runner, int32_t surfaceID) { diff --git a/src/vm_builtins.c b/src/vm_builtins.c index 30337d04..2a3cb754 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -3701,8 +3701,9 @@ static RValue builtin_camera_apply(VMContext* ctx, RValue* args, int32_t argCoun if (1 > argCount) return RValue_makeUndefined(); Runner* runner = ctx->runner; GMLCamera* camera = Runner_getCameraById(runner, RValue_toInt32(args[0])); - if (camera != nullptr) { + if (camera != nullptr) { runner->renderer->vtable->applyProjection(runner->renderer, &camera->ViewMatrix, &camera->ProjectionMatrix); + runner->renderer->CameraCurrent = RValue_toInt32(args[0]); } return RValue_makeUndefined(); } From 87ea7f7d00ea30bc612d6f5b31fcd41bbed260d5 Mon Sep 17 00:00:00 2001 From: Classic0306 <190026317+Classic0306@users.noreply.github.com> Date: Thu, 18 Jun 2026 21:50:25 +0200 Subject: [PATCH 13/16] rebase and fix little things --- src/gl/gl_renderer.c | 33 +++++++++++++++++++++------------ src/runner.c | 3 ++- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index 01d597ec..0faded55 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -250,6 +250,10 @@ static void glInit(Renderer* renderer, DataWin* dataWin) { GLRenderer* gl = (GLRenderer*) renderer; renderer->dataWin = dataWin; + Matrix4f World; + Matrix4f_identity(&World); + renderer->gmlMatrices[MATRIX_WORLD] = World; + GMLShader* defaultShader = safeCalloc(1, sizeof(GMLShader)); bool success = compileProgram(defaultShader, "default", defaultVertexShaderSource, defaultFragmentShaderSource, 0, nullptr); if (!success) { @@ -400,8 +404,14 @@ static void glGpuSetShader(Renderer* renderer, int32_t shaderIndex) { GLShaderUniform* gmAlphaTestEnabledUniform = findShaderUniformByName(gmlShader, "gm_AlphaTestEnabled"); GLShaderUniform* gmAlphaRefValue = findShaderUniformByName(gmlShader, "gm_AlphaRefValue"); + Matrix4f FlippedClip[MATRICES_MAX]; + for (int32_t i = 0; i < MATRICES_MAX; i++) { + FlippedClip[i] = renderer->gmlMatrices[i]; + Matrix4f_flipClipY(&FlippedClip[i]); + } + if (gmMatricesUniform != nullptr) { - glUniformMatrix4fv(gmMatricesUniform->location, 5, GL_FALSE, renderer->gmlMatrices[0].m); + glUniformMatrix4fv(gmMatricesUniform->location, 5, GL_FALSE, FlippedClip[0].m); } if (gmFogColourUniform != nullptr) { glUniform1i(gmFogColourUniform->location, gl->fogColor); @@ -428,13 +438,18 @@ static void glShaderSettingsRefresh(Renderer* renderer) { glUseProgram(gl->defaultShaderProgram->shaderId); - GLShaderUniform* uProjection = findShaderUniformByName(gl->defaultShaderProgram, "uProjection"); + GLShaderUniform* uWorldViewProjection = findShaderUniformByName(gl->defaultShaderProgram, "uWorldViewProjection"); GLShaderUniform* uFogColor = findShaderUniformByName(gl->defaultShaderProgram, "uFogColor"); GLShaderUniform* uAlphaTestRef = findShaderUniformByName(gl->defaultShaderProgram, "uAlphaTestRef"); GLShaderUniform* uAlphaTestEnabled = findShaderUniformByName(gl->defaultShaderProgram, "uAlphaTestEnabled"); GLShaderUniform* uTexture = findShaderUniformByName(gl->defaultShaderProgram, "uTexture"); + Matrix4f FlippedClip[MATRICES_MAX]; + for (int32_t i = 0; i < MATRICES_MAX; i++) { + FlippedClip[i] = renderer->gmlMatrices[i]; + Matrix4f_flipClipY(&FlippedClip[i]); + } - glUniformMatrix4fv(uProjection->location, 1, GL_FALSE, renderer->gmlMatrices[MATRIX_WORLD_VIEW_PROJECTION].m); + glUniformMatrix4fv(uWorldViewProjection->location, 1, GL_FALSE, FlippedClip[MATRIX_WORLD_VIEW_PROJECTION].m); glUniform4f(uFogColor->location, fogR, fogG, fogB, gl->fogEnable ? 1.0f : 0.0f); glUniform1f(uAlphaTestRef->location, gl->alphaTestRef); glUniform1i(uAlphaTestEnabled->location, gl->alphaTestEnable); @@ -457,8 +472,7 @@ static void glApplyProjection(Renderer* renderer, const Matrix4f* ViewMatrix,con Matrix4f_multiply(&WorldView, &View, &World); Matrix4f WorldViewProjection; - Matrix4f_multiply(&WorldViewProjection, &View, &World); - Matrix4f_multiply(&WorldViewProjection, &Projection, &WorldViewProjection); + Matrix4f_multiply(&WorldViewProjection, &Projection, &WorldView); renderer->gmlMatrices[MATRIX_VIEW] = View; renderer->gmlMatrices[MATRIX_PROJECTION] = Projection; @@ -570,11 +584,6 @@ static void glBeginView(Renderer* renderer, MAYBE_UNUSED int32_t viewX, MAYBE_UN GMLCamera* camera = Runner_getCameraById(renderer->runner, gl->base.CameraCurrent); glApplyProjection(renderer,&camera->ViewMatrix,&camera->ProjectionMatrix); - //Matrix4f ViewMatrix = camera->ViewMatrix; - //Matrix4f ProjectionMatrix = camera->ProjectionMatrix; - //runner->renderer->vtable->applyProjection(runner->renderer, &ViewMatrix, &ProjectionMatrix); - - glShaderSettingsRefresh(renderer); glActiveTexture(GL_TEXTURE1); @@ -2022,6 +2031,7 @@ static bool glSetRenderTarget(Renderer* renderer, int32_t surfaceId, bool implic glApplyProjection(renderer,&camera->ViewMatrix,&camera->ProjectionMatrix); return true; } else { + //camera will use full surface. Matrix4f ProjectionMatrix; Matrix4f_Orthographic(&ProjectionMatrix, (float) gl->surfaceWidth[surfaceId], (float) -gl->surfaceHeight[surfaceId], 32000.0, 0.0); @@ -2558,8 +2568,7 @@ static void glSetMatrix(Renderer* renderer, int32_t MatrixType, Matrix4f Matrix) Matrix4f_multiply(&WorldView, &View, &World); Matrix4f WorldViewProjection; - Matrix4f_multiply(&WorldViewProjection, &View, &World); - Matrix4f_multiply(&WorldViewProjection, &Projection, &WorldViewProjection); + Matrix4f_multiply(&WorldViewProjection, &Projection, &WorldView); renderer->gmlMatrices[MATRIX_WORLD_VIEW] = WorldView; renderer->gmlMatrices[MATRIX_WORLD_VIEW_PROJECTION] = WorldViewProjection; diff --git a/src/runner.c b/src/runner.c index 925c488f..143d9c22 100644 --- a/src/runner.c +++ b/src/runner.c @@ -1211,7 +1211,8 @@ void Runner_drawViews(Runner* runner, int32_t gameW, int32_t gameH, bool debugSh camera->ProjectionMatrix = ProjectionMatrix; } - runner->renderer->vtable->applyProjection(runner->renderer, &ViewMatrix, &ProjectionMatrix); + renderer->vtable->beginView(renderer, fullViewX, fullViewY, fullViewW, fullViewH, 0, 0, gameW, gameH, 0.0f); + Runner_draw(runner); if (debugShowCollisionMasks) DebugOverlay_drawCollisionMasks(runner); From 25fe4a3f9ba8b1d69ddb491ce78e4dc7ff57add0 Mon Sep 17 00:00:00 2001 From: Classic0306 <190026317+Classic0306@users.noreply.github.com> Date: Fri, 19 Jun 2026 18:37:16 +0200 Subject: [PATCH 14/16] remove more thing, try fix GUI kinda --- src/gl/gl_renderer.c | 42 ++++++++++++++++++++++++++++++------------ src/runner.c | 33 ++++----------------------------- src/vm_builtins.c | 16 ++++++++++++++-- 3 files changed, 48 insertions(+), 43 deletions(-) diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index 0faded55..c84b1110 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -596,7 +596,7 @@ static void glEndView(Renderer* renderer) { glDisable(GL_SCISSOR_TEST); } -static void glBeginGUI(Renderer* renderer, MAYBE_UNUSED int32_t guiW, MAYBE_UNUSED int32_t guiH, int32_t portX, int32_t portY, int32_t portW, int32_t portH, int32_t targetSurfaceId) { +static void glBeginGUI(Renderer* renderer, MAYBE_UNUSED int32_t guiW, MAYBE_UNUSED int32_t guiH, int32_t portX, int32_t portY, int32_t portW, MAYBE_UNUSED int32_t portH, int32_t targetSurfaceId) { GLRenderer* gl = (GLRenderer*) renderer; gl->batchCount = 0; @@ -617,25 +617,43 @@ static void glBeginGUI(Renderer* renderer, MAYBE_UNUSED int32_t guiW, MAYBE_UNUS glEnable(GL_SCISSOR_TEST); - //Matrix4f projection; - //Matrix4f_guiProjection(&projection, (float) guiW, (float) guiH, (float) portW, (float) portH); - //Matrix4f_flipClipY(&projection); - //renderer->gmlMatrices[MATRIX_WORLD_VIEW_PROJECTION] = projection; - glShaderSettingsRefresh(renderer); + gl->base.CameraCurrent = 0; //replace this number with whatver camera ID is used for the GUI. maybe some special ID? I have no idea how it should be + //GMLCamera* camera = Runner_getCameraById(renderer->runner, gl->base.CameraCurrent); use this or something later + Matrix4f ProjectionMatrix; + Matrix4f_Orthographic(&ProjectionMatrix, (float) guiW, (float) guiH, 32000.0, 0.0); + + Matrix4f ViewMatrix; + float x = (float) guiW /2; + float y = (float) guiH /2; + Matrix4f_identity(&ViewMatrix); + Matrix4f_LookAt(&ViewMatrix, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0); + + glApplyProjection(renderer,&ViewMatrix,&ProjectionMatrix); + + glActiveTexture(GL_TEXTURE1); glBindVertexArray(gl->vao); } -static void glSetGuiProjection(Renderer* renderer, int32_t guiW, int32_t guiH, int32_t portW, int32_t portH, bool renderingToUserSurface) { +static void glSetGuiProjection(Renderer* renderer, int32_t guiW, int32_t guiH, MAYBE_UNUSED int32_t portW, MAYBE_UNUSED int32_t portH, MAYBE_UNUSED bool renderingToUserSurface) { GLRenderer* gl = (GLRenderer*) renderer; flushBatch(gl); - Matrix4f projection; - Matrix4f_guiProjection(&projection, (float) guiW, (float) guiH, (float) portW, (float) portH); + // GL surfaces are stored bottom-up and draw_surface samples them with vertical flip. - // Flip the projection when we are rendering to a user surface so it comes back upright. - if (renderingToUserSurface) Matrix4f_flipClipY(&projection); - renderer->gmlMatrices[MATRIX_WORLD_VIEW_PROJECTION] = projection; + gl->base.CameraCurrent = 0; //replace this number with whatver camera ID is used for the GUI. maybe some special ID? I have no idea how it should be + //GMLCamera* camera = Runner_getCameraById(renderer->runner, gl->base.CameraCurrent); use this or something later + //yeah no I have no idea how to do the GUI + Matrix4f ProjectionMatrix; + Matrix4f_Orthographic(&ProjectionMatrix, (float) guiW, (float) guiH, 32000.0, 0.0); + if (renderingToUserSurface) Matrix4f_flipClipY(&ProjectionMatrix); + Matrix4f ViewMatrix; + float x = (float) guiW * 0.5f; + float y = (float) guiH * 0.5f; + Matrix4f_identity(&ViewMatrix); + Matrix4f_LookAt(&ViewMatrix, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0); + + glApplyProjection(renderer,&ViewMatrix,&ProjectionMatrix); glShaderSettingsRefresh(renderer); } diff --git a/src/runner.c b/src/runner.c index 143d9c22..f366a33a 100644 --- a/src/runner.c +++ b/src/runner.c @@ -1022,19 +1022,6 @@ void Runner_drawGUI(Runner* runner, int32_t windowW, int32_t windowH, int32_t ta int32_t guiW = runner->guiWidth > 0 ? runner->guiWidth : targetW; int32_t guiH = runner->guiHeight > 0 ? runner->guiHeight : targetH; beginGuiPass(runner, guiW, guiH, windowW, windowH, RENDER_TARGET_HOST_FRAMEBUFFER); - - //make default projection - Matrix4f ProjectionMatrix; - Matrix4f_Orthographic(&ProjectionMatrix, (float) guiW, (float) guiH, 32000.0, 0.0); - - Matrix4f ViewMatrix; - float x = (float) guiW / 2; - float y = (float) guiH / 2; - Matrix4f_identity(&ViewMatrix); - Matrix4f_LookAt(&ViewMatrix, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0); - - runner->renderer->vtable->applyProjection(runner->renderer, &ViewMatrix, &ProjectionMatrix); - fireDrawSubtype(runner, drawables, drawableCount, DRAW_GUI_BEGIN); fireDrawSubtype(runner, drawables, drawableCount, DRAW_GUI); fireDrawSubtype(runner, drawables, drawableCount, DRAW_GUI_END); @@ -1146,10 +1133,11 @@ void Runner_drawViews(Runner* runner, int32_t gameW, int32_t gameH, bool debugSh Matrix4f ViewMatrix = camera->ViewMatrix; Matrix4f ProjectionMatrix = camera->ProjectionMatrix; - runner->renderer->vtable->applyProjection(runner->renderer, &ViewMatrix, &ProjectionMatrix); - runner->viewCurrent = (int32_t) vi; runner->renderer->CameraCurrent = runner->views[runner->viewCurrent].cameraId; + runner->renderer->vtable->applyProjection(runner->renderer, &ViewMatrix, &ProjectionMatrix); + + Runner_draw(runner); renderer->vtable->flush(renderer); @@ -3917,20 +3905,7 @@ void Runner_guiSizeChanged(Runner* runner) { runner->guiPassH = guiH; int32_t top = findStackTop(runner); bool renderingToUserSurface = (top != -1 && runner->surfaceStack[top] != runner->applicationSurfaceId); - float MULT = 1.0; - if (renderingToUserSurface == true) { - MULT = -1.0; - } - Matrix4f ProjectionMatrix; - Matrix4f_Orthographic(&ProjectionMatrix, (float) runner->guiPassW, (float) runner->guiPassH*MULT, 32000.0, 0.0); - - Matrix4f ViewMatrix; - float x = (float) runner->guiPassW /2; - float y = (float) runner->guiPassH /2; - Matrix4f_identity(&ViewMatrix); - Matrix4f_LookAt(&ViewMatrix, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0); - - runner->renderer->vtable->applyProjection(runner->renderer, &ViewMatrix, &ProjectionMatrix); + runner->renderer->vtable->setGuiProjection(runner->renderer, guiW, guiH, runner->guiPassPortW, runner->guiPassPortH, renderingToUserSurface); } bool Runner_surfaceSetTarget(Runner* runner, int32_t surfaceID) { diff --git a/src/vm_builtins.c b/src/vm_builtins.c index 2a3cb754..e71ddff8 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -2929,14 +2929,26 @@ static RValue builtin_matrix_build_projection_perspective_fov(MAYBE_UNUSED VMCon } static RValue builtin_matrix_get(MAYBE_UNUSED VMContext *ctx, RValue *args, int32_t argCount) { int32_t Matrix = RValue_toInt32(args[0]); - return RValue_makeArray(matrixToGml(&ctx->runner->renderer->gmlMatrices[Matrix])); + if (Matrix < 0 || Matrix > 2) return RValue_makeUndefined(); + bool toPrevMatrix = argCount == 2; + GMLArray *destArray = toPrevMatrix ? args[1].array : nullptr; + if (toPrevMatrix && !rvalueIsMatrix(args[1])) return RValue_makeUndefined(); + + if (!toPrevMatrix) { + return RValue_makeArray(matrixToGml(&ctx->runner->renderer->gmlMatrices[Matrix])); + } else { + repeat (16, i) { + *GMLArray_slot(destArray, i) = RValue_makeReal(ctx->runner->renderer->gmlMatrices[Matrix].m[i]); + } + return RValue_makeArrayWeak(destArray); + } } static RValue builtin_matrix_set(MAYBE_UNUSED VMContext *ctx, RValue *args, int32_t argCount) { int32_t Matrix = RValue_toInt32(args[0]); Matrix4f m; matrixFromGml(&m, args[1].array); - //add safe guards or whatever itis + if (Matrix < 0 || Matrix > 2) return RValue_makeUndefined(); if (ctx->runner->renderer != nullptr) { ctx->runner->renderer->vtable->setMatrix(ctx->runner->renderer, Matrix, m); } From ceceff787ea2edf730b504d707af161af88c2354 Mon Sep 17 00:00:00 2001 From: Classic0306 <190026317+Classic0306@users.noreply.github.com> Date: Fri, 19 Jun 2026 18:58:02 +0200 Subject: [PATCH 15/16] try to fix things, I wanna give up --- src/gl/gl_renderer.c | 43 ++++++++++++++++++++++++++++++++++--------- src/renderer.h | 3 ++- src/runner.c | 1 + src/runner.h | 1 + 4 files changed, 38 insertions(+), 10 deletions(-) diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index c84b1110..ff45ae94 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -616,9 +616,21 @@ static void glBeginGUI(Renderer* renderer, MAYBE_UNUSED int32_t guiW, MAYBE_UNUS } glEnable(GL_SCISSOR_TEST); + //I dunno hopefully this is at least somewhat correct... + gl->base.CameraCurrent = GUI_CAMERA; + GMLCamera* camera = &renderer->runner->guiCamera; + camera->allocated = true; + camera->viewX = 0.0; + camera->viewY = 0.0; + camera->viewWidth = guiW; + camera->viewHeight = guiH; + camera->borderX = 0; + camera->borderY = 0; + camera->speedX = 0; + camera->speedY = 0; + camera->objectId = -1; + camera->viewAngle = 0; - gl->base.CameraCurrent = 0; //replace this number with whatver camera ID is used for the GUI. maybe some special ID? I have no idea how it should be - //GMLCamera* camera = Runner_getCameraById(renderer->runner, gl->base.CameraCurrent); use this or something later Matrix4f ProjectionMatrix; Matrix4f_Orthographic(&ProjectionMatrix, (float) guiW, (float) guiH, 32000.0, 0.0); @@ -627,8 +639,9 @@ static void glBeginGUI(Renderer* renderer, MAYBE_UNUSED int32_t guiW, MAYBE_UNUS float y = (float) guiH /2; Matrix4f_identity(&ViewMatrix); Matrix4f_LookAt(&ViewMatrix, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0); - - glApplyProjection(renderer,&ViewMatrix,&ProjectionMatrix); + camera->ViewMatrix = ViewMatrix; + camera->ProjectionMatrix = ProjectionMatrix; + glApplyProjection(renderer,&camera->ViewMatrix,&camera->ProjectionMatrix); glActiveTexture(GL_TEXTURE1); @@ -641,8 +654,20 @@ static void glSetGuiProjection(Renderer* renderer, int32_t guiW, int32_t guiH, M flushBatch(gl); // GL surfaces are stored bottom-up and draw_surface samples them with vertical flip. - gl->base.CameraCurrent = 0; //replace this number with whatver camera ID is used for the GUI. maybe some special ID? I have no idea how it should be - //GMLCamera* camera = Runner_getCameraById(renderer->runner, gl->base.CameraCurrent); use this or something later + gl->base.CameraCurrent = GUI_CAMERA; + GMLCamera* camera = &renderer->runner->guiCamera; + camera->allocated = true; + camera->viewX = 0.0; + camera->viewY = 0.0; + camera->viewWidth = guiW; + camera->viewHeight = guiH; + camera->borderX = 0; + camera->borderY = 0; + camera->speedX = 0; + camera->speedY = 0; + camera->objectId = -1; + camera->viewAngle = 0; + //yeah no I have no idea how to do the GUI Matrix4f ProjectionMatrix; Matrix4f_Orthographic(&ProjectionMatrix, (float) guiW, (float) guiH, 32000.0, 0.0); @@ -652,9 +677,9 @@ static void glSetGuiProjection(Renderer* renderer, int32_t guiW, int32_t guiH, M float y = (float) guiH * 0.5f; Matrix4f_identity(&ViewMatrix); Matrix4f_LookAt(&ViewMatrix, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0); - - glApplyProjection(renderer,&ViewMatrix,&ProjectionMatrix); - glShaderSettingsRefresh(renderer); + camera->ViewMatrix = ViewMatrix; + camera->ProjectionMatrix = ProjectionMatrix; + glApplyProjection(renderer,&camera->ViewMatrix,&camera->ProjectionMatrix); } static void glEndGUI(Renderer* renderer) { diff --git a/src/renderer.h b/src/renderer.h index 4da9d52e..59d42234 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -40,7 +40,8 @@ #define MAX_VS_LIGHTS 8 #define MAX_TEXTURE_STAGES 8 - +//these 2 IDs are just IDs I simply made up, replace them with proper ones eventually oki? +#define GUI_CAMERA 4096 #define SURFACE_CAMERA 8192 // Sentinel returned by ensureApplicationSurface on platforms that don't back the application_surface with a real entry in the renderer's surface table. diff --git a/src/runner.c b/src/runner.c index f366a33a..007abc97 100644 --- a/src/runner.c +++ b/src/runner.c @@ -1314,6 +1314,7 @@ GMLCamera* Runner_getCameraById(Runner* runner, int32_t id) { else if (MAX_DEFAULT_ROOM_CAMERAS > id) camera = &runner->defaultCameras[id]; else if (MAX_CAMERAS > id) camera = &runner->userCameras[id - MAX_DEFAULT_ROOM_CAMERAS]; else if (id == SURFACE_CAMERA) camera = &runner->surfaceCamera; + else if (id == GUI_CAMERA) camera = &runner->guiCamera; else return nullptr; if (!camera->allocated) return nullptr; return camera; diff --git a/src/runner.h b/src/runner.h index d76cdc09..ede102c6 100644 --- a/src/runner.h +++ b/src/runner.h @@ -473,6 +473,7 @@ struct Runner { GMLCamera defaultCameras[MAX_DEFAULT_ROOM_CAMERAS]; GMLCamera userCameras[MAX_USER_CAMERAS]; GMLCamera surfaceCamera; + GMLCamera guiCamera; RunnerGamepadState* gamepads; RuntimeBackground backgrounds[8]; uint32_t backgroundColor; // runtime-mutable (BGR format) From 474c19563b914a10ef4696300e9f816570b391f2 Mon Sep 17 00:00:00 2001 From: Classic0306 <190026317+Classic0306@users.noreply.github.com> Date: Sat, 20 Jun 2026 14:33:57 +0200 Subject: [PATCH 16/16] fix merge conflict --- src/gl/gl_renderer.c | 10 +++++----- src/runner.c | 35 +++++++++++++++++++---------------- src/vm_builtins.c | 2 +- 3 files changed, 25 insertions(+), 22 deletions(-) diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index ff45ae94..32eb7869 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -635,8 +635,8 @@ static void glBeginGUI(Renderer* renderer, MAYBE_UNUSED int32_t guiW, MAYBE_UNUS Matrix4f_Orthographic(&ProjectionMatrix, (float) guiW, (float) guiH, 32000.0, 0.0); Matrix4f ViewMatrix; - float x = (float) guiW /2; - float y = (float) guiH /2; + float x = (float) guiW * 0.5f; + float y = (float) guiH * 0.5f; Matrix4f_identity(&ViewMatrix); Matrix4f_LookAt(&ViewMatrix, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0); camera->ViewMatrix = ViewMatrix; @@ -2076,11 +2076,11 @@ static bool glSetRenderTarget(Renderer* renderer, int32_t surfaceId, bool implic } else { //camera will use full surface. Matrix4f ProjectionMatrix; - Matrix4f_Orthographic(&ProjectionMatrix, (float) gl->surfaceWidth[surfaceId], (float) -gl->surfaceHeight[surfaceId], 32000.0, 0.0); + Matrix4f_Orthographic(&ProjectionMatrix, (float) gl->surfaceWidth[surfaceId], -((float) gl->surfaceHeight[surfaceId]), 32000.0, 0.0); Matrix4f ViewMatrix; - float x = (float) gl->surfaceWidth[surfaceId] /2; - float y = (float) gl->surfaceHeight[surfaceId] /2; + float x = (float) gl->surfaceWidth[surfaceId] * 0.5f; + float y = (float) gl->surfaceHeight[surfaceId] * 0.5f; Matrix4f_identity(&ViewMatrix); Matrix4f_LookAt(&ViewMatrix, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0); gl->base.CameraCurrent = SURFACE_CAMERA; diff --git a/src/runner.c b/src/runner.c index 007abc97..312a2bbe 100644 --- a/src/runner.c +++ b/src/runner.c @@ -1172,28 +1172,31 @@ void Runner_drawViews(Runner* runner, int32_t gameW, int32_t gameH, bool debugSh } if (!anyViewRendered) { - // See GameMaker-HTML5's "DrawViews", in specific the !m_enableviews path - // When views aren't used, the room width/height is used - int32_t viewX, viewY, viewW, viewH; - expandViewAxis(0, (int32_t) runner->currentRoom->width, gameW, widescreenBaseW, &viewX, &viewW); - expandViewAxis(0, (int32_t) runner->currentRoom->height, gameH, widescreenBaseH, &viewY, &viewH); - applyFreeCamera(runner, &viewX, &viewY, &viewW, &viewH); - renderer->vtable->beginView(renderer, viewX, viewY, viewW, viewH, 0, 0, gameW, gameH, 0); - + // No views enabled: render with default full-screen view. + // gameW/gameH already include the widescreen extra, shift the world origin by half of it on each grown axis so the original room stays centered and the revealed area is split evenly between the opposing edges. + runner->viewCurrent = 0; + GMLCamera* camera = Runner_getCameraForView(runner, (int32_t) runner->viewCurrent); + runner->renderer->CameraCurrent = runner->views[runner->viewCurrent].cameraId; + int32_t fullViewX = -(runner->widescreenExtraWidth / 2); + int32_t fullViewY = -(runner->widescreenExtraHeight / 2); + int32_t fullViewW = gameW; + int32_t fullViewH = gameH; + applyFreeCamera(runner, &fullViewX, &fullViewY, &fullViewW, &fullViewH); + //make default projection Matrix4f ProjectionMatrix; - Matrix4f_Orthographic(&ProjectionMatrix, (float) gameW, (float) -gameH, 32000.0, 0.0); + Matrix4f_Orthographic(&ProjectionMatrix, (float) runner->currentRoom->width, -((float) runner->currentRoom->height), 32000.0, 0.0); Matrix4f ViewMatrix; - float x = (float) gameW /2; - float y = (float) gameH /2; + float x = (float) runner->currentRoom->width * 0.5f; + float y = (float) runner->currentRoom->height * 0.5f; Matrix4f_identity(&ViewMatrix); Matrix4f_LookAt(&ViewMatrix, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0); if (camera != nullptr) { camera->viewX = 0; camera->viewY = 0; - camera->viewWidth = gameW; - camera->viewHeight = gameH; + camera->viewWidth = runner->currentRoom->width; + camera->viewHeight = runner->currentRoom->height; camera->viewAngle = 0.0; camera->ViewMatrix = ViewMatrix; camera->ProjectionMatrix = ProjectionMatrix; @@ -1340,11 +1343,11 @@ static void initDefaultCameraFromRoomView(GMLCamera* camera, RoomView* roomView) camera->viewAngle = 0; //make default projection Matrix4f ProjectionMatrix; - Matrix4f_Orthographic(&ProjectionMatrix, (float) camera->viewWidth, (float) -camera->viewHeight, 32000.0, 0.0); + Matrix4f_Orthographic(&ProjectionMatrix, (float) camera->viewWidth, -((float) camera->viewHeight), 32000.0, 0.0); Matrix4f ViewMatrix; - float x = camera->viewX + camera->viewWidth/2; - float y = camera->viewY + camera->viewHeight/2; + float x = camera->viewX + camera->viewWidth * 0.5f; + float y = camera->viewY + camera->viewHeight * 0.5f; Matrix4f_identity(&ViewMatrix); Matrix4f_LookAt(&ViewMatrix, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0); Matrix4f_translate(&ViewMatrix, x, y, 0.0f); diff --git a/src/vm_builtins.c b/src/vm_builtins.c index e71ddff8..43d659f5 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -228,7 +228,7 @@ static void UpdateCameraViewSimple(GMLCamera* camera) { Matrix4f_translate(&ViewMatrix, -x, -y, 0.0f); Matrix4f ProjectionMatrix; - Matrix4f_Orthographic(&ProjectionMatrix, (float) camera->viewWidth, (float) -camera->viewHeight, 32000.0, 0.0); + Matrix4f_Orthographic(&ProjectionMatrix, (float) camera->viewWidth, -((float) camera->viewHeight), 32000.0, 0.0); camera->ViewMatrix = ViewMatrix;