mirror of
https://github.com/FabricMC/fabric.git
synced 2024-11-28 10:36:43 -05:00
Reuse TerrainFallbackConsumer to render vanilla models when (#870)
called from BlockModelRenderer. Fixes #869.
This commit is contained in:
parent
57b0bb7ac0
commit
a2a03a90f8
2 changed files with 39 additions and 31 deletions
|
@ -19,12 +19,12 @@ package net.fabricmc.fabric.impl.client.indigo.renderer.render;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.client.render.RenderLayer;
|
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.render.block.BlockModelRenderer;
|
|
||||||
import net.minecraft.client.render.model.BakedModel;
|
import net.minecraft.client.render.model.BakedModel;
|
||||||
import net.minecraft.client.util.math.Matrix4f;
|
import net.minecraft.client.util.math.Matrix4f;
|
||||||
import net.minecraft.client.util.math.Matrix3f;
|
import net.minecraft.client.util.math.Matrix3f;
|
||||||
|
@ -46,17 +46,37 @@ public class BlockRenderContext extends AbstractRenderContext implements RenderC
|
||||||
private final BlockRenderInfo blockInfo = new BlockRenderInfo();
|
private final BlockRenderInfo blockInfo = new BlockRenderInfo();
|
||||||
private final AoCalculator aoCalc = new AoCalculator(blockInfo, this::brightness, this::aoLevel);
|
private final AoCalculator aoCalc = new AoCalculator(blockInfo, this::brightness, this::aoLevel);
|
||||||
private final MeshConsumer meshConsumer = new MeshConsumer(blockInfo, this::outputBuffer, aoCalc, this::transform);
|
private final MeshConsumer meshConsumer = new MeshConsumer(blockInfo, this::outputBuffer, aoCalc, this::transform);
|
||||||
private final Random random = new Random();
|
|
||||||
private BlockModelRenderer vanillaRenderer;
|
|
||||||
private VertexConsumer bufferBuilder;
|
private VertexConsumer bufferBuilder;
|
||||||
private long seed;
|
|
||||||
private boolean isCallingVanilla = false;
|
|
||||||
private boolean didOutput = false;
|
private boolean didOutput = false;
|
||||||
private MatrixStack matrixStack;
|
// These are kept as fields to avoid avoid the heap allocation for a supplier.
|
||||||
|
// BlockModelRenderer allows the caller to supply both the random object and seed.
|
||||||
|
private Random random;
|
||||||
|
private long seed;
|
||||||
|
private final Supplier<Random> randomSupplier = () -> {
|
||||||
|
random.setSeed(seed);
|
||||||
|
return random;
|
||||||
|
};
|
||||||
|
|
||||||
public boolean isCallingVanilla() {
|
/**
|
||||||
return isCallingVanilla;
|
* Reuse the fallback consumer from the render context used during chunk rebuild to make it properly
|
||||||
}
|
* apply the current transforms to vanilla models.
|
||||||
|
*/
|
||||||
|
private final TerrainFallbackConsumer fallbackConsumer = new TerrainFallbackConsumer(blockInfo, this::outputBuffer, aoCalc, this::transform) {
|
||||||
|
@Override
|
||||||
|
protected int overlay() {
|
||||||
|
return overlay;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Matrix4f matrix() {
|
||||||
|
return matrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Matrix3f normalMatrix() {
|
||||||
|
return normalMatrix;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private int brightness(BlockPos pos) {
|
private int brightness(BlockPos pos) {
|
||||||
if (blockInfo.blockView == null) {
|
if (blockInfo.blockView == null) {
|
||||||
|
@ -76,35 +96,29 @@ public class BlockRenderContext extends AbstractRenderContext implements RenderC
|
||||||
return bufferBuilder;
|
return bufferBuilder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean tesselate(BlockModelRenderer vanillaRenderer, BlockRenderView blockView, BakedModel model, BlockState state, BlockPos pos, MatrixStack matrixStack, VertexConsumer buffer, boolean checkSides, long seed, int overlay) {
|
public boolean render(BlockRenderView blockView, BakedModel model, BlockState state, BlockPos pos, MatrixStack matrixStack, VertexConsumer buffer, Random random, long seed, int overlay) {
|
||||||
this.vanillaRenderer = vanillaRenderer;
|
|
||||||
this.bufferBuilder = buffer;
|
this.bufferBuilder = buffer;
|
||||||
this.matrixStack = matrixStack;
|
|
||||||
this.matrix = matrixStack.peek().getModel();
|
this.matrix = matrixStack.peek().getModel();
|
||||||
this.normalMatrix = matrixStack.peek().getNormal();
|
this.normalMatrix = matrixStack.peek().getNormal();
|
||||||
|
this.random = random;
|
||||||
this.seed = seed;
|
this.seed = seed;
|
||||||
|
|
||||||
this.overlay = overlay;
|
this.overlay = overlay;
|
||||||
this.didOutput = false;
|
this.didOutput = false;
|
||||||
aoCalc.clear();
|
aoCalc.clear();
|
||||||
blockInfo.setBlockView(blockView);
|
blockInfo.setBlockView(blockView);
|
||||||
blockInfo.prepareForBlock(state, pos, model.useAmbientOcclusion());
|
blockInfo.prepareForBlock(state, pos, model.useAmbientOcclusion());
|
||||||
|
|
||||||
((FabricBakedModel) model).emitBlockQuads(blockView, state, pos, blockInfo.randomSupplier, this);
|
((FabricBakedModel) model).emitBlockQuads(blockView, state, pos, randomSupplier, this);
|
||||||
|
|
||||||
this.vanillaRenderer = null;
|
|
||||||
blockInfo.release();
|
blockInfo.release();
|
||||||
this.bufferBuilder = null;
|
this.bufferBuilder = null;
|
||||||
|
this.random = null;
|
||||||
|
this.seed = seed;
|
||||||
|
|
||||||
return didOutput;
|
return didOutput;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void acceptVanillaModel(BakedModel model) {
|
|
||||||
isCallingVanilla = true;
|
|
||||||
didOutput = didOutput && vanillaRenderer.render(blockInfo.blockView, model, blockInfo.blockState, blockInfo.blockPos, matrixStack, bufferBuilder, false, random, seed, overlay);
|
|
||||||
isCallingVanilla = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private class MeshConsumer extends AbstractMeshConsumer {
|
private class MeshConsumer extends AbstractMeshConsumer {
|
||||||
MeshConsumer(BlockRenderInfo blockInfo, Function<RenderLayer, VertexConsumer> bufferFunc, AoCalculator aoCalc, QuadTransform transform) {
|
MeshConsumer(BlockRenderInfo blockInfo, Function<RenderLayer, VertexConsumer> bufferFunc, AoCalculator aoCalc, QuadTransform transform) {
|
||||||
super(blockInfo, bufferFunc, aoCalc, transform);
|
super(blockInfo, bufferFunc, aoCalc, transform);
|
||||||
|
@ -133,7 +147,7 @@ public class BlockRenderContext extends AbstractRenderContext implements RenderC
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Consumer<BakedModel> fallbackConsumer() {
|
public Consumer<BakedModel> fallbackConsumer() {
|
||||||
return this::acceptVanillaModel;
|
return fallbackConsumer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -27,7 +27,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.client.color.block.BlockColors;
|
|
||||||
import net.minecraft.client.render.VertexConsumer;
|
import net.minecraft.client.render.VertexConsumer;
|
||||||
import net.minecraft.client.render.block.BlockModelRenderer;
|
import net.minecraft.client.render.block.BlockModelRenderer;
|
||||||
import net.minecraft.client.render.model.BakedModel;
|
import net.minecraft.client.render.model.BakedModel;
|
||||||
|
@ -43,22 +42,17 @@ import net.fabricmc.fabric.impl.client.indigo.renderer.render.BlockRenderContext
|
||||||
|
|
||||||
@Mixin(BlockModelRenderer.class)
|
@Mixin(BlockModelRenderer.class)
|
||||||
public abstract class MixinBlockModelRenderer implements AccessBlockModelRenderer {
|
public abstract class MixinBlockModelRenderer implements AccessBlockModelRenderer {
|
||||||
@Shadow
|
|
||||||
protected BlockColors colorMap;
|
|
||||||
|
|
||||||
@Shadow
|
@Shadow
|
||||||
protected abstract void getQuadDimensions(BlockRenderView blockView, BlockState blockState, BlockPos blockPos, int[] vertexData, Direction face, float[] aoData, BitSet controlBits);
|
protected abstract void getQuadDimensions(BlockRenderView blockView, BlockState blockState, BlockPos blockPos, int[] vertexData, Direction face, float[] aoData, BitSet controlBits);
|
||||||
|
|
||||||
private final ThreadLocal<BlockRenderContext> CONTEXTS = ThreadLocal.withInitial(BlockRenderContext::new);
|
private final ThreadLocal<BlockRenderContext> CONTEXTS = ThreadLocal.withInitial(BlockRenderContext::new);
|
||||||
|
|
||||||
@Inject(at = @At("HEAD"), method = "render(Lnet/minecraft/world/BlockRenderView;Lnet/minecraft/client/render/model/BakedModel;Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumer;ZLjava/util/Random;JI)Z", cancellable = true)
|
@Inject(at = @At("HEAD"), method = "render(Lnet/minecraft/world/BlockRenderView;Lnet/minecraft/client/render/model/BakedModel;Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumer;ZLjava/util/Random;JI)Z", cancellable = true)
|
||||||
private void hookTesselate(BlockRenderView blockView, BakedModel model, BlockState state, BlockPos pos, MatrixStack matrix, VertexConsumer buffer, boolean checkSides, Random rand, long seed, int overlay, CallbackInfoReturnable<Boolean> ci) {
|
private void hookRender(BlockRenderView blockView, BakedModel model, BlockState state, BlockPos pos, MatrixStack matrix, VertexConsumer buffer, boolean checkSides, Random rand, long seed, int overlay, CallbackInfoReturnable<Boolean> ci) {
|
||||||
if (!((FabricBakedModel) model).isVanillaAdapter()) {
|
if (!((FabricBakedModel) model).isVanillaAdapter()) {
|
||||||
BlockRenderContext context = CONTEXTS.get();
|
BlockRenderContext context = CONTEXTS.get();
|
||||||
|
// Note that we do not support face-culling here (so checkSides is ignored)
|
||||||
if (!context.isCallingVanilla()) {
|
ci.setReturnValue(context.render(blockView, model, state, pos, matrix, buffer, rand, seed, overlay));
|
||||||
ci.setReturnValue(CONTEXTS.get().tesselate((BlockModelRenderer) (Object) this, blockView, model, state, pos, matrix, buffer, checkSides, seed, overlay));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue