Reuse TerrainFallbackConsumer to render vanilla models when (#870)

called from BlockModelRenderer. Fixes #869.
This commit is contained in:
shartte 2020-07-17 15:49:30 +02:00 committed by modmuss50
parent 57b0bb7ac0
commit a2a03a90f8
2 changed files with 39 additions and 31 deletions

View file

@ -19,12 +19,12 @@ package net.fabricmc.fabric.impl.client.indigo.renderer.render;
import java.util.Random;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.WorldRenderer;
import net.minecraft.client.render.block.BlockModelRenderer;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.util.math.Matrix4f;
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 AoCalculator aoCalc = new AoCalculator(blockInfo, this::brightness, this::aoLevel);
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 long seed;
private boolean isCallingVanilla = 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) {
if (blockInfo.blockView == null) {
@ -76,35 +96,29 @@ public class BlockRenderContext extends AbstractRenderContext implements RenderC
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) {
this.vanillaRenderer = vanillaRenderer;
public boolean render(BlockRenderView blockView, BakedModel model, BlockState state, BlockPos pos, MatrixStack matrixStack, VertexConsumer buffer, Random random, long seed, int overlay) {
this.bufferBuilder = buffer;
this.matrixStack = matrixStack;
this.matrix = matrixStack.peek().getModel();
this.normalMatrix = matrixStack.peek().getNormal();
this.random = random;
this.seed = seed;
this.overlay = overlay;
this.didOutput = false;
aoCalc.clear();
blockInfo.setBlockView(blockView);
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();
this.bufferBuilder = null;
this.random = null;
this.seed = seed;
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 {
MeshConsumer(BlockRenderInfo blockInfo, Function<RenderLayer, VertexConsumer> bufferFunc, AoCalculator aoCalc, QuadTransform transform) {
super(blockInfo, bufferFunc, aoCalc, transform);
@ -133,7 +147,7 @@ public class BlockRenderContext extends AbstractRenderContext implements RenderC
@Override
public Consumer<BakedModel> fallbackConsumer() {
return this::acceptVanillaModel;
return fallbackConsumer;
}
@Override

View file

@ -27,7 +27,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import net.minecraft.block.BlockState;
import net.minecraft.client.color.block.BlockColors;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.block.BlockModelRenderer;
import net.minecraft.client.render.model.BakedModel;
@ -43,22 +42,17 @@ import net.fabricmc.fabric.impl.client.indigo.renderer.render.BlockRenderContext
@Mixin(BlockModelRenderer.class)
public abstract class MixinBlockModelRenderer implements AccessBlockModelRenderer {
@Shadow
protected BlockColors colorMap;
@Shadow
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);
@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()) {
BlockRenderContext context = CONTEXTS.get();
if (!context.isCallingVanilla()) {
ci.setReturnValue(CONTEXTS.get().tesselate((BlockModelRenderer) (Object) this, blockView, model, state, pos, matrix, buffer, checkSides, seed, overlay));
}
// Note that we do not support face-culling here (so checkSides is ignored)
ci.setReturnValue(context.render(blockView, model, state, pos, matrix, buffer, rand, seed, overlay));
}
}