From 278deb33aa1ef7f57ee47dd65e4c07afa80f36e0 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/26] 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 aabb8efdc..dbb496a76 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -663,6 +663,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; @@ -670,6 +671,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 dbbe8c77f..237c206e7 100644 --- a/src/runner.h +++ b/src/runner.h @@ -159,6 +159,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 07d4a389e..a35c54dab 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -3020,20 +3020,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; @@ -3555,9 +3555,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; @@ -3572,6 +3587,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(); } @@ -3759,9 +3776,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(); } @@ -16288,7 +16310,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 fe6c64265bc7ede2241a2abe21ceddd95808fbdb 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/26] 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 237c206e7..7285725e1 100644 --- a/src/runner.h +++ b/src/runner.h @@ -156,9 +156,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 a35c54dab..6f87f5f2b 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -3550,11 +3550,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 59bbbd548843863426be2aa46c1a26e277dd103f 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/26] 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 6f87f5f2b..119d3cade 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -3580,8 +3580,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 43143e67c257967429a8e632a99ce7f75e6abfc7 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/26] change more things to use matricies! I kinda forgor what else I did --- src/gl/gl_renderer.c | 42 ++++++++--- src/gl/gl_renderer.h | 2 + src/gl_legacy/gl_legacy_renderer.c | 4 +- src/renderer.h | 3 +- src/runner.c | 8 ++- src/vm_builtins.c | 110 +++++++++++++++++++++++++++-- 6 files changed, 148 insertions(+), 21 deletions(-) diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index dbb496a76..1f93a5169 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -27,9 +27,9 @@ // ===[ Shader Sources ]=== static const char* baseVertexShader = - "uniform mat4 uProjection;\n" + "uniform mat4 uWorldViewProjection;\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"; @@ -643,7 +643,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); @@ -661,16 +661,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; } @@ -697,7 +711,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); @@ -1981,7 +1995,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; @@ -2537,6 +2551,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; @@ -2611,6 +2632,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 6ca2e97b7..e68c044b0 100644 --- a/src/gl/gl_renderer.h +++ b/src/gl/gl_renderer.h @@ -49,6 +49,8 @@ typedef struct { bool colorWriteR, colorWriteG, colorWriteB, colorWriteA; bool fogEnable; uint32_t fogColor; // BGR + float fogStart; + float fogEnd; GLuint vao, vbo, ebo; Vertex* vertexData; // MAX_QUADS * VERTICES_PER_QUAD vertices diff --git a/src/gl_legacy/gl_legacy_renderer.c b/src/gl_legacy/gl_legacy_renderer.c index f28a277ce..290632b69 100644 --- a/src/gl_legacy/gl_legacy_renderer.c +++ b/src/gl_legacy/gl_legacy_renderer.c @@ -203,8 +203,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 b434bb3b7..342ac77a3 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -80,7 +80,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); @@ -159,6 +159,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 5ceb551d6..cec2cb87f 100644 --- a/src/runner.c +++ b/src/runner.c @@ -1165,9 +1165,11 @@ void Runner_drawViews(Runner* runner, int32_t gameW, int32_t gameH, bool debugSh if (runner->drawBackgroundColor) renderer->vtable->clearScreen(renderer, runner->currentRoom->backgroundColor, 1.0f); - 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 119d3cade..052d31b80 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -2965,6 +2965,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(); @@ -3717,6 +3734,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); } @@ -3772,10 +3873,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(); @@ -16260,7 +16359,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 2a711375294a12a75b64942a674fb9718ceacb19 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/26] I somehow already forgor what else I did --- src/gl/gl_renderer.c | 32 ++++--- src/matrix_math.h | 81 +++++++++++++++++ src/runner.c | 47 ++++++++++ src/runner.h | 4 +- src/vm_builtins.c | 210 +++++++++++++++---------------------------- 5 files changed, 221 insertions(+), 153 deletions(-) diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index 1f93a5169..f72246abb 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -629,28 +629,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); if (hasVAO()) glBindVertexArray(gl->vao); - renderer->previousViewMatrix = projection; } @@ -2555,6 +2548,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 240875b41..9973a092d 100644 --- a/src/matrix_math.h +++ b/src/matrix_math.h @@ -52,6 +52,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 cec2cb87f..fca2ffb9b 100644 --- a/src/runner.c +++ b/src/runner.c @@ -1051,6 +1051,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); @@ -1194,6 +1207,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); @@ -1212,6 +1230,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); @@ -1346,6 +1376,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 7285725e1..fe57d8710 100644 --- a/src/runner.h +++ b/src/runner.h @@ -146,8 +146,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 052d31b80..1f92dc353 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -218,6 +218,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) { @@ -1571,22 +1586,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: @@ -1612,7 +1639,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: { @@ -2914,14 +2944,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(ctx->dataWin->gen8.wadVersion, &mat)); @@ -2974,7 +2997,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); } @@ -2982,7 +3005,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(); @@ -2997,60 +3019,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; @@ -3553,8 +3526,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(); } @@ -3671,7 +3653,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(); } @@ -3724,8 +3718,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]); @@ -3735,83 +3729,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 5f2d4f40498cc4ee2fac15ffeaf50dc5440bde02 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/26] clean up a little bit --- src/runner.h | 1 - src/vm_builtins.c | 23 ++--------------------- 2 files changed, 2 insertions(+), 22 deletions(-) diff --git a/src/runner.h b/src/runner.h index fe57d8710..4ba3d487f 100644 --- a/src/runner.h +++ b/src/runner.h @@ -156,7 +156,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 1f92dc353..39ab865c6 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -3528,15 +3528,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(); } @@ -3658,13 +3650,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(); } @@ -3740,14 +3726,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 0161a05ca5cfa83255f806d0dbadb9699cb796a5 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/26] make rendering to surfaces work in a hacky way --- src/gl/gl_renderer.c | 46 +++++++++++++++++++++++++++------------- src/renderer.h | 2 ++ src/runner.c | 50 +++++++++++++++++++++++++++++++------------- src/vm_builtins.c | 13 +----------- 4 files changed, 69 insertions(+), 42 deletions(-) diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index f72246abb..b7e79fb9b 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -676,9 +676,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) { @@ -702,10 +700,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); @@ -795,11 +793,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. @@ -1980,18 +1978,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 342ac77a3..7634c6ee0 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -9,6 +9,7 @@ #include "data_win.h" #include "instance.h" + // GameMaker Blend Modes #define bm_complex -1 @@ -183,6 +184,7 @@ struct Renderer { Matrix4f gmlMatrices[MATRICES_MAX]; int32_t currentShader; BlendFactors blendFactors; + int32_t V_SurfaceID; }; // ===[ Shared Helpers (platform-agnostic) ]=== diff --git a/src/runner.c b/src/runner.c index fca2ffb9b..50e93acc3 100644 --- a/src/runner.c +++ b/src/runner.c @@ -1053,16 +1053,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); @@ -1180,7 +1183,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); @@ -1209,7 +1214,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); @@ -1232,16 +1239,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); @@ -3967,6 +3981,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); } @@ -3981,6 +3998,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 39ab865c6..83b379301 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -3716,18 +3716,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 f5d518548c7dbb777fca6046f454b26745f6affa 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/26] 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 b7e79fb9b..ac718d83a 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -1983,16 +1983,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 7634c6ee0..4fba8e4cc 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -175,7 +175,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 d550cd63477523286e7e332c35696c9080982bfd 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/26] 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 ac718d83a..58480356c 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -1979,6 +1979,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; } @@ -1987,6 +1988,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); @@ -1997,6 +1999,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; } @@ -2661,5 +2681,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 4fba8e4cc..e5d585201 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -43,6 +43,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. @@ -185,6 +187,7 @@ struct Renderer { int32_t currentShader; BlendFactors blendFactors; int32_t V_SurfaceID; + int32_t CameraCurrent; }; // ===[ Shared Helpers (platform-agnostic) ]=== diff --git a/src/runner.c b/src/runner.c index 50e93acc3..9eb4893ae 100644 --- a/src/runner.c +++ b/src/runner.c @@ -1190,6 +1190,7 @@ void Runner_drawViews(Runner* runner, int32_t gameW, int32_t gameH, bool debugSh runner->viewCurrent = (int32_t) vi; + runner->renderer->CameraCurrent = runner->viewCurrent; Runner_draw(runner); renderer->vtable->flush(renderer); @@ -1210,6 +1211,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; @@ -1266,6 +1268,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 ]=== @@ -1367,6 +1370,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 4ba3d487f..71eecf4ef 100644 --- a/src/runner.h +++ b/src/runner.h @@ -475,6 +475,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 83b379301..2f840acf1 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -228,7 +228,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; } @@ -3752,7 +3758,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 96b1bcbf1603ea0d55bf11936959040ceddf0905 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/26] 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 58480356c..369caf400 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -793,11 +793,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 e68c044b0..6ca2e97b7 100644 --- a/src/gl/gl_renderer.h +++ b/src/gl/gl_renderer.h @@ -49,8 +49,6 @@ typedef struct { bool colorWriteR, colorWriteG, colorWriteB, colorWriteA; bool fogEnable; uint32_t fogColor; // BGR - float fogStart; - float fogEnd; GLuint vao, vbo, ebo; Vertex* vertexData; // MAX_QUADS * VERTICES_PER_QUAD vertices diff --git a/src/renderer.h b/src/renderer.h index e5d585201..04e3d3837 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -9,7 +9,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 9eb4893ae..dad4e9cb3 100644 --- a/src/runner.c +++ b/src/runner.c @@ -1190,7 +1190,7 @@ void Runner_drawViews(Runner* runner, int32_t gameW, int32_t gameH, bool debugSh 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); @@ -1211,7 +1211,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; @@ -1268,7 +1268,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 2f840acf1..edac9e6b5 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -3572,11 +3572,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(); @@ -3654,8 +3649,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(); @@ -3776,13 +3769,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 c4a20e8bbfc18e148d903d85b1e191432884ee20 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/26] remove hacks and hopefully it's good enough --- src/gl/gl_renderer.c | 32 ++++++++++++++++++++++---------- src/runner.c | 40 +++++++++++----------------------------- src/vm_builtins.c | 23 +++++++++++------------ 3 files changed, 44 insertions(+), 51 deletions(-) diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index 369caf400..c6b45f6f3 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -1968,6 +1968,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; @@ -1977,17 +1986,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); @@ -1997,7 +2008,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; @@ -2016,12 +2026,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; } @@ -2680,7 +2693,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/runner.c b/src/runner.c index dad4e9cb3..2a42d8b4d 100644 --- a/src/runner.c +++ b/src/runner.c @@ -1063,9 +1063,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); @@ -1183,9 +1180,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); @@ -1216,9 +1210,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); @@ -1249,14 +1240,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); @@ -1370,7 +1358,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; @@ -1395,22 +1383,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. @@ -3985,9 +3973,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); } @@ -4002,9 +3987,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 edac9e6b5..babb98259 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -218,7 +218,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; @@ -1594,7 +1594,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; } @@ -1602,23 +1602,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; } @@ -1647,7 +1647,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; } @@ -3534,7 +3534,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(); } @@ -3649,7 +3649,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(); } @@ -3715,7 +3715,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); } @@ -3751,7 +3751,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 10e0e92837b7f4a22ad5f88f1f075e66c757f5f6 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/26] 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 c6b45f6f3..0dc7f3b3c 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -547,6 +547,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); @@ -620,7 +646,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; @@ -640,6 +666,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); @@ -653,33 +693,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 290632b69..23e99cfd1 100644 --- a/src/gl_legacy/gl_legacy_renderer.c +++ b/src/gl_legacy/gl_legacy_renderer.c @@ -203,7 +203,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 2a42d8b4d..47febec88 100644 --- a/src/runner.c +++ b/src/runner.c @@ -1208,10 +1208,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); @@ -1241,6 +1237,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; } @@ -3962,7 +3963,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 babb98259..e8c054c48 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -3768,8 +3768,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 beabe398c04970cc6437bfa0fb1dad1d398a0a53 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/26] rebase and fix little things --- src/gl/gl_renderer.c | 37 +++++++++++++++++++++++++------------ src/runner.c | 3 ++- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index 0dc7f3b3c..4a1fb4aef 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -259,6 +259,14 @@ static void glInit(Renderer* renderer, DataWin* dataWin) { GLRenderer* gl = (GLRenderer*) renderer; renderer->dataWin = dataWin; + Matrix4f World; + Matrix4f_identity(&World); + renderer->gmlMatrices[MATRIX_WORLD] = World; + + Matrix4f World; + Matrix4f_identity(&World); + renderer->gmlMatrices[MATRIX_WORLD] = World; + GMLShader* defaultShader = (GMLShader*)safeCalloc(1, sizeof(GMLShader)); const char* versionStr = (const char*) glGetString(GL_VERSION); fprintf(stderr, "OpenGL version: %s\n", versionStr); @@ -505,8 +513,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); @@ -533,13 +547,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); @@ -562,8 +581,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; @@ -675,11 +693,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); @@ -2014,6 +2027,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); @@ -2614,8 +2628,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 47febec88..d8a415e7d 100644 --- a/src/runner.c +++ b/src/runner.c @@ -1246,7 +1246,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 77fdb3868a18f1f49b0241f92e504a94a0de9799 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/26] remove more thing, try fix GUI kinda --- src/gl/gl_renderer.c | 42 ++++++++++++++++++++++++++++++------------ src/runner.c | 31 ++++--------------------------- src/vm_builtins.c | 16 ++++++++++++++-- 3 files changed, 48 insertions(+), 41 deletions(-) diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index 4a1fb4aef..bf5b70c3e 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -706,7 +706,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; @@ -727,25 +727,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); if (hasVAO()) 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 d8a415e7d..964fbdd2b 100644 --- a/src/runner.c +++ b/src/runner.c @@ -1051,19 +1051,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); @@ -1185,6 +1172,9 @@ void Runner_drawViews(Runner* runner, int32_t gameW, int32_t gameH, bool debugSh 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); @@ -3964,20 +3954,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 e8c054c48..d67e676b3 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -2996,14 +2996,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 ce8c9aa44dd77e16ede88aba1a95774e48e5604e 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/26] 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 bf5b70c3e..7bdb07572 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -726,9 +726,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); @@ -737,8 +749,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); @@ -751,8 +764,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); @@ -762,9 +787,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 04e3d3837..f4f710d52 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -41,7 +41,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 964fbdd2b..68d3458c2 100644 --- a/src/runner.c +++ b/src/runner.c @@ -1351,6 +1351,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 71eecf4ef..ee5efd396 100644 --- a/src/runner.h +++ b/src/runner.h @@ -476,6 +476,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 ce3e26a4fffb709e00c2d36d2bc465b9a25cbefe 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/26] 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 7bdb07572..452da7803 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -745,8 +745,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; @@ -2072,11 +2072,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 68d3458c2..190a49832 100644 --- a/src/runner.c +++ b/src/runner.c @@ -1209,28 +1209,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; @@ -1377,11 +1380,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 d67e676b3..dbc391779 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -230,7 +230,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; From 82468e7eb6c81b07129986ca97c9ed852b79ff55 Mon Sep 17 00:00:00 2001 From: Classic0306 <190026317+Classic0306@users.noreply.github.com> Date: Sun, 21 Jun 2026 15:37:14 +0200 Subject: [PATCH 17/26] fix little oversight and PS2 build --- src/ps2/gs_renderer.c | 3 ++- src/runner.c | 17 ++++++++--------- src/vm_builtins.c | 1 + 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/ps2/gs_renderer.c b/src/ps2/gs_renderer.c index 1fa771334..436bd7c89 100644 --- a/src/ps2/gs_renderer.c +++ b/src/ps2/gs_renderer.c @@ -1157,8 +1157,9 @@ static void gsEndView(MAYBE_UNUSED Renderer* renderer) { // No-op } -static void gsApplyProjection(MAYBE_UNUSED Renderer* renderer, MAYBE_UNUSED const Matrix4f* worldToClip) { +static void gsApplyProjection(MAYBE_UNUSED Renderer* renderer, MAYBE_UNUSED const Matrix4f* ViewMatrix, MAYBE_UNUSED const Matrix4f* ProjectionMatrix) { // No-op + //Um but I do feel like the PS2 should be capable of this though? } static void gsSetGuiProjection(Renderer* renderer, int32_t guiW, int32_t guiH, MAYBE_UNUSED int32_t portW, MAYBE_UNUSED int32_t portH, MAYBE_UNUSED bool renderingToUserSurface) { diff --git a/src/runner.c b/src/runner.c index 190a49832..5a6133620 100644 --- a/src/runner.c +++ b/src/runner.c @@ -1209,17 +1209,16 @@ void Runner_drawViews(Runner* runner, int32_t gameW, int32_t gameH, bool debugSh } if (!anyViewRendered) { - // 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); - + // 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); + //whenever somebody feels like it, do make that free cam thingy work with this //make default projection Matrix4f ProjectionMatrix; Matrix4f_Orthographic(&ProjectionMatrix, (float) runner->currentRoom->width, -((float) runner->currentRoom->height), 32000.0, 0.0); @@ -1239,7 +1238,7 @@ void Runner_drawViews(Runner* runner, int32_t gameW, int32_t gameH, bool debugSh camera->ProjectionMatrix = ProjectionMatrix; } - renderer->vtable->beginView(renderer, fullViewX, fullViewY, fullViewW, fullViewH, 0, 0, gameW, gameH, 0.0f); + renderer->vtable->beginView(renderer, viewX, viewY, viewW, viewH, 0, 0, gameW, gameH, 0); Runner_draw(runner); diff --git a/src/vm_builtins.c b/src/vm_builtins.c index dbc391779..7e5de420f 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -3639,6 +3639,7 @@ static RValue builtin_camera_set_view_size(VMContext* ctx, RValue* args, int32_t if (camera != nullptr) { camera->viewWidth = RValue_toInt32(args[1]); camera->viewHeight = RValue_toInt32(args[2]); + UpdateCameraViewSimple(camera); } return RValue_makeUndefined(); } From a1e440d39ee5a8a9107263652ce650a1dbf6b75e Mon Sep 17 00:00:00 2001 From: Classic0306 <190026317+Classic0306@users.noreply.github.com> Date: Mon, 29 Jun 2026 17:06:25 +0200 Subject: [PATCH 18/26] fix variable name casing in Matrix4f_LookAt --- src/matrix_math.h | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/matrix_math.h b/src/matrix_math.h index 9973a092d..3af37907d 100644 --- a/src/matrix_math.h +++ b/src/matrix_math.h @@ -52,19 +52,8 @@ 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) { +static inline Matrix4f* Matrix4f_LookAt(Matrix4f* dest, float xFrom, float yFrom, float zFrom, float xTo, float yTo, float zTo, float xUp, float yUp, float zUp) { - 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; From ec991b049b7c4f5914f4ca1e37a10ead2a580b8b Mon Sep 17 00:00:00 2001 From: Classic0306 <190026317+Classic0306@users.noreply.github.com> Date: Mon, 29 Jun 2026 17:32:26 +0200 Subject: [PATCH 19/26] fix variable casing --- src/gl/gl_renderer.c | 62 +++++++++++++++--------------- src/gl_legacy/gl_legacy_renderer.c | 4 +- src/ps2/gs_renderer.c | 2 +- src/renderer.h | 2 +- src/runner.c | 42 ++++++++++---------- src/runner.h | 4 +- src/vm_builtins.c | 36 ++++++++--------- 7 files changed, 76 insertions(+), 76 deletions(-) diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index 452da7803..e34b2a586 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -567,15 +567,15 @@ 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) { +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 View = *viewMatrix; + Matrix4f Projection = *projectionMatrix; Matrix4f WorldView; Matrix4f_multiply(&WorldView, &View, &World); @@ -691,7 +691,7 @@ static void glBeginView(Renderer* renderer, MAYBE_UNUSED int32_t viewX, MAYBE_UN 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); + glApplyProjection(renderer,&camera->viewMatrix,&camera->projectionMatrix); glShaderSettingsRefresh(renderer); glActiveTexture(GL_TEXTURE1); @@ -741,17 +741,17 @@ static void glBeginGUI(Renderer* renderer, MAYBE_UNUSED int32_t guiW, MAYBE_UNUS camera->objectId = -1; camera->viewAngle = 0; - Matrix4f ProjectionMatrix; - Matrix4f_Orthographic(&ProjectionMatrix, (float) guiW, (float) guiH, 32000.0, 0.0); + Matrix4f projectionMatrix; + Matrix4f_Orthographic(&projectionMatrix, (float) guiW, (float) guiH, 32000.0, 0.0); - Matrix4f ViewMatrix; + 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); - camera->ViewMatrix = ViewMatrix; - camera->ProjectionMatrix = ProjectionMatrix; - glApplyProjection(renderer,&camera->ViewMatrix,&camera->ProjectionMatrix); + Matrix4f_identity(&viewMatrix); + Matrix4f_LookAt(&viewMatrix, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0); + camera->viewMatrix = viewMatrix; + camera->projectionMatrix = projectionMatrix; + glApplyProjection(renderer,&camera->viewMatrix,&camera->projectionMatrix); glActiveTexture(GL_TEXTURE1); @@ -779,17 +779,17 @@ static void glSetGuiProjection(Renderer* renderer, int32_t guiW, int32_t guiH, M 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); - if (renderingToUserSurface) Matrix4f_flipClipY(&ProjectionMatrix); - Matrix4f ViewMatrix; + 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); - camera->ViewMatrix = ViewMatrix; - camera->ProjectionMatrix = ProjectionMatrix; - glApplyProjection(renderer,&camera->ViewMatrix,&camera->ProjectionMatrix); + Matrix4f_identity(&viewMatrix); + Matrix4f_LookAt(&viewMatrix, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0); + camera->viewMatrix = viewMatrix; + camera->projectionMatrix = projectionMatrix; + glApplyProjection(renderer,&camera->viewMatrix,&camera->projectionMatrix); } static void glEndGUI(Renderer* renderer) { @@ -2057,7 +2057,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,&camera->ViewMatrix,&camera->ProjectionMatrix); + glApplyProjection(renderer,&camera->viewMatrix,&camera->projectionMatrix); return true; } @@ -2067,18 +2067,18 @@ static bool glSetRenderTarget(Renderer* renderer, int32_t surfaceId, bool implic //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); + 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); + Matrix4f projectionMatrix; + Matrix4f_Orthographic(&projectionMatrix, (float) gl->surfaceWidth[surfaceId], -((float) gl->surfaceHeight[surfaceId]), 32000.0, 0.0); - Matrix4f ViewMatrix; + Matrix4f viewMatrix; 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); + 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; GMLCamera* camera = &renderer->runner->surfaceCamera; @@ -2095,11 +2095,11 @@ static bool glSetRenderTarget(Renderer* renderer, int32_t surfaceId, bool implic camera->objectId = -1; camera->viewAngle = 0; - camera->ProjectionMatrix = ProjectionMatrix; - camera->ViewMatrix = ViewMatrix; + camera->projectionMatrix = projectionMatrix; + camera->viewMatrix = viewMatrix; glViewport(0, 0, gl->surfaceWidth[surfaceId], gl->surfaceHeight[surfaceId]); glDisable(GL_SCISSOR_TEST); - glApplyProjection(renderer, &ViewMatrix,&ProjectionMatrix); + glApplyProjection(renderer, &viewMatrix,&projectionMatrix); return true; } diff --git a/src/gl_legacy/gl_legacy_renderer.c b/src/gl_legacy/gl_legacy_renderer.c index 23e99cfd1..b5dd08479 100644 --- a/src/gl_legacy/gl_legacy_renderer.c +++ b/src/gl_legacy/gl_legacy_renderer.c @@ -203,8 +203,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, MAYBE_UNUSED const Matrix4f* ViewMatrix, MAYBE_UNUSED const Matrix4f* ProjectionMatrix) { - Matrix4f projection = *ProjectionMatrix; //fix it later +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); glLoadMatrixf(projection.m); diff --git a/src/ps2/gs_renderer.c b/src/ps2/gs_renderer.c index 436bd7c89..75cbbea33 100644 --- a/src/ps2/gs_renderer.c +++ b/src/ps2/gs_renderer.c @@ -1157,7 +1157,7 @@ static void gsEndView(MAYBE_UNUSED Renderer* renderer) { // No-op } -static void gsApplyProjection(MAYBE_UNUSED Renderer* renderer, MAYBE_UNUSED const Matrix4f* ViewMatrix, MAYBE_UNUSED const Matrix4f* ProjectionMatrix) { +static void gsApplyProjection(MAYBE_UNUSED Renderer* renderer, MAYBE_UNUSED const Matrix4f* viewMatrix, MAYBE_UNUSED const Matrix4f* projectionMatrix) { // No-op //Um but I do feel like the PS2 should be capable of this though? } diff --git a/src/renderer.h b/src/renderer.h index f4f710d52..0b44b446f 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -83,7 +83,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* ViewMatrix,const Matrix4f* ProjectionMatrix); + 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); diff --git a/src/runner.c b/src/runner.c index 5a6133620..2c5b8549b 100644 --- a/src/runner.c +++ b/src/runner.c @@ -1165,14 +1165,14 @@ void Runner_drawViews(Runner* runner, int32_t gameW, int32_t gameH, bool debugSh if (runner->drawBackgroundColor) renderer->vtable->clearScreen(renderer, runner->currentRoom->backgroundColor, 1.0f); - Matrix4f ViewMatrix = camera->ViewMatrix; - Matrix4f ProjectionMatrix = camera->ProjectionMatrix; - runner->renderer->vtable->applyProjection(runner->renderer, &ViewMatrix, &ProjectionMatrix); + 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->renderer->vtable->applyProjection(runner->renderer, &viewMatrix, &projectionMatrix); Runner_draw(runner); @@ -1220,22 +1220,22 @@ void Runner_drawViews(Runner* runner, int32_t gameW, int32_t gameH, bool debugSh applyFreeCamera(runner, &viewX, &viewY, &viewW, &viewH); //whenever somebody feels like it, do make that free cam thingy work with this //make default projection - Matrix4f ProjectionMatrix; - Matrix4f_Orthographic(&ProjectionMatrix, (float) runner->currentRoom->width, -((float) runner->currentRoom->height), 32000.0, 0.0); + Matrix4f projectionMatrix; + Matrix4f_Orthographic(&projectionMatrix, (float) runner->currentRoom->width, -((float) runner->currentRoom->height), 32000.0, 0.0); - Matrix4f ViewMatrix; + Matrix4f viewMatrix; 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); + 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 = runner->currentRoom->width; camera->viewHeight = runner->currentRoom->height; camera->viewAngle = 0.0; - camera->ViewMatrix = ViewMatrix; - camera->ProjectionMatrix = ProjectionMatrix; + camera->viewMatrix = viewMatrix; + camera->projectionMatrix = projectionMatrix; } renderer->vtable->beginView(renderer, viewX, viewY, viewW, viewH, 0, 0, gameW, gameH, 0); @@ -1378,22 +1378,22 @@ static void initDefaultCameraFromRoomView(GMLCamera* camera, RoomView* roomView) camera->objectId = roomView->objectId; camera->viewAngle = 0; //make default projection - Matrix4f ProjectionMatrix; - Matrix4f_Orthographic(&ProjectionMatrix, (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 ViewMatrix; + Matrix4f viewMatrix; 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); - Matrix4f_rotateZ(&ViewMatrix, -camera->viewAngle * (float) M_PI / 180.0f); - Matrix4f_translate(&ViewMatrix, -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 = ProjectionMatrix; - camera->ViewMatrix = ViewMatrix; + camera->projectionMatrix = projectionMatrix; + camera->viewMatrix = viewMatrix; } // Copies the viewport (port) properties and enabled flag from parsed room data. diff --git a/src/runner.h b/src/runner.h index ee5efd396..a1ea343d8 100644 --- a/src/runner.h +++ b/src/runner.h @@ -156,8 +156,8 @@ typedef struct { int32_t speedY; int32_t objectId; // follow target (object index), -1 = none float viewAngle; - Matrix4f ViewMatrix; - Matrix4f ProjectionMatrix; + Matrix4f viewMatrix; + Matrix4f projectionMatrix; } GMLCamera; typedef struct { diff --git a/src/vm_builtins.c b/src/vm_builtins.c index 7e5de420f..146ed24b0 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -218,23 +218,23 @@ static DsStack* dsStackGet(Runner* runner, int32_t id) { return &runner->dsStackPool[id]; } -static void UpdateCameraViewSimple(GMLCamera* camera) { +static void updateCameraViewSimple(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); - - Matrix4f ProjectionMatrix; - Matrix4f_Orthographic(&ProjectionMatrix, (float) camera->viewWidth, -((float) camera->viewHeight), 32000.0, 0.0); + 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); + + Matrix4f projectionMatrix; + Matrix4f_Orthographic(&projectionMatrix, (float) camera->viewWidth, -((float) camera->viewHeight), 32000.0, 0.0); - camera->ViewMatrix = ViewMatrix; - camera->ProjectionMatrix = ProjectionMatrix; + camera->viewMatrix = viewMatrix; + camera->projectionMatrix = projectionMatrix; } @@ -3559,7 +3559,7 @@ 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); - camera->ViewMatrix = m; + camera->viewMatrix = m; return RValue_makeUndefined(); } @@ -3567,14 +3567,14 @@ static RValue builtin_camera_get_view_mat(VMContext* ctx, RValue* args, int32_t 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)); + 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)); + return RValue_makeArray(matrixToGml(&camera->projectionMatrix)); } static RValue builtin_camera_set_proj_mat(VMContext* ctx, RValue* args, int32_t argCount) { @@ -3584,8 +3584,8 @@ 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); - camera->ProjectionMatrix = m; - camera->ProjectionMatrix.m[Matrix_getIndex(1, 1)] = -m.m[Matrix_getIndex(1, 1)]; + camera->projectionMatrix = m; + camera->projectionMatrix.m[Matrix_getIndex(1, 1)] = -m.m[Matrix_getIndex(1, 1)]; return RValue_makeUndefined(); } @@ -3782,7 +3782,7 @@ 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) { - runner->renderer->vtable->applyProjection(runner->renderer, &camera->ViewMatrix, &camera->ProjectionMatrix); + runner->renderer->vtable->applyProjection(runner->renderer, &camera->viewMatrix, &camera->projectionMatrix); runner->renderer->CameraCurrent = RValue_toInt32(args[0]); } return RValue_makeUndefined(); From e3bac0781f9088edfbd6039d8cbe6a34b617253d Mon Sep 17 00:00:00 2001 From: Classic0306 <190026317+Classic0306@users.noreply.github.com> Date: Mon, 29 Jun 2026 17:43:16 +0200 Subject: [PATCH 20/26] am I done already... --- src/runner.c | 21 +++++++++++++++++++++ src/runner.h | 3 +++ src/vm_builtins.c | 39 +++++++++------------------------------ 3 files changed, 33 insertions(+), 30 deletions(-) diff --git a/src/runner.c b/src/runner.c index 2c5b8549b..54ed86dbb 100644 --- a/src/runner.c +++ b/src/runner.c @@ -46,6 +46,26 @@ static void freeRuntimeLayersArray(RuntimeLayer** runtimeLayerArray) { *runtimeLayerArray = nullptr; } +void Runner_updateCameraViewSimple(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); + + Matrix4f projectionMatrix; + Matrix4f_Orthographic(&projectionMatrix, (float) camera->viewWidth, -((float) camera->viewHeight), 32000.0, 0.0); + + + camera->viewMatrix = viewMatrix; + camera->projectionMatrix = projectionMatrix; + +} + // ===[ Helper: Find event action in object hierarchy ]=== // Resolves the handler for (objectIndex, eventType, eventSubtype) via the precomputed ResolvedEventTable. // Returns the CODE chunk handler id, or -1 if the object does not respond. @@ -3288,6 +3308,7 @@ static void updateViews(Runner* runner) { int32_t iy = (int32_t) GMLReal_floor(target->y); camera->viewX = followAxis(camera->viewX, camera->viewWidth, ix, camera->borderX, camera->speedX, (int32_t) room->width); camera->viewY = followAxis(camera->viewY, camera->viewHeight, iy, camera->borderY, camera->speedY, (int32_t) room->height); + Runner_updateCameraViewSimple(camera); } } } diff --git a/src/runner.h b/src/runner.h index a1ea343d8..78bbfaa87 100644 --- a/src/runner.h +++ b/src/runner.h @@ -677,6 +677,9 @@ void Runner_removeInstanceFromObjectLists(Runner* runner, Instance* inst); // Reset every per-object list to length 0 without releasing the backing arrays. void Runner_clearAllObjectLists(Runner* runner); +// Update The Camera For Basic Views! +void Runner_updateCameraViewSimple(GMLCamera* camera); + // Push a snapshot of instancesByObject[targetObjIndex] onto runner->instanceSnapshots. Returns the base offset where this snapshot begins. // The length is arrlen(runner->instanceSnapshots) - base. // Invalid indices or empty buckets push zero entries (base == current arena length). diff --git a/src/vm_builtins.c b/src/vm_builtins.c index 146ed24b0..b5e5050c8 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -218,27 +218,6 @@ static DsStack* dsStackGet(Runner* runner, int32_t id) { return &runner->dsStackPool[id]; } -static void updateCameraViewSimple(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); - - Matrix4f projectionMatrix; - Matrix4f_Orthographic(&projectionMatrix, (float) camera->viewWidth, -((float) camera->viewHeight), 32000.0, 0.0); - - - camera->viewMatrix = viewMatrix; - camera->projectionMatrix = projectionMatrix; - -} - - // ===[ BUILT-IN VARIABLE GET/SET ]=== static bool isValidAlarmIndex(int alarmIndex) { @@ -1594,7 +1573,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); - UpdateCameraViewSimple(camera); + Runner_updateCameraViewSimple(camera); } return; } @@ -1602,7 +1581,7 @@ void VMBuiltins_setVariable(VMContext* ctx, Instance* inst, int16_t builtinVarId GMLCamera* camera = Runner_getCameraForView(runner, arrayIndex); if (camera != nullptr) { camera->viewY = RValue_toInt32(val); - UpdateCameraViewSimple(camera); + Runner_updateCameraViewSimple(camera); } return; } @@ -1610,7 +1589,7 @@ void VMBuiltins_setVariable(VMContext* ctx, Instance* inst, int16_t builtinVarId GMLCamera* camera = Runner_getCameraForView(runner, arrayIndex); if (camera != nullptr) { camera->viewWidth = RValue_toInt32(val); - UpdateCameraViewSimple(camera); + Runner_updateCameraViewSimple(camera); } return; } @@ -1618,7 +1597,7 @@ void VMBuiltins_setVariable(VMContext* ctx, Instance* inst, int16_t builtinVarId GMLCamera* camera = Runner_getCameraForView(runner, arrayIndex); if (camera != nullptr) { camera->viewHeight = RValue_toInt32(val); - UpdateCameraViewSimple(camera); + Runner_updateCameraViewSimple(camera); } return; } @@ -1647,7 +1626,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); - UpdateCameraViewSimple(camera); + Runner_updateCameraViewSimple(camera); } return; } @@ -3546,7 +3525,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]); - UpdateCameraViewSimple(camera); + Runner_updateCameraViewSimple(camera); } return RValue_makeUndefined(); } @@ -3639,7 +3618,7 @@ static RValue builtin_camera_set_view_size(VMContext* ctx, RValue* args, int32_t if (camera != nullptr) { camera->viewWidth = RValue_toInt32(args[1]); camera->viewHeight = RValue_toInt32(args[2]); - UpdateCameraViewSimple(camera); + Runner_updateCameraViewSimple(camera); } return RValue_makeUndefined(); } @@ -3662,7 +3641,7 @@ static RValue builtin_camera_set_view_angle(VMContext* ctx, RValue* args, int32_ if (camera != nullptr) { camera->viewAngle = (float) RValue_toReal(args[1]); - UpdateCameraViewSimple(camera); + Runner_updateCameraViewSimple(camera); } return RValue_makeUndefined(); } @@ -3728,7 +3707,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]); - UpdateCameraViewSimple(camera); + Runner_updateCameraViewSimple(camera); return RValue_makeReal(id); } From 885044c704bd8225b0be7c71870bd60978c46385 Mon Sep 17 00:00:00 2001 From: Classic0306 <190026317+Classic0306@users.noreply.github.com> Date: Mon, 29 Jun 2026 18:15:58 +0200 Subject: [PATCH 21/26] fix merge conflicts --- src/gl/gl_renderer.c | 50 ++++++++++++++++++++------------------------ src/vm_builtins.c | 6 +++--- 2 files changed, 26 insertions(+), 30 deletions(-) diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index e34b2a586..f02f37b88 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -259,13 +259,9 @@ static void glInit(Renderer* renderer, DataWin* dataWin) { GLRenderer* gl = (GLRenderer*) renderer; renderer->dataWin = dataWin; - Matrix4f World; - Matrix4f_identity(&World); - renderer->gmlMatrices[MATRIX_WORLD] = World; - - Matrix4f World; - Matrix4f_identity(&World); - renderer->gmlMatrices[MATRIX_WORLD] = World; + Matrix4f world; + Matrix4f_identity(&world); + renderer->gmlMatrices[MATRIX_WORLD] = world; GMLShader* defaultShader = (GMLShader*)safeCalloc(1, sizeof(GMLShader)); const char* versionStr = (const char*) glGetString(GL_VERSION); @@ -573,20 +569,20 @@ static void glApplyProjection(Renderer* renderer, const Matrix4f* viewMatrix,con // 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 world = renderer->gmlMatrices[MATRIX_WORLD]; + Matrix4f view = *viewMatrix; + Matrix4f projection = *projectionMatrix; - Matrix4f WorldView; - Matrix4f_multiply(&WorldView, &View, &World); + Matrix4f worldView; + Matrix4f_multiply(&worldView, &view, &world); - Matrix4f WorldViewProjection; - Matrix4f_multiply(&WorldViewProjection, &Projection, &WorldView); + Matrix4f worldViewProjection; + Matrix4f_multiply(&worldViewProjection, &projection, &worldView); - renderer->gmlMatrices[MATRIX_VIEW] = View; - renderer->gmlMatrices[MATRIX_PROJECTION] = Projection; - renderer->gmlMatrices[MATRIX_WORLD_VIEW] = WorldView; - renderer->gmlMatrices[MATRIX_WORLD_VIEW_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); } @@ -2663,18 +2659,18 @@ static void glSetMatrix(Renderer* renderer, int32_t MatrixType, Matrix4f Matrix) 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 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 worldView; + Matrix4f_multiply(&worldView, &view, &world); - Matrix4f WorldViewProjection; - Matrix4f_multiply(&WorldViewProjection, &Projection, &WorldView); + Matrix4f worldViewProjection; + Matrix4f_multiply(&worldViewProjection, &projection, &worldView); - renderer->gmlMatrices[MATRIX_WORLD_VIEW] = WorldView; - renderer->gmlMatrices[MATRIX_WORLD_VIEW_PROJECTION] = WorldViewProjection; + renderer->gmlMatrices[MATRIX_WORLD_VIEW] = worldView; + renderer->gmlMatrices[MATRIX_WORLD_VIEW_PROJECTION] = worldViewProjection; glShaderSettingsRefresh(renderer); diff --git a/src/vm_builtins.c b/src/vm_builtins.c index b5e5050c8..947b73566 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -2981,7 +2981,7 @@ static RValue builtin_matrix_get(MAYBE_UNUSED VMContext *ctx, RValue *args, int3 if (toPrevMatrix && !rvalueIsMatrix(args[1])) return RValue_makeUndefined(); if (!toPrevMatrix) { - return RValue_makeArray(matrixToGml(&ctx->runner->renderer->gmlMatrices[Matrix])); + return RValue_makeArray(matrixToGml(ctx->dataWin->gen8.wadVersion, &ctx->runner->renderer->gmlMatrices[Matrix])); } else { repeat (16, i) { *GMLArray_slot(destArray, i) = RValue_makeReal(ctx->runner->renderer->gmlMatrices[Matrix].m[i]); @@ -3546,14 +3546,14 @@ static RValue builtin_camera_get_view_mat(VMContext* ctx, RValue* args, int32_t 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)); + return RValue_makeArray(matrixToGml(ctx->dataWin->gen8.wadVersion, &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)); + return RValue_makeArray(matrixToGml(ctx->dataWin->gen8.wadVersion, &camera->projectionMatrix)); } static RValue builtin_camera_set_proj_mat(VMContext* ctx, RValue* args, int32_t argCount) { From b61edad0f145459c92615ba6648441e8c2b3e492 Mon Sep 17 00:00:00 2001 From: Classic0306 <190026317+Classic0306@users.noreply.github.com> Date: Mon, 29 Jun 2026 18:58:24 +0200 Subject: [PATCH 22/26] did I finally do it correctly? --- src/gl/gl_renderer.c | 52 ++++++++++++++++++++++---------------------- src/renderer.h | 2 +- src/runner.c | 8 +++---- src/vm_builtins.c | 38 +++++++++++++++----------------- 4 files changed, 49 insertions(+), 51 deletions(-) diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index f02f37b88..25f9aa3df 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -509,14 +509,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]); - } + 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, FlippedClip[0].m); + glUniformMatrix4fv(gmMatricesUniform->location, 5, GL_FALSE, flippedClip[0].m); } if (gmFogColourUniform != nullptr) { glUniform1i(gmFogColourUniform->location, gl->fogColor); @@ -548,13 +548,13 @@ static void glShaderSettingsRefresh(Renderer* renderer) { GLShaderUniform* uAlphaTestRef = findShaderUniformByName(gl->defaultShaderProgram, "uAlphaTestRef"); GLShaderUniform* uAlphaTestEnabled = findShaderUniformByName(gl->defaultShaderProgram, "uAlphaTestEnabled"); GLShaderUniform* uTexture = findShaderUniformByName(gl->defaultShaderProgram, "uTexture"); - Matrix4f FlippedClip[MATRICES_MAX]; + Matrix4f flippedClip[MATRICES_MAX]; for (int32_t i = 0; i < MATRICES_MAX; i++) { - FlippedClip[i] = renderer->gmlMatrices[i]; - Matrix4f_flipClipY(&FlippedClip[i]); + flippedClip[i] = renderer->gmlMatrices[i]; + Matrix4f_flipClipY(&flippedClip[i]); } - glUniformMatrix4fv(uWorldViewProjection->location, 1, GL_FALSE, FlippedClip[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); @@ -680,13 +680,13 @@ static void glBeginView(Renderer* renderer, MAYBE_UNUSED int32_t viewX, MAYBE_UN glEnable(GL_SCISSOR_TEST); glScissor(portX, portY, portW, portH); - int32_t ViewCurrent = 0; + int32_t viewCurrent = 0; if (renderer->runner->viewsEnabled) { - ViewCurrent = renderer->runner->viewCurrent; + viewCurrent = renderer->runner->viewCurrent; } - RuntimeView* view = &renderer->runner->views[ViewCurrent]; - gl->base.CameraCurrent = view->cameraId; - GMLCamera* camera = Runner_getCameraById(renderer->runner, gl->base.CameraCurrent); + 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); glShaderSettingsRefresh(renderer); @@ -723,7 +723,7 @@ 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; + gl->base.cameraCurrent = GUI_CAMERA; GMLCamera* camera = &renderer->runner->guiCamera; camera->allocated = true; camera->viewX = 0.0; @@ -760,7 +760,7 @@ 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 = GUI_CAMERA; + gl->base.cameraCurrent = GUI_CAMERA; GMLCamera* camera = &renderer->runner->guiCamera; camera->allocated = true; camera->viewX = 0.0; @@ -2036,13 +2036,13 @@ static bool glSetRenderTarget(Renderer* renderer, int32_t surfaceId, bool implic GLRenderer* gl = (GLRenderer*) renderer; flushBatch(gl); - int32_t ViewCurrent = 0; + int32_t viewCurrent = 0; if (renderer->runner->viewsEnabled) { - ViewCurrent = renderer->runner->viewCurrent; + viewCurrent = renderer->runner->viewCurrent; } - RuntimeView* view = &renderer->runner->views[ViewCurrent]; - gl->base.CameraCurrent = view->cameraId; - GMLCamera* camera = Runner_getCameraById(renderer->runner, gl->base.CameraCurrent); + 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; @@ -2075,7 +2075,7 @@ static bool glSetRenderTarget(Renderer* renderer, int32_t surfaceId, bool implic 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; + gl->base.cameraCurrent = SURFACE_CAMERA; GMLCamera* camera = &renderer->runner->surfaceCamera; @@ -2653,10 +2653,10 @@ static bool glShadersSupported(void) { return true; } -static void glSetMatrix(Renderer* renderer, int32_t MatrixType, Matrix4f Matrix) { +static void glSetMatrix(Renderer* renderer, int32_t matrixType, Matrix4f matrix) { GLRenderer* gl = (GLRenderer*) renderer; flushBatch(gl); - renderer->gmlMatrices[MatrixType] = Matrix; + 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]; @@ -2759,6 +2759,6 @@ Renderer* GLRenderer_create(void) { gl->base.drawValign = 0; gl->base.circlePrecision = 24; gl->base.currentShader = -1; - gl->base.CameraCurrent = 0; + gl->base.cameraCurrent = 0; return (Renderer*) gl; } diff --git a/src/renderer.h b/src/renderer.h index 0b44b446f..8d38ee0cf 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -162,7 +162,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); + void (*setMatrix)(Renderer* renderer, int32_t matrixType, Matrix4f matrix); } RendererVtable; // ===[ Renderer Base Struct ]=== diff --git a/src/runner.c b/src/runner.c index 54ed86dbb..c357da523 100644 --- a/src/runner.c +++ b/src/runner.c @@ -1191,7 +1191,7 @@ void Runner_drawViews(Runner* runner, int32_t gameW, int32_t gameH, bool debugSh runner->viewCurrent = (int32_t) vi; - runner->renderer->CameraCurrent = runner->views[runner->viewCurrent].cameraId; + runner->renderer->cameraCurrent = runner->views[runner->viewCurrent].cameraId; runner->renderer->vtable->applyProjection(runner->renderer, &viewMatrix, &projectionMatrix); @@ -1215,7 +1215,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->views[runner->viewCurrent].cameraId; + runner->renderer->cameraCurrent = runner->views[runner->viewCurrent].cameraId; renderer->vtable->beginView(renderer, viewX, viewY, viewW, viewH, portX, portY, portW, portH, viewAngle); Runner_draw(runner); @@ -1231,7 +1231,7 @@ void Runner_drawViews(Runner* runner, int32_t gameW, int32_t gameH, bool debugSh if (!anyViewRendered) { runner->viewCurrent = 0; GMLCamera* camera = Runner_getCameraForView(runner, (int32_t) runner->viewCurrent); - runner->renderer->CameraCurrent = runner->views[runner->viewCurrent].cameraId; + runner->renderer->cameraCurrent = runner->views[runner->viewCurrent].cameraId; // 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; @@ -1270,7 +1270,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->views[runner->viewCurrent].cameraId; + runner->renderer->cameraCurrent = runner->views[runner->viewCurrent].cameraId; } // ===[ Instance Creation Helper ]=== diff --git a/src/vm_builtins.c b/src/vm_builtins.c index 947b73566..a29a49874 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -1572,32 +1572,32 @@ void VMBuiltins_setVariable(VMContext* ctx, Instance* inst, int16_t builtinVarId case BUILTIN_VAR_VIEW_XVIEW: { GMLCamera* camera = Runner_getCameraForView(runner, arrayIndex); if (camera != nullptr) { - camera->viewX = RValue_toReal(val); - Runner_updateCameraViewSimple(camera); + camera->viewX = RValue_toReal(val); + Runner_updateCameraViewSimple(camera); } return; } case BUILTIN_VAR_VIEW_YVIEW: { GMLCamera* camera = Runner_getCameraForView(runner, arrayIndex); if (camera != nullptr) { - camera->viewY = RValue_toInt32(val); - Runner_updateCameraViewSimple(camera); + camera->viewY = RValue_toInt32(val); + Runner_updateCameraViewSimple(camera); } return; } case BUILTIN_VAR_VIEW_WVIEW: { GMLCamera* camera = Runner_getCameraForView(runner, arrayIndex); if (camera != nullptr) { - camera->viewWidth = RValue_toInt32(val); - Runner_updateCameraViewSimple(camera); + camera->viewWidth = RValue_toInt32(val); + Runner_updateCameraViewSimple(camera); } return; } case BUILTIN_VAR_VIEW_HVIEW: { GMLCamera* camera = Runner_getCameraForView(runner, arrayIndex); if (camera != nullptr) { - camera->viewHeight = RValue_toInt32(val); - Runner_updateCameraViewSimple(camera); + camera->viewHeight = RValue_toInt32(val); + Runner_updateCameraViewSimple(camera); } return; } @@ -1625,8 +1625,8 @@ void VMBuiltins_setVariable(VMContext* ctx, Instance* inst, int16_t builtinVarId case BUILTIN_VAR_VIEW_ANGLE: { GMLCamera* camera = Runner_getCameraForView(runner, arrayIndex); if (camera != nullptr) { - camera->viewAngle = (float) RValue_toReal(val); - Runner_updateCameraViewSimple(camera); + camera->viewAngle = (float) RValue_toReal(val); + Runner_updateCameraViewSimple(camera); } return; } @@ -3525,7 +3525,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]); - Runner_updateCameraViewSimple(camera); + Runner_updateCameraViewSimple(camera); } return RValue_makeUndefined(); } @@ -3618,7 +3618,7 @@ static RValue builtin_camera_set_view_size(VMContext* ctx, RValue* args, int32_t if (camera != nullptr) { camera->viewWidth = RValue_toInt32(args[1]); camera->viewHeight = RValue_toInt32(args[2]); - Runner_updateCameraViewSimple(camera); + Runner_updateCameraViewSimple(camera); } return RValue_makeUndefined(); } @@ -3638,10 +3638,9 @@ 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]); - Runner_updateCameraViewSimple(camera); + if (camera != nullptr) { + camera->viewAngle = (float) RValue_toReal(args[1]); + Runner_updateCameraViewSimple(camera); } return RValue_makeUndefined(); } @@ -3706,8 +3705,7 @@ 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]); - - Runner_updateCameraViewSimple(camera); + Runner_updateCameraViewSimple(camera); return RValue_makeReal(id); } @@ -3743,7 +3741,7 @@ 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->renderer->CameraCurrent); + return RValue_makeReal(runner->renderer->cameraCurrent); } return RValue_makeReal(-1); } @@ -3762,7 +3760,7 @@ static RValue builtin_camera_apply(VMContext* ctx, RValue* args, int32_t argCoun GMLCamera* camera = Runner_getCameraById(runner, RValue_toInt32(args[0])); if (camera != nullptr) { runner->renderer->vtable->applyProjection(runner->renderer, &camera->viewMatrix, &camera->projectionMatrix); - runner->renderer->CameraCurrent = RValue_toInt32(args[0]); + runner->renderer->cameraCurrent = RValue_toInt32(args[0]); } return RValue_makeUndefined(); } From 255a5e7bddd0d8ea8e94bbabd1e0ef66fa911272 Mon Sep 17 00:00:00 2001 From: Classic0306 <190026317+Classic0306@users.noreply.github.com> Date: Thu, 2 Jul 2026 22:08:37 +0200 Subject: [PATCH 23/26] do the same changes to legacy renderer and fix little oversight --- src/gl/gl_renderer.c | 16 +-- src/gl_legacy/gl_legacy_renderer.c | 200 +++++++++++++++++++++-------- src/vm_builtins.c | 2 +- 3 files changed, 156 insertions(+), 62 deletions(-) diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index 25f9aa3df..946ed8c38 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -510,10 +510,10 @@ static void glGpuSetShader(Renderer* renderer, int32_t shaderIndex) { 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]); - } + memcpy(flippedClip, renderer->gmlMatrices, sizeof(flippedClip)); + + Matrix4f_flipClipY(&flippedClip[MATRIX_PROJECTION]); + Matrix4f_flipClipY(&flippedClip[MATRIX_WORLD_VIEW_PROJECTION]); if (gmMatricesUniform != nullptr) { glUniformMatrix4fv(gmMatricesUniform->location, 5, GL_FALSE, flippedClip[0].m); @@ -549,10 +549,10 @@ static void glShaderSettingsRefresh(Renderer* renderer) { 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]); - } + memcpy(flippedClip, renderer->gmlMatrices, sizeof(flippedClip)); + //I was making the Legacy OpenGL renderer work with the projections, then I realized I think I only need to flip the Projection(s) and not the other ones + Matrix4f_flipClipY(&flippedClip[MATRIX_PROJECTION]); + Matrix4f_flipClipY(&flippedClip[MATRIX_WORLD_VIEW_PROJECTION]); glUniformMatrix4fv(uWorldViewProjection->location, 1, GL_FALSE, flippedClip[MATRIX_WORLD_VIEW_PROJECTION].m); glUniform4f(uFogColor->location, fogR, fogG, fogB, gl->fogEnable ? 1.0f : 0.0f); diff --git a/src/gl_legacy/gl_legacy_renderer.c b/src/gl_legacy/gl_legacy_renderer.c index b5dd08479..9c7d08d32 100644 --- a/src/gl_legacy/gl_legacy_renderer.c +++ b/src/gl_legacy/gl_legacy_renderer.c @@ -58,23 +58,52 @@ static bool hasFBO() { // ===[ Helpers ]=== static void glApplyViewport(GLLegacyRenderer* gl, int32_t x, int32_t y, int32_t w, int32_t h) { - int32_t glY = gl->gameH - y - h; - glViewport(x, glY, w, h); + glViewport(x, y, w, h); glEnable(GL_SCISSOR_TEST); - glScissor(x, glY, w, h); + glScissor(x, y, w, h); gl->base.CPortX = x; - gl->base.CPortY = glY; + gl->base.CPortY = y; gl->base.CPortW = w; gl->base.CPortH = h; } +// 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) { + + Matrix4f world = renderer->gmlMatrices[MATRIX_WORLD]; + Matrix4f view = *viewMatrix; + Matrix4f projection = *projectionMatrix; + + Matrix4f worldView; + Matrix4f_multiply(&worldView, &view, &world); + + Matrix4f worldViewProjection; + Matrix4f_multiply(&worldViewProjection, &projection, &worldView); + + renderer->gmlMatrices[MATRIX_VIEW] = view; + renderer->gmlMatrices[MATRIX_PROJECTION] = projection; + renderer->gmlMatrices[MATRIX_WORLD_VIEW] = worldView; + renderer->gmlMatrices[MATRIX_WORLD_VIEW_PROJECTION] = worldViewProjection; + + Matrix4f_flipClipY(&projection); + + glMatrixMode(GL_PROJECTION); + glLoadMatrixf(projection.m); + glMatrixMode(GL_MODELVIEW); + glLoadMatrixf(worldView.m); +} + // ===[ Vtable Implementations ]=== static void glInit(Renderer* renderer, DataWin* dataWin) { GLLegacyRenderer* gl = (GLLegacyRenderer*) renderer; renderer->dataWin = dataWin; + Matrix4f world; + Matrix4f_identity(&world); + renderer->gmlMatrices[MATRIX_WORLD] = world; + if (!hasFBO()) { fprintf(stderr, "GL: The legacy-gl renderer requires FBO support!\n"); abort(); @@ -174,7 +203,7 @@ static void glBeginFrame(Renderer* renderer, int32_t gameW, int32_t gameH, int32 glBindTexture(GL_TEXTURE_2D, 0); } -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) { GLLegacyRenderer* gl = (GLLegacyRenderer*) renderer; glBindTexture(GL_TEXTURE_2D, 0); @@ -184,35 +213,23 @@ static void glBeginView(Renderer* renderer, int32_t viewX, int32_t viewY, int32_ // OpenGL viewport Y is bottom-up, game Y is top-down glApplyViewport(gl, portX, portY, portW, portH); - // World -> clip transform for this view. - Matrix4f projection; - Matrix4f_viewProjection(&projection, (float) viewX, (float) viewY, (float) viewW, (float) viewH, viewAngle); - Matrix4f_flipClipY(&projection); + 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); - glMatrixMode(GL_PROJECTION); - glLoadMatrixf(projection.m); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); glActiveTexture(GL_TEXTURE0); - renderer->previousViewMatrix = projection; } static void glEndView(MAYBE_UNUSED 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, MAYBE_UNUSED const Matrix4f* viewMatrix, MAYBE_UNUSED const Matrix4f* projectionMatrix) { - Matrix4f projection = *projectionMatrix; //fix it later - Matrix4f_flipClipY(&projection); - glMatrixMode(GL_PROJECTION); - glLoadMatrixf(projection.m); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - 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) { GLLegacyRenderer* gl = (GLLegacyRenderer*) renderer; @@ -230,13 +247,33 @@ static void glBeginGUI(Renderer* renderer, int32_t guiW, int32_t guiH, int32_t p glApplyViewport(gl, portX, portY, portW, portH); } - Matrix4f projection; - Matrix4f_guiProjection(&projection, (float) guiW, (float) guiH, (float) portW, (float) portH); + //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; + + Matrix4f projectionMatrix; + Matrix4f_Orthographic(&projectionMatrix, (float) guiW, (float) guiH, 32000.0, 0.0); + + 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); + camera->viewMatrix = viewMatrix; + camera->projectionMatrix = projectionMatrix; + glApplyProjection(renderer,&camera->viewMatrix,&camera->projectionMatrix); - glMatrixMode(GL_PROJECTION); - glLoadMatrixf(projection.m); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); glActiveTexture(GL_TEXTURE0); } @@ -244,12 +281,34 @@ static void glSetGuiProjection(MAYBE_UNUSED Renderer* renderer, int32_t guiW, in 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. + + renderer->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); // Flip the projection when we are rendering to a user surface so it comes back upright. - if (renderingToUserSurface) Matrix4f_flipClipY(&projection); - glMatrixMode(GL_PROJECTION); - glLoadMatrixf(projection.m); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); + 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); + camera->viewMatrix = viewMatrix; + camera->projectionMatrix = projectionMatrix; + glApplyProjection(renderer,&camera->viewMatrix,&camera->projectionMatrix); } static void glEndGUI(MAYBE_UNUSED Renderer* renderer) { @@ -284,11 +343,10 @@ static void glClearScreen(MAYBE_UNUSED Renderer* renderer, uint32_t color, float 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); + 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. @@ -1549,6 +1607,14 @@ static void glLegacySurfaceFree(Renderer* renderer, int32_t surfaceId) { static bool glLegacySetRenderTarget(Renderer* renderer, int32_t surfaceId, bool implicitApplicationSurface) { GLLegacyRenderer* gl = (GLLegacyRenderer*) renderer; + 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; @@ -1556,27 +1622,55 @@ static bool glLegacySetRenderTarget(Renderer* renderer, int32_t surfaceId, bool if (surfaceId == renderer->runner->applicationSurfaceId && implicitApplicationSurface) { glViewport(gl->base.CPortX, gl->base.CPortY, gl->base.CPortW, gl->base.CPortH); - glMatrixMode(GL_PROJECTION); - glLoadMatrixf(renderer->previousViewMatrix.m); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); glEnable(GL_SCISSOR_TEST); + glApplyProjection(renderer,&camera->viewMatrix,&camera->projectionMatrix); return true; } - int32_t w = gl->surfaceWidth[surfaceId]; - int32_t h = gl->surfaceHeight[surfaceId]; + 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 { + //camera will use full surface. + 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] * 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; + + 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; + glViewport(0, 0, gl->surfaceWidth[surfaceId], gl->surfaceHeight[surfaceId]); + glDisable(GL_SCISSOR_TEST); + glApplyProjection(renderer, &viewMatrix,&projectionMatrix); + return true; + } + - glViewport(0, 0, w, h); + glViewport(0, 0, gl->surfaceWidth[surfaceId], gl->surfaceHeight[surfaceId]); glDisable(GL_SCISSOR_TEST); - Matrix4f projection; - Matrix4f_identity(&projection); - Matrix4f_ortho(&projection, 0.0f, (float) w, 0.0f, (float) h, -1.0f, 1.0f); - glMatrixMode(GL_PROJECTION); - glLoadMatrixf(projection.m); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); return true; } diff --git a/src/vm_builtins.c b/src/vm_builtins.c index a29a49874..ffd1c0b51 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -2995,7 +2995,7 @@ static RValue builtin_matrix_set(MAYBE_UNUSED VMContext *ctx, RValue *args, int3 Matrix4f m; matrixFromGml(&m, args[1].array); if (Matrix < 0 || Matrix > 2) return RValue_makeUndefined(); - if (ctx->runner->renderer != nullptr) { + if (ctx->runner->renderer->vtable->setMatrix != nullptr) { ctx->runner->renderer->vtable->setMatrix(ctx->runner->renderer, Matrix, m); } From d72e3eaa35b2bc2d05189dee57d5226158bfab3d Mon Sep 17 00:00:00 2001 From: Classic0306 <190026317+Classic0306@users.noreply.github.com> Date: Fri, 3 Jul 2026 15:51:41 +0200 Subject: [PATCH 24/26] hopefully fix PS2 build --- src/matrix_math.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/matrix_math.h b/src/matrix_math.h index 3af37907d..be7a38e2a 100644 --- a/src/matrix_math.h +++ b/src/matrix_math.h @@ -54,24 +54,24 @@ static inline Matrix4f* Matrix4f_multiply(Matrix4f* dest, const Matrix4f* a, con static inline Matrix4f* Matrix4f_LookAt(Matrix4f* dest, float xFrom, float yFrom, float zFrom, float xTo, float yTo, float zTo, float xUp, float yUp, float zUp) { - double magUp = sqrt(xUp * xUp + yUp * yUp + zUp * zUp); + float 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); + float xLook = xTo - xFrom; + float yLook = yTo - yFrom; + float zLook = zTo - zFrom; + float 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); + float xRight = yUp * zLook - zUp * yLook; + float yRight = zUp * xLook - xUp * zLook; + float zRight = xUp * yLook - yUp * xLook; + float magRight = sqrt(xRight * xRight + yRight * yRight + zRight * zRight); xRight /= magRight; yRight /= magRight; zRight /= magRight; @@ -85,7 +85,7 @@ static inline Matrix4f* Matrix4f_LookAt(Matrix4f* dest, float xFrom, float yFrom yUp /= magUp; zUp /= magUp; - double x, y, z; + float x, y, z; x = xFrom * xRight + yFrom * yRight + zFrom * zRight; y = xFrom * xUp + yFrom * yUp + zFrom * zUp; z = xFrom * xLook + yFrom * yLook + zFrom * zLook; From 6c88d9f971767a3bc24bbe8c60dd881d7957329f Mon Sep 17 00:00:00 2001 From: Classic0306 <190026317+Classic0306@users.noreply.github.com> Date: Sun, 5 Jul 2026 23:42:33 +0200 Subject: [PATCH 25/26] rebase what time now? --- src/renderer.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/renderer.h b/src/renderer.h index 8d38ee0cf..77dac7828 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -186,8 +186,7 @@ struct Renderer { Matrix4f gmlMatrices[MATRICES_MAX]; int32_t currentShader; BlendFactors blendFactors; - int32_t V_SurfaceID; - int32_t CameraCurrent; + int32_t cameraCurrent; }; // ===[ Shared Helpers (platform-agnostic) ]=== From 7e7eeed0ce909bc377dcf4cede0769e60003c8cd Mon Sep 17 00:00:00 2001 From: Classic0306 <190026317+Classic0306@users.noreply.github.com> Date: Tue, 7 Jul 2026 21:39:22 +0200 Subject: [PATCH 26/26] maybe this would fix it? --- src/runner.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/runner.c b/src/runner.c index c357da523..1f985f162 100644 --- a/src/runner.c +++ b/src/runner.c @@ -1240,22 +1240,13 @@ void Runner_drawViews(Runner* runner, int32_t gameW, int32_t gameH, bool debugSh applyFreeCamera(runner, &viewX, &viewY, &viewW, &viewH); //whenever somebody feels like it, do make that free cam thingy work with this //make default projection - Matrix4f projectionMatrix; - Matrix4f_Orthographic(&projectionMatrix, (float) runner->currentRoom->width, -((float) runner->currentRoom->height), 32000.0, 0.0); - - Matrix4f viewMatrix; - 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 = runner->currentRoom->width; camera->viewHeight = runner->currentRoom->height; camera->viewAngle = 0.0; - camera->viewMatrix = viewMatrix; - camera->projectionMatrix = projectionMatrix; + Runner_updateCameraViewSimple(camera); } renderer->vtable->beginView(renderer, viewX, viewY, viewW, viewH, 0, 0, gameW, gameH, 0);