mirror of
https://github.com/FabricMC/fabric.git
synced 2025-03-22 21:15:23 -04:00
Fix WorldRenderEvents.AFTER_TRANSLUCENT (#3563)
* Fix WorldRenderEvents.AFTER_TRANSLUCENT * Add test for WorldRenderEvents.AFTER_TRANSLUCENT * Reset matrixStack
This commit is contained in:
parent
04ac8cf319
commit
bab36248d7
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
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue