Fix a WorldRenderEvents.BLOCK_OUTLINE bug (#1319)

* Fix bug related to immediate mode VCP

* Add testmod

(cherry picked from commit 6d5e24549f)
This commit is contained in:
Technici4n 2021-04-14 18:40:14 +01:00 committed by modmuss50
parent aaa30be003
commit 78c482ee45
5 changed files with 89 additions and 6 deletions

View file

@ -120,7 +120,11 @@ public interface WorldRenderContext {
* {@code WorldRenderer.drawBlockOutline}. * {@code WorldRenderer.drawBlockOutline}.
*/ */
@Environment(EnvType.CLIENT) @Environment(EnvType.CLIENT)
public interface BlockOutlineContext { interface BlockOutlineContext {
/**
* @deprecated Use {@link #consumers()} directly.
*/
@Deprecated
VertexConsumer vertexConsumer(); VertexConsumer vertexConsumer();
Entity entity(); Entity entity();

View file

@ -21,6 +21,7 @@ import net.minecraft.client.render.Camera;
import net.minecraft.client.render.Frustum; import net.minecraft.client.render.Frustum;
import net.minecraft.client.render.GameRenderer; import net.minecraft.client.render.GameRenderer;
import net.minecraft.client.render.LightmapTextureManager; import net.minecraft.client.render.LightmapTextureManager;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.WorldRenderer; import net.minecraft.client.render.WorldRenderer;
@ -52,7 +53,6 @@ public final class WorldRenderContextImpl implements WorldRenderContext.BlockOut
private boolean advancedTranslucency; private boolean advancedTranslucency;
private ClientWorld world; private ClientWorld world;
private VertexConsumer vertexConsumer;
private Entity entity; private Entity entity;
private double cameraX; private double cameraX;
private double cameraY; private double cameraY;
@ -97,7 +97,6 @@ public final class WorldRenderContextImpl implements WorldRenderContext.BlockOut
} }
public void prepareBlockOutline( public void prepareBlockOutline(
VertexConsumer vertexConsumer,
Entity entity, Entity entity,
double cameraX, double cameraX,
double cameraY, double cameraY,
@ -105,7 +104,6 @@ public final class WorldRenderContextImpl implements WorldRenderContext.BlockOut
BlockPos blockPos, BlockPos blockPos,
BlockState blockState BlockState blockState
) { ) {
this.vertexConsumer = vertexConsumer;
this.entity = entity; this.entity = entity;
this.cameraX = cameraX; this.cameraX = cameraX;
this.cameraY = cameraY; this.cameraY = cameraY;
@ -186,7 +184,7 @@ public final class WorldRenderContextImpl implements WorldRenderContext.BlockOut
@Override @Override
public VertexConsumer vertexConsumer() { public VertexConsumer vertexConsumer() {
return vertexConsumer; return consumers.getBuffer(RenderLayer.getLines());
} }
@Override @Override

View file

@ -32,6 +32,7 @@ import net.minecraft.client.render.Camera;
import net.minecraft.client.render.Frustum; import net.minecraft.client.render.Frustum;
import net.minecraft.client.render.GameRenderer; import net.minecraft.client.render.GameRenderer;
import net.minecraft.client.render.LightmapTextureManager; import net.minecraft.client.render.LightmapTextureManager;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.WorldRenderer; import net.minecraft.client.render.WorldRenderer;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.MatrixStack;
@ -97,6 +98,7 @@ public abstract class MixinWorldRenderer {
context.renderBlockOutline = WorldRenderEvents.BEFORE_BLOCK_OUTLINE.invoker().beforeBlockOutline(context, client.crosshairTarget); context.renderBlockOutline = WorldRenderEvents.BEFORE_BLOCK_OUTLINE.invoker().beforeBlockOutline(context, client.crosshairTarget);
} }
@SuppressWarnings("ConstantConditions")
@Inject(method = "drawBlockOutline", at = @At("HEAD"), cancellable = true) @Inject(method = "drawBlockOutline", at = @At("HEAD"), cancellable = true)
private void onDrawBlockOutline(MatrixStack matrixStack, VertexConsumer vertexConsumer, Entity entity, double cameraX, double cameraY, double cameraZ, BlockPos blockPos, BlockState blockState, CallbackInfo ci) { private void onDrawBlockOutline(MatrixStack matrixStack, VertexConsumer vertexConsumer, Entity entity, double cameraX, double cameraY, double cameraZ, BlockPos blockPos, BlockState blockState, CallbackInfo ci) {
if (!context.renderBlockOutline) { if (!context.renderBlockOutline) {
@ -104,11 +106,15 @@ public abstract class MixinWorldRenderer {
// fire the BLOCK_OUTLINE event per contract of the API. // fire the BLOCK_OUTLINE event per contract of the API.
ci.cancel(); ci.cancel();
} else { } else {
context.prepareBlockOutline(vertexConsumer, entity, cameraX, cameraY, cameraZ, blockPos, blockState); context.prepareBlockOutline(entity, cameraX, cameraY, cameraZ, blockPos, blockState);
if (!WorldRenderEvents.BLOCK_OUTLINE.invoker().onBlockOutline(context, context)) { if (!WorldRenderEvents.BLOCK_OUTLINE.invoker().onBlockOutline(context, context)) {
ci.cancel(); ci.cancel();
} }
// The immediate mode VertexConsumers use a shared buffer, so we have to make sure that the immediate mode VCP
// can accept block outline lines rendered to the existing vertexConsumer by the vanilla block overlay.
context.consumers().getBuffer(RenderLayer.getLines());
} }
} }

View file

@ -0,0 +1,56 @@
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.fabricmc.fabric.test.rendering.client;
import net.minecraft.block.Blocks;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.OverlayTexture;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext;
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents;
public class WorldRenderEventsTests implements ClientModInitializer {
private static boolean onBlockOutline(WorldRenderContext wrc, WorldRenderContext.BlockOutlineContext blockOutlineContext) {
if (blockOutlineContext.blockState().isOf(Blocks.DIAMOND_BLOCK)) {
wrc.matrixStack().push();
Vec3d cameraPos = MinecraftClient.getInstance().gameRenderer.getCamera().getPos();
BlockPos pos = blockOutlineContext.blockPos();
double x = pos.getX() - cameraPos.x;
double y = pos.getY() - cameraPos.y;
double z = pos.getZ() - cameraPos.z;
wrc.matrixStack().translate(x+0.25, y+0.25+1, z+0.25);
wrc.matrixStack().scale(0.5f, 0.5f, 0.5f);
MinecraftClient.getInstance().getBlockRenderManager().renderBlockAsEntity(
Blocks.DIAMOND_BLOCK.getDefaultState(),
wrc.matrixStack(), wrc.consumers(), 15728880, OverlayTexture.DEFAULT_UV);
wrc.matrixStack().pop();
}
return true;
}
// Renders a diamond block above diamond blocks when they are looked at.
@Override
public void onInitializeClient() {
WorldRenderEvents.BLOCK_OUTLINE.register(WorldRenderEventsTests::onBlockOutline);
}
}

View file

@ -0,0 +1,19 @@
{
"schemaVersion": 1,
"id": "fabric-rendering-v1-testmod",
"name": "Fabric Rendering (v1) Test Mod",
"version": "1.0.0",
"environment": "*",
"license": "Apache-2.0",
"depends": {
"fabric-rendering-v1": "*"
},
"entrypoints": {
"main": [
"net.fabricmc.fabric.test.rendering.CustomArmorTests"
],
"client": [
"net.fabricmc.fabric.test.rendering.client.WorldRenderEventsTests"
]
}
}