Improve virtual model rendering

- Use VirtualEmptyBlockGetter instead of mc.level
- Move getBufferBuilder from BlockModel to ModelUtil
- Add static .is method to VirtualEmptyModelData
This commit is contained in:
PepperCode1 2021-12-20 17:47:30 -08:00
parent 26c35e31b6
commit 810cae681a
4 changed files with 181 additions and 46 deletions

View file

@ -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<BakedQuad> 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);
}
}

View file

@ -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<ModelBlockRenderer> MODEL_RENDERER = Lazy.of(() -> new ModelBlockRenderer(Minecraft.getInstance().getBlockColors()));
private static final Lazy<BlockModelShaper> 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<BakedQuad> 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<StructureTemplate.StructureBlockInfo> 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();

View file

@ -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());
}
}

View file

@ -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;