From bab36248d7d5548e29ce95226ab5e8f15132c522 Mon Sep 17 00:00:00 2001 From: Kevin <92656833+kevinthegreat1@users.noreply.github.com> Date: Mon, 5 Feb 2024 06:30:21 -0500 Subject: [PATCH] Fix WorldRenderEvents.AFTER_TRANSLUCENT (#3563) * Fix WorldRenderEvents.AFTER_TRANSLUCENT * Add test for WorldRenderEvents.AFTER_TRANSLUCENT * Reset matrixStack --- .../rendering/v1/WorldRenderContext.java | 6 +++ .../rendering/WorldRenderContextImpl.java | 12 ++++++ .../client/rendering/WorldRendererMixin.java | 28 +++++--------- .../client/WorldRenderEventsTests.java | 37 ++++++++++++++++++- 4 files changed, 63 insertions(+), 20 deletions(-) diff --git a/fabric-rendering-v1/src/client/java/net/fabricmc/fabric/api/client/rendering/v1/WorldRenderContext.java b/fabric-rendering-v1/src/client/java/net/fabricmc/fabric/api/client/rendering/v1/WorldRenderContext.java index 7dca30f3f..e36cd0603 100644 --- a/fabric-rendering-v1/src/client/java/net/fabricmc/fabric/api/client/rendering/v1/WorldRenderContext.java +++ b/fabric-rendering-v1/src/client/java/net/fabricmc/fabric/api/client/rendering/v1/WorldRenderContext.java @@ -45,6 +45,12 @@ public interface WorldRenderContext { */ WorldRenderer worldRenderer(); + /** + * The matrix stack is only not null in {@link WorldRenderEvents#AFTER_ENTITIES} or later events. + */ + @Nullable + MatrixStack matrixStack(); + float tickDelta(); long limitTime(); diff --git a/fabric-rendering-v1/src/client/java/net/fabricmc/fabric/impl/client/rendering/WorldRenderContextImpl.java b/fabric-rendering-v1/src/client/java/net/fabricmc/fabric/impl/client/rendering/WorldRenderContextImpl.java index dd33e3190..224389fe8 100644 --- a/fabric-rendering-v1/src/client/java/net/fabricmc/fabric/impl/client/rendering/WorldRenderContextImpl.java +++ b/fabric-rendering-v1/src/client/java/net/fabricmc/fabric/impl/client/rendering/WorldRenderContextImpl.java @@ -27,6 +27,7 @@ import net.minecraft.client.render.RenderLayer; import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.WorldRenderer; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.world.ClientWorld; import net.minecraft.entity.Entity; import net.minecraft.util.math.BlockPos; @@ -36,6 +37,7 @@ import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext; public final class WorldRenderContextImpl implements WorldRenderContext.BlockOutlineContext, WorldRenderContext { private WorldRenderer worldRenderer; + private MatrixStack matrixStack; private float tickDelta; private long limitTime; private boolean blockOutlines; @@ -75,6 +77,7 @@ public final class WorldRenderContextImpl implements WorldRenderContext.BlockOut ClientWorld world ) { this.worldRenderer = worldRenderer; + this.matrixStack = null; this.tickDelta = tickDelta; this.limitTime = limitTime; this.blockOutlines = blockOutlines; @@ -93,6 +96,10 @@ public final class WorldRenderContextImpl implements WorldRenderContext.BlockOut this.frustum = frustum; } + public void setMatrixStack(MatrixStack matrixStack) { + this.matrixStack = matrixStack; + } + public void prepareBlockOutline( Entity entity, double cameraX, @@ -114,6 +121,11 @@ public final class WorldRenderContextImpl implements WorldRenderContext.BlockOut return worldRenderer; } + @Override + public MatrixStack matrixStack() { + return matrixStack; + } + @Override public float tickDelta() { return tickDelta; diff --git a/fabric-rendering-v1/src/client/java/net/fabricmc/fabric/mixin/client/rendering/WorldRendererMixin.java b/fabric-rendering-v1/src/client/java/net/fabricmc/fabric/mixin/client/rendering/WorldRendererMixin.java index 65333c2ff..e6b597288 100644 --- a/fabric-rendering-v1/src/client/java/net/fabricmc/fabric/mixin/client/rendering/WorldRendererMixin.java +++ b/fabric-rendering-v1/src/client/java/net/fabricmc/fabric/mixin/client/rendering/WorldRendererMixin.java @@ -16,6 +16,7 @@ package net.fabricmc.fabric.mixin.client.rendering; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import org.joml.Matrix4f; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -58,13 +59,11 @@ public abstract class WorldRendererMixin { @Shadow private MinecraftClient client; @Unique private final WorldRenderContextImpl context = new WorldRenderContextImpl(); - @Unique private boolean didRenderParticles; @Inject(method = "render", at = @At("HEAD")) private void beforeRender(float tickDelta, long limitTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightmapTextureManager lightmapTextureManager, Matrix4f positionMatrix, Matrix4f projectionMatrix, CallbackInfo ci) { context.prepare((WorldRenderer) (Object) this, tickDelta, limitTime, renderBlockOutline, camera, gameRenderer, lightmapTextureManager, projectionMatrix, positionMatrix, bufferBuilders.getEntityVertexConsumers(), world.getProfiler(), transparencyPostProcessor != null, world); WorldRenderEvents.START.invoker().onStart(context); - didRenderParticles = false; } @Inject(method = "setupTerrain", at = @At("RETURN")) @@ -86,6 +85,12 @@ public abstract class WorldRendererMixin { WorldRenderEvents.BEFORE_ENTITIES.invoker().beforeEntities(context); } + @ModifyExpressionValue(method = "render", at = @At(value = "NEW", target = "net/minecraft/client/util/math/MatrixStack")) + private MatrixStack setMatrixStack(MatrixStack matrixStack) { + context.setMatrixStack(matrixStack); + return matrixStack; + } + @Inject(method = "render", at = @At(value = "CONSTANT", args = "stringValue=blockentities", ordinal = 0)) private void afterEntities(CallbackInfo ci) { WorldRenderEvents.AFTER_ENTITIES.invoker().afterEntities(context); @@ -136,24 +141,9 @@ public abstract class WorldRendererMixin { WorldRenderEvents.BEFORE_DEBUG_RENDER.invoker().beforeDebugRender(context); } - @Inject( - method = "render", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/client/particle/ParticleManager;renderParticles(Lnet/minecraft/client/render/LightmapTextureManager;Lnet/minecraft/client/render/Camera;F)V" - ) - ) - private void onRenderParticles(CallbackInfo ci) { - // set a flag so we know the next pushMatrix call is after particles - didRenderParticles = true; - } - - @Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/util/math/MatrixStack;push()V")) + @Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/option/GameOptions;getCloudRenderModeValue()Lnet/minecraft/client/option/CloudRenderMode;")) private void beforeClouds(CallbackInfo ci) { - if (didRenderParticles) { - didRenderParticles = false; - WorldRenderEvents.AFTER_TRANSLUCENT.invoker().afterTranslucent(context); - } + WorldRenderEvents.AFTER_TRANSLUCENT.invoker().afterTranslucent(context); } @Inject( diff --git a/fabric-rendering-v1/src/testmodClient/java/net/fabricmc/fabric/test/rendering/client/WorldRenderEventsTests.java b/fabric-rendering-v1/src/testmodClient/java/net/fabricmc/fabric/test/rendering/client/WorldRenderEventsTests.java index 48d752f21..5423abaf8 100644 --- a/fabric-rendering-v1/src/testmodClient/java/net/fabricmc/fabric/test/rendering/client/WorldRenderEventsTests.java +++ b/fabric-rendering-v1/src/testmodClient/java/net/fabricmc/fabric/test/rendering/client/WorldRenderEventsTests.java @@ -16,9 +16,17 @@ package net.fabricmc.fabric.test.rendering.client; +import com.mojang.blaze3d.systems.RenderSystem; + import net.minecraft.block.Blocks; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.BufferBuilder; +import net.minecraft.client.render.GameRenderer; import net.minecraft.client.render.OverlayTexture; +import net.minecraft.client.render.Tessellator; +import net.minecraft.client.render.VertexFormat; +import net.minecraft.client.render.VertexFormats; +import net.minecraft.client.render.WorldRenderer; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; @@ -50,9 +58,36 @@ public class WorldRenderEventsTests implements ClientModInitializer { return true; } - // Renders a diamond block above diamond blocks when they are looked at. + /** + * Renders a translucent box at (0, 100, 0). + */ + private static void renderAfterTranslucent(WorldRenderContext context) { + MatrixStack matrices = context.matrixStack(); + Vec3d camera = context.camera().getPos(); + Tessellator tessellator = RenderSystem.renderThreadTesselator(); + BufferBuilder buffer = tessellator.getBuffer(); + + matrices.push(); + matrices.translate(-camera.x, -camera.y, -camera.z); + + RenderSystem.setShader(GameRenderer::getPositionColorProgram); + RenderSystem.setShaderColor(1f, 1f, 1f, 1f); + RenderSystem.enableBlend(); + RenderSystem.defaultBlendFunc(); + + buffer.begin(VertexFormat.DrawMode.TRIANGLE_STRIP, VertexFormats.POSITION_COLOR); + WorldRenderer.renderFilledBox(matrices, buffer, 0, 100, 0, 1, 101, 1, 0, 1, 0, 0.5f); + tessellator.draw(); + + matrices.pop(); + RenderSystem.disableBlend(); + } + @Override public void onInitializeClient() { + // Renders a diamond block above diamond blocks when they are looked at. WorldRenderEvents.BLOCK_OUTLINE.register(WorldRenderEventsTests::onBlockOutline); + // Renders a translucent box at (0, 100, 0) + WorldRenderEvents.AFTER_TRANSLUCENT.register(WorldRenderEventsTests::renderAfterTranslucent); } }