Fix WorldRenderEvents.AFTER_TRANSLUCENT ()

* Fix WorldRenderEvents.AFTER_TRANSLUCENT

* Add test for WorldRenderEvents.AFTER_TRANSLUCENT

* Reset matrixStack
This commit is contained in:
Kevin 2024-02-05 06:30:21 -05:00 committed by GitHub
parent 04ac8cf319
commit bab36248d7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 63 additions and 20 deletions
fabric-rendering-v1/src
client/java/net/fabricmc/fabric
api/client/rendering/v1
impl/client/rendering
mixin/client/rendering
testmodClient/java/net/fabricmc/fabric/test/rendering/client

View file

@ -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();

View file

@ -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;

View file

@ -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(

View file

@ -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);
}
}