From 3e8644c9881231e0ba5056c47ef03cb045f4e56c Mon Sep 17 00:00:00 2001 From: PepperCode1 <44146161+PepperCode1@users.noreply.github.com> Date: Mon, 20 Dec 2021 17:47:30 -0800 Subject: [PATCH] Improve virtual model rendering - Use VirtualEmptyBlockGetter instead of mc.level - Move getBufferBuilder from BlockModel to ModelUtil - Add static .is method to VirtualEmptyModelData --- .../flywheel/core/model/BlockModel.java | 40 +----- .../flywheel/core/model/ModelUtil.java | 47 +++++- .../util/VirtualEmptyBlockGetter.java | 136 ++++++++++++++++++ .../flywheel/util/VirtualEmptyModelData.java | 4 + 4 files changed, 181 insertions(+), 46 deletions(-) create mode 100644 src/main/java/com/jozufozu/flywheel/util/VirtualEmptyBlockGetter.java diff --git a/src/main/java/com/jozufozu/flywheel/core/model/BlockModel.java b/src/main/java/com/jozufozu/flywheel/core/model/BlockModel.java index 44d81c899..14c6cbbb8 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/BlockModel.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/BlockModel.java @@ -1,24 +1,14 @@ package com.jozufozu.flywheel.core.model; -import java.util.Arrays; - import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat; import com.jozufozu.flywheel.core.Formats; import com.jozufozu.flywheel.util.BufferBuilderReader; import com.jozufozu.flywheel.util.RenderMath; -import com.jozufozu.flywheel.util.VirtualEmptyModelData; -import com.mojang.blaze3d.vertex.BufferBuilder; -import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.block.BlockRenderDispatcher; -import net.minecraft.client.renderer.block.ModelBlockRenderer; -import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; import net.minecraft.world.level.block.state.BlockState; /** @@ -42,7 +32,7 @@ public class BlockModel implements Model { } public BlockModel(BakedModel model, BlockState referenceState, PoseStack ms) { - reader = new BufferBuilderReader(getBufferBuilder(model, referenceState, ms)); + reader = new BufferBuilderReader(ModelUtil.getBufferBuilder(model, referenceState, ms)); name = referenceState.toString(); } @@ -76,32 +66,4 @@ public class BlockModel implements Model { buffer.endVertex(); } } - - public static BufferBuilder getBufferBuilder(BakedModel model, BlockState referenceState, PoseStack ms) { - Minecraft mc = Minecraft.getInstance(); - BlockRenderDispatcher dispatcher = mc.getBlockRenderer(); - ModelBlockRenderer blockRenderer = dispatcher.getModelRenderer(); - BufferBuilder builder = new BufferBuilder(512); - - // BakedQuadWrapper quadReader = new BakedQuadWrapper(); - // - // IModelData modelData = model.getModelData(mc.world, BlockPos.ZERO.up(255), referenceState, VirtualEmptyModelData.INSTANCE); - // List quads = Arrays.stream(dirs) - // .flatMap(dir -> model.getQuads(referenceState, dir, mc.world.rand, modelData).stream()) - // .collect(Collectors.toList()); - - builder.begin(com.mojang.blaze3d.vertex.VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK); - blockRenderer.tesselateBlock(mc.level, model, referenceState, BlockPos.ZERO.above(255), ms, builder, true, mc.level.random, 42, OverlayTexture.NO_OVERLAY, VirtualEmptyModelData.INSTANCE); - builder.end(); - return builder; - } - - // DOWN, UP, NORTH, SOUTH, WEST, EAST, null - private static final Direction[] dirs; - - static { - Direction[] directions = Direction.values(); - - dirs = Arrays.copyOf(directions, directions.length + 1); - } } diff --git a/src/main/java/com/jozufozu/flywheel/core/model/ModelUtil.java b/src/main/java/com/jozufozu/flywheel/core/model/ModelUtil.java index bdbb738e8..7e5dca986 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/ModelUtil.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/ModelUtil.java @@ -1,14 +1,16 @@ package com.jozufozu.flywheel.core.model; -import static com.mojang.blaze3d.vertex.VertexFormat.Mode.QUADS; - +import java.util.Arrays; import java.util.Collection; import java.util.Random; import com.jozufozu.flywheel.util.Lazy; +import com.jozufozu.flywheel.util.VirtualEmptyBlockGetter; +import com.jozufozu.flywheel.util.VirtualEmptyModelData; import com.mojang.blaze3d.vertex.BufferBuilder; import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexFormat; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.ItemBlockRenderTypes; @@ -16,7 +18,9 @@ import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.block.BlockModelShaper; import net.minecraft.client.renderer.block.ModelBlockRenderer; import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.client.resources.model.BakedModel; import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.block.RenderShape; import net.minecraft.world.level.block.state.BlockState; @@ -26,13 +30,42 @@ import net.minecraftforge.client.model.data.EmptyModelData; public class ModelUtil { private static final Lazy MODEL_RENDERER = Lazy.of(() -> new ModelBlockRenderer(Minecraft.getInstance().getBlockColors())); - private static final Lazy BLOCK_MODELS = Lazy.of(() -> Minecraft.getInstance().getModelManager().getBlockModelShaper()); + + // DOWN, UP, NORTH, SOUTH, WEST, EAST, null + private static final Direction[] CULL_FACES; + + static { + Direction[] directions = Direction.values(); + + CULL_FACES = Arrays.copyOf(directions, directions.length + 1); + } + + public static BufferBuilder getBufferBuilder(BakedModel model, BlockState referenceState, PoseStack ms) { + ModelBlockRenderer blockRenderer = Minecraft.getInstance().getBlockRenderer().getModelRenderer(); + BufferBuilder builder = new BufferBuilder(512); + + // BakedQuadWrapper quadReader = new BakedQuadWrapper(); + // + // IModelData modelData = model.getModelData(VirtualEmptyBlockGetter.INSTANCE, BlockPos.ZERO, referenceState, VirtualEmptyModelData.INSTANCE); + // List quads = Arrays.stream(CULL_FACES) + // .flatMap(dir -> model.getQuads(referenceState, dir, new Random(), modelData).stream()) + // .collect(Collectors.toList()); + + builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK); + blockRenderer.tesselateBlock(VirtualEmptyBlockGetter.INSTANCE, model, referenceState, BlockPos.ZERO, ms, builder, + true, new Random(), 42, OverlayTexture.NO_OVERLAY, VirtualEmptyModelData.INSTANCE); + builder.end(); + return builder; + } public static BufferBuilder getBufferBuilderFromTemplate(BlockAndTintGetter renderWorld, RenderType layer, Collection blocks) { + ModelBlockRenderer modelRenderer = MODEL_RENDERER.get(); + BlockModelShaper blockModels = Minecraft.getInstance().getModelManager().getBlockModelShaper(); + PoseStack ms = new PoseStack(); Random random = new Random(); - BufferBuilder builder = new BufferBuilder(DefaultVertexFormat.BLOCK.getIntegerSize()); - builder.begin(QUADS, DefaultVertexFormat.BLOCK); + BufferBuilder builder = new BufferBuilder(512); + builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK); ForgeHooksClient.setRenderType(layer); ModelBlockRenderer.enableCaching(); @@ -48,8 +81,8 @@ public class ModelUtil { ms.pushPose(); ms.translate(pos.getX(), pos.getY(), pos.getZ()); - MODEL_RENDERER.get().tesselateBlock(renderWorld, BLOCK_MODELS.get().getBlockModel(state), state, pos, ms, builder, true, - random, 42, OverlayTexture.NO_OVERLAY, EmptyModelData.INSTANCE); + modelRenderer.tesselateBlock(renderWorld, blockModels.getBlockModel(state), state, pos, ms, builder, + true, random, 42, OverlayTexture.NO_OVERLAY, EmptyModelData.INSTANCE); ms.popPose(); } ModelBlockRenderer.clearCache(); diff --git a/src/main/java/com/jozufozu/flywheel/util/VirtualEmptyBlockGetter.java b/src/main/java/com/jozufozu/flywheel/util/VirtualEmptyBlockGetter.java new file mode 100644 index 000000000..4f88342ab --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/util/VirtualEmptyBlockGetter.java @@ -0,0 +1,136 @@ +package com.jozufozu.flywheel.util; + +import net.minecraft.client.Minecraft; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Registry; +import net.minecraft.core.SectionPos; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.ColorResolver; +import net.minecraft.world.level.LightLayer; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.biome.Biomes; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.DataLayer; +import net.minecraft.world.level.chunk.LightChunkGetter; +import net.minecraft.world.level.lighting.LayerLightEventListener; +import net.minecraft.world.level.lighting.LevelLightEngine; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.level.material.Fluids; + +public enum VirtualEmptyBlockGetter implements BlockAndTintGetter { + INSTANCE; + + private final LevelLightEngine lightEngine = new LevelLightEngine(new LightChunkGetter() { + @Override + public BlockGetter getChunkForLighting(int p_63023_, int p_63024_) { + return VirtualEmptyBlockGetter.this; + } + + @Override + public BlockGetter getLevel() { + return VirtualEmptyBlockGetter.this; + } + }, false, false) { + private static final LayerLightEventListener SKY_DUMMY_LISTENER = new LayerLightEventListener() { + @Override + public void checkBlock(BlockPos pos) { + } + + @Override + public void onBlockEmissionIncrease(BlockPos pos, int p_164456_) { + } + + @Override + public boolean hasLightWork() { + return false; + } + + @Override + public int runUpdates(int p_164449_, boolean p_164450_, boolean p_164451_) { + return p_164449_; + } + + @Override + public void updateSectionStatus(SectionPos pos, boolean p_75838_) { + } + + @Override + public void enableLightSources(ChunkPos pos, boolean p_164453_) { + } + + @Override + public DataLayer getDataLayerData(SectionPos pos) { + return null; + } + + @Override + public int getLightValue(BlockPos pos) { + return 15; + } + }; + + @Override + public LayerLightEventListener getLayerListener(LightLayer layer) { + if (layer == LightLayer.BLOCK) { + return LayerLightEventListener.DummyLightLayerEventListener.INSTANCE; + } else { + return SKY_DUMMY_LISTENER; + } + } + + @Override + public int getRawBrightness(BlockPos pos, int skyDarken) { + return 15 - skyDarken; + } + }; + + public static boolean is(BlockAndTintGetter blockGetter) { + return blockGetter == INSTANCE; + } + + @Override + public BlockEntity getBlockEntity(BlockPos pos) { + return null; + } + + @Override + public BlockState getBlockState(BlockPos pos) { + return Blocks.AIR.defaultBlockState(); + } + + @Override + public FluidState getFluidState(BlockPos pos) { + return Fluids.EMPTY.defaultFluidState(); + } + + @Override + public int getHeight() { + return 1; + } + + @Override + public int getMinBuildHeight() { + return 0; + } + + @Override + public float getShade(Direction direction, boolean bool) { + return Minecraft.getInstance().level.getShade(direction, bool); + } + + @Override + public LevelLightEngine getLightEngine() { + return lightEngine; + } + + @Override + public int getBlockTint(BlockPos pos, ColorResolver resolver) { + Biome plainsBiome = Minecraft.getInstance().getConnection().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY).getOrThrow(Biomes.PLAINS); + return resolver.getColor(plainsBiome, pos.getX(), pos.getZ()); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/util/VirtualEmptyModelData.java b/src/main/java/com/jozufozu/flywheel/util/VirtualEmptyModelData.java index e61807f85..6d60d2bdb 100644 --- a/src/main/java/com/jozufozu/flywheel/util/VirtualEmptyModelData.java +++ b/src/main/java/com/jozufozu/flywheel/util/VirtualEmptyModelData.java @@ -12,6 +12,10 @@ public enum VirtualEmptyModelData implements IModelData { INSTANCE; + public static boolean is(IModelData data) { + return data == INSTANCE; + } + @Override public boolean hasProperty(ModelProperty prop) { return false;