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")