From 41cb15e07f9afff5a0fb0d9a34c6e2b1d089d807 Mon Sep 17 00:00:00 2001 From: PepperCode1 <44146161+PepperCode1@users.noreply.github.com> Date: Mon, 9 Dec 2024 10:44:21 -0800 Subject: [PATCH] Add translucent block outline to context --- .../rendering/v1/WorldRenderContext.java | 45 ++++++++----- .../rendering/v1/WorldRenderEvents.java | 14 ++-- .../rendering/WorldRenderContextImpl.java | 65 ++++++++++++------- .../client/rendering/WorldRendererMixin.java | 5 +- 4 files changed, 79 insertions(+), 50 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 2a8861695a..cde20742aa 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 @@ -44,12 +44,6 @@ public interface WorldRenderContext { */ WorldRenderer worldRenderer(); - /** - * The matrix stack is only not null in {@link WorldRenderEvents#AFTER_ENTITIES} or later events. - */ - @Nullable - MatrixStack matrixStack(); - RenderTickCounter tickCounter(); boolean blockOutlines(); @@ -58,10 +52,10 @@ public interface WorldRenderContext { GameRenderer gameRenderer(); - Matrix4f projectionMatrix(); - Matrix4f positionMatrix(); + Matrix4f projectionMatrix(); + /** * Convenient access to {WorldRenderer.world}. * @@ -92,30 +86,39 @@ public interface WorldRenderContext { * possible, caller should use a separate "immediate" instance. * *

This property is {@code null} before {@link WorldRenderEvents#BEFORE_ENTITIES} and after - * {@link WorldRenderEvents#BEFORE_DEBUG_RENDER} because the consumer buffers are not available before or + * {@link WorldRenderEvents#BLOCK_OUTLINE} (translucent) because the consumer buffers are not available before or * drawn after that in vanilla world rendering. Renders that cannot draw in one of the supported events * must be drawn directly to the frame buffer, preferably in {@link WorldRenderEvents#LAST} to avoid being * overdrawn or cleared. */ - @Nullable VertexConsumerProvider consumers(); + @Nullable + VertexConsumerProvider consumers(); /** * View frustum, after it is initialized. Will be {@code null} during * {@link WorldRenderEvents#START}. */ - @Nullable Frustum frustum(); + @Nullable + Frustum frustum(); /** - * Used in {@code BLOCK_OUTLINE} to convey the parameters normally sent to + * The matrix stack is only not null in {@link WorldRenderEvents#AFTER_ENTITIES} or later events. + */ + @Nullable + MatrixStack matrixStack(); + + /** + * Meant to be used in {@link WorldRenderEvents#BEFORE_BLOCK_OUTLINE} and {@link WorldRenderEvents#BLOCK_OUTLINE}. + * @return {@code true} if the current block outline is being rendered after translucent terrain; {@code false} if + * it is being rendered after solid terrain + */ + boolean translucentBlockOutline(); + + /** + * Used in {@link WorldRenderEvents#BLOCK_OUTLINE} to convey the parameters normally sent to * {@code WorldRenderer.drawBlockOutline}. */ interface BlockOutlineContext { - /** - * @deprecated Use {@link #consumers()} directly. - */ - @Deprecated - VertexConsumer vertexConsumer(); - Entity entity(); double cameraX(); @@ -127,5 +130,11 @@ interface BlockOutlineContext { BlockPos blockPos(); BlockState blockState(); + + /** + * @deprecated Use {@link #consumers()} directly. + */ + @Deprecated + VertexConsumer vertexConsumer(); } } diff --git a/fabric-rendering-v1/src/client/java/net/fabricmc/fabric/api/client/rendering/v1/WorldRenderEvents.java b/fabric-rendering-v1/src/client/java/net/fabricmc/fabric/api/client/rendering/v1/WorldRenderEvents.java index 119f81ac23..02c1460774 100644 --- a/fabric-rendering-v1/src/client/java/net/fabricmc/fabric/api/client/rendering/v1/WorldRenderEvents.java +++ b/fabric-rendering-v1/src/client/java/net/fabricmc/fabric/api/client/rendering/v1/WorldRenderEvents.java @@ -37,9 +37,11 @@ *

  • AFTER_SETUP *
  • BEFORE_ENTITIES *
  • AFTER_ENTITIES - *
  • BEFORE_BLOCK_OUTLINE - *
  • BLOCK_OUTLINE (If not cancelled in BEFORE_BLOCK_OUTLINE) + *
  • BEFORE_BLOCK_OUTLINE (non-translucent) + *
  • BLOCK_OUTLINE (if not cancelled in non-translucent BEFORE_BLOCK_OUTLINE and vanilla checks pass) *
  • BEFORE_DEBUG_RENDER + *
  • BEFORE_BLOCK_OUTLINE (translucent) + *
  • BLOCK_OUTLINE (if not cancelled in translucent BEFORE_BLOCK_OUTLINE and vanilla checks pass) *
  • AFTER_TRANSLUCENT *
  • LAST *
  • END @@ -139,11 +141,11 @@ private WorldRenderEvents() { } * renders. Mods that replace the default block outline for specific blocks * should instead subscribe to {@link #BLOCK_OUTLINE}. */ - public static final Event BEFORE_BLOCK_OUTLINE = EventFactory.createArrayBacked(BeforeBlockOutline.class, (context, translucent, hit) -> true, callbacks -> (context, translucent, hit) -> { + public static final Event BEFORE_BLOCK_OUTLINE = EventFactory.createArrayBacked(BeforeBlockOutline.class, (context, hit) -> true, callbacks -> (context, hit) -> { boolean shouldRender = true; for (final BeforeBlockOutline callback : callbacks) { - if (!callback.beforeBlockOutline(context, translucent, hit)) { + if (!callback.beforeBlockOutline(context, hit)) { shouldRender = false; } } @@ -279,15 +281,13 @@ public interface BeforeBlockOutline { * Event signature for {@link WorldRenderEvents#BEFORE_BLOCK_OUTLINE}. * * @param context Access to state and parameters available during world rendering. - * @param translucent If {@code true}, current block outline is being rendered after translucent terrain. - * Otherwise, it is being rendered after solid terrain. * @param hitResult The game object currently under the crosshair target. * Normally equivalent to {@link MinecraftClient#crosshairTarget}. Provided for convenience. * @return true if vanilla block outline rendering should happen. * Returning false prevents {@link WorldRenderEvents#BLOCK_OUTLINE} from invoking * and also skips the vanilla block outline render, but has no effect on other subscribers to this event. */ - boolean beforeBlockOutline(WorldRenderContext context, boolean translucent, @Nullable HitResult hitResult); + boolean beforeBlockOutline(WorldRenderContext context, @Nullable HitResult hitResult); } @FunctionalInterface 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 12b0abba27..c5fc6cbf39 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 @@ -16,6 +16,7 @@ package net.fabricmc.fabric.impl.client.rendering; +import org.jetbrains.annotations.Nullable; import org.joml.Matrix4f; import net.minecraft.block.BlockState; @@ -37,17 +38,21 @@ public final class WorldRenderContextImpl implements WorldRenderContext.BlockOutlineContext, WorldRenderContext { private WorldRenderer worldRenderer; private RenderTickCounter tickCounter; - private MatrixStack matrixStack; private boolean blockOutlines; private Camera camera; - private Frustum frustum; private GameRenderer gameRenderer; - private Matrix4f projectionMatrix; private Matrix4f positionMatrix; + private Matrix4f projectionMatrix; private VertexConsumerProvider consumers; private boolean advancedTranslucency; private ClientWorld world; + @Nullable + private Frustum frustum; + @Nullable + private MatrixStack matrixStack; + private boolean translucentBlockOutline; + private Entity entity; private double cameraX; private double cameraY; @@ -59,27 +64,29 @@ public final class WorldRenderContextImpl implements WorldRenderContext.BlockOut public void prepare( WorldRenderer worldRenderer, - RenderTickCounter delta, + RenderTickCounter tickCounter, boolean blockOutlines, Camera camera, GameRenderer gameRenderer, - Matrix4f projectionMatrix, Matrix4f positionMatrix, + Matrix4f projectionMatrix, VertexConsumerProvider consumers, boolean advancedTranslucency, ClientWorld world ) { this.worldRenderer = worldRenderer; - this.tickCounter = delta; - this.matrixStack = null; + this.tickCounter = tickCounter; this.blockOutlines = blockOutlines; this.camera = camera; this.gameRenderer = gameRenderer; - this.projectionMatrix = projectionMatrix; this.positionMatrix = positionMatrix; + this.projectionMatrix = projectionMatrix; this.consumers = consumers; this.advancedTranslucency = advancedTranslucency; this.world = world; + + frustum = null; + matrixStack = null; } public void setFrustum(Frustum frustum) { @@ -90,6 +97,10 @@ public void setMatrixStack(MatrixStack matrixStack) { this.matrixStack = matrixStack; } + public void setTranslucentBlockOutline(boolean translucentBlockOutline) { + this.translucentBlockOutline = translucentBlockOutline; + } + public void prepareBlockOutline( Entity entity, double cameraX, @@ -111,11 +122,6 @@ public WorldRenderer worldRenderer() { return worldRenderer; } - @Override - public MatrixStack matrixStack() { - return matrixStack; - } - @Override public RenderTickCounter tickCounter() { return this.tickCounter; @@ -132,8 +138,8 @@ public Camera camera() { } @Override - public Matrix4f projectionMatrix() { - return projectionMatrix; + public GameRenderer gameRenderer() { + return gameRenderer; } @Override @@ -141,14 +147,19 @@ public Matrix4f positionMatrix() { return positionMatrix; } + @Override + public Matrix4f projectionMatrix() { + return projectionMatrix; + } + @Override public ClientWorld world() { return world; } @Override - public Frustum frustum() { - return frustum; + public boolean advancedTranslucency() { + return advancedTranslucency; } @Override @@ -157,18 +168,20 @@ public VertexConsumerProvider consumers() { } @Override - public GameRenderer gameRenderer() { - return gameRenderer; + @Nullable + public Frustum frustum() { + return frustum; } @Override - public boolean advancedTranslucency() { - return advancedTranslucency; + @Nullable + public MatrixStack matrixStack() { + return matrixStack; } @Override - public VertexConsumer vertexConsumer() { - return consumers.getBuffer(RenderLayer.getLines()); + public boolean translucentBlockOutline() { + return translucentBlockOutline; } @Override @@ -200,4 +213,10 @@ public BlockPos blockPos() { public BlockState blockState() { return blockState; } + + @Deprecated + @Override + public VertexConsumer vertexConsumer() { + return consumers.getBuffer(RenderLayer.getLines()); + } } 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 fb3707db7e..73ca3122d2 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 @@ -69,7 +69,7 @@ public abstract class WorldRendererMixin { @Inject(method = "render", at = @At("HEAD")) private void beforeRender(ObjectAllocator objectAllocator, RenderTickCounter tickCounter, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, Matrix4f positionMatrix, Matrix4f projectionMatrix, CallbackInfo ci) { - context.prepare((WorldRenderer) (Object) this, tickCounter, renderBlockOutline, camera, gameRenderer, projectionMatrix, positionMatrix, bufferBuilders.getEntityVertexConsumers(), MinecraftClient.isFabulousGraphicsOrBetter(), world); + context.prepare((WorldRenderer) (Object) this, tickCounter, renderBlockOutline, camera, gameRenderer, positionMatrix, projectionMatrix, bufferBuilders.getEntityVertexConsumers(), MinecraftClient.isFabulousGraphicsOrBetter(), world); WorldRenderEvents.START.invoker().onStart(context); } @@ -117,7 +117,8 @@ private void afterEntities(CallbackInfo ci) { @Inject(method = "renderTargetBlockOutline", at = @At("HEAD")) private void beforeRenderOutline(Camera camera, VertexConsumerProvider.Immediate vertexConsumers, MatrixStack matrices, boolean translucent, CallbackInfo ci) { - context.renderBlockOutline = WorldRenderEvents.BEFORE_BLOCK_OUTLINE.invoker().beforeBlockOutline(context, translucent, client.crosshairTarget); + context.setTranslucentBlockOutline(translucent); + context.renderBlockOutline = WorldRenderEvents.BEFORE_BLOCK_OUTLINE.invoker().beforeBlockOutline(context, client.crosshairTarget); } @SuppressWarnings("ConstantConditions")