From eed627a67773c97d8636aa1e1ac1241569e0729f Mon Sep 17 00:00:00 2001 From: froslanz Date: Sat, 24 Oct 2026 19:13:22 -0400 Subject: [PATCH] capture projection/view matrices for world-to-screen projection MatrixCapture keeps the matrices from the level render pass so 2d overlays (nametags) can project world positions onto the gui-scaled screen. --- .../fros/mixin/render/MixinLevelRenderer.java | 4 ++ .../cc/fros/util/render/MatrixCapture.java | 49 +++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 src/main/java/cc/fros/util/render/MatrixCapture.java diff --git a/src/main/java/cc/fros/mixin/render/MixinLevelRenderer.java b/src/main/java/cc/fros/mixin/render/MixinLevelRenderer.java index a504a35..c4e7fb9 100644 --- a/src/main/java/cc/fros/mixin/render/MixinLevelRenderer.java +++ b/src/main/java/cc/fros/mixin/render/MixinLevelRenderer.java @@ -7,6 +7,7 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Axis; import cc.fros.event.impl.render.Render3DEvent; import cc.fros.event.impl.render.RenderBlockOutlineEvent; +import cc.fros.util.render.MatrixCapture; import net.minecraft.client.Camera; import net.minecraft.client.DeltaTracker; import net.minecraft.client.renderer.LevelRenderer; @@ -37,6 +38,9 @@ public class MixinLevelRenderer { Camera camera, Matrix4f positionMatrix, Matrix4f matrix4f, Matrix4f projectionMatrix, GpuBufferSlice fogBuffer, Vector4f fogColor, boolean renderSky, CallbackInfo ci, @Local ProfilerFiller profiler) { + MatrixCapture.projection = new Matrix4f(projectionMatrix); + MatrixCapture.view = new Matrix4f(positionMatrix); + PoseStack stack = new PoseStack(); stack.pushPose(); stack.mulPose(Axis.XP.rotationDegrees(mc.gameRenderer.getMainCamera().xRot())); diff --git a/src/main/java/cc/fros/util/render/MatrixCapture.java b/src/main/java/cc/fros/util/render/MatrixCapture.java new file mode 100644 index 0000000..66dcbd2 --- /dev/null +++ b/src/main/java/cc/fros/util/render/MatrixCapture.java @@ -0,0 +1,49 @@ +package cc.fros.util.render; + +import cc.fros.util.traits.Util; +import net.minecraft.world.phys.Vec3; +import org.joml.Matrix4f; +import org.joml.Vector4f; + +/** + * Projection/view matrices captured during the level pass, used to project + * world positions onto the gui-scaled screen for 2d overlays like nametags. + */ +public final class MatrixCapture implements Util { + public static Matrix4f projection; + public static Matrix4f view; + + private MatrixCapture() { + throw new AssertionError(); + } + + public static float[] worldToScreen(double worldX, double worldY, double worldZ) { + if (projection == null || view == null) return null; + + Vec3 camPos = mc.gameRenderer.getMainCamera().position(); + Matrix4f mvp = projection.mul(view, new Matrix4f()); + + Vector4f point = new Vector4f( + (float) (worldX - camPos.x()), + (float) (worldY - camPos.y()), + (float) (worldZ - camPos.z()), + 1.0f + ); + mvp.transform(point); + + if (point.w <= 0.0f) return null; + + float ndcX = point.x / point.w; + float ndcY = point.y / point.w; + + if (ndcX < -1.1f || ndcX > 1.1f || ndcY < -1.1f || ndcY > 1.1f) return null; + + int guiW = mc.getWindow().getGuiScaledWidth(); + int guiH = mc.getWindow().getGuiScaledHeight(); + + return new float[]{ + (ndcX + 1.0f) / 2.0f * guiW, + (1.0f - ndcY) / 2.0f * guiH + }; + } +}