Shuffling the shade

- Update Flywheel and add support for unshaded quads
- Fix models marking shafts and other parts as unshaded
- Refactor SchematicRenderer buffer building
- Improve block entity render bounding box caching
- Fix #2785
This commit is contained in:
PepperCode1 2022-02-19 21:42:40 -08:00
parent 984cde4d43
commit 0cf0d3930e
51 changed files with 230 additions and 227 deletions

View file

@ -19,7 +19,7 @@ parchment_version = 2022.01.23
# dependency versions
registrate_version = MC1.18-1.0.21
flywheel_version = 1.18-0.6.1.61
flywheel_version = 1.18-0.6.1.62
jei_minecraft_version = 1.18.1
jei_version = 9.3.2.92

View file

@ -42,7 +42,6 @@ import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.DistExecutor;
@ -96,7 +95,6 @@ public class KineticTileEntity extends SmartTileEntity
effects.tick();
if (level.isClientSide) {
cachedBoundingBox = null; // cache the bounding box for every frame between ticks
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> this.tickAudio());
return;
}
@ -570,20 +568,6 @@ public class KineticTileEntity extends SmartTileEntity
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(this));
}
protected AABB cachedBoundingBox;
@OnlyIn(Dist.CLIENT)
public AABB getRenderBoundingBox() {
if (cachedBoundingBox == null) {
cachedBoundingBox = makeRenderBoundingBox();
}
return cachedBoundingBox;
}
protected AABB makeRenderBoundingBox() {
return super.getRenderBoundingBox();
}
@OnlyIn(Dist.CLIENT)
public void tickAudio() {
float componentSpeed = Math.abs(getSpeed());

View file

@ -1,17 +1,13 @@
package com.simibubi.create.content.contraptions.components.actors;
import com.simibubi.create.foundation.tileEntity.SyncedTileEntity;
import com.simibubi.create.foundation.tileEntity.CachedRenderBBTileEntity;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public class HarvesterTileEntity extends SyncedTileEntity {
private static final AABB RENDER_BOX = new AABB(0, 0, 0, 1, 1, 1);
public class HarvesterTileEntity extends CachedRenderBBTileEntity {
// For simulations such as Ponder
private float manuallyAnimatedSpeed;
@ -21,9 +17,8 @@ public class HarvesterTileEntity extends SyncedTileEntity {
}
@Override
@OnlyIn(Dist.CLIENT)
public AABB getRenderBoundingBox() {
return RENDER_BOX.move(worldPosition);
protected AABB createRenderBoundingBox() {
return new AABB(worldPosition);
}
public float getAnimatedSpeed() {

View file

@ -15,8 +15,6 @@ import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public abstract class PortableStorageInterfaceTileEntity extends SmartTileEntity {
@ -113,15 +111,9 @@ public abstract class PortableStorageInterfaceTileEntity extends SmartTileEntity
return powered;
}
protected AABB cachedBoundingBox;
@Override
@OnlyIn(Dist.CLIENT)
public AABB getRenderBoundingBox() {
if (cachedBoundingBox == null) {
cachedBoundingBox = super.getRenderBoundingBox().inflate(2);
}
return cachedBoundingBox;
protected AABB createRenderBoundingBox() {
return super.createRenderBoundingBox().inflate(2);
}
public boolean isTransferring() {

View file

@ -231,7 +231,7 @@ public class CrushingWheelControllerTileEntity extends SmartTileEntity {
processingEntity.setPos(entityOutPos.x, entityOutPos.y, entityOutPos.z);
}
}
processingEntity.hurt(CrushingWheelTileEntity.damageSource, crusherDamage);
processingEntity.hurt(CrushingWheelTileEntity.DAMAGE_SOURCE, crusherDamage);
if (!processingEntity.isAlive()) {
processingEntity.setPos(entityOutPos.x, entityOutPos.y, entityOutPos.z);
}

View file

@ -19,7 +19,7 @@ import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
@EventBusSubscriber
public class CrushingWheelTileEntity extends KineticTileEntity {
public static DamageSource damageSource = new DamageSource("create.crush").bypassArmor()
public static final DamageSource DAMAGE_SOURCE = new DamageSource("create.crush").bypassArmor()
.setScalesWithDifficulty();
public CrushingWheelTileEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
@ -40,7 +40,7 @@ public class CrushingWheelTileEntity extends KineticTileEntity {
}
@Override
public AABB makeRenderBoundingBox() {
protected AABB createRenderBoundingBox() {
return new AABB(worldPosition).inflate(1);
}
@ -52,14 +52,14 @@ public class CrushingWheelTileEntity extends KineticTileEntity {
@SubscribeEvent
public static void crushingIsFortunate(LootingLevelEvent event) {
if (event.getDamageSource() != damageSource)
if (event.getDamageSource() != DAMAGE_SOURCE)
return;
event.setLootingLevel(2); //This does not currently increase mob drops. It seems like this only works for damage done by an entity.
}
@SubscribeEvent
public static void handleCrushedMobDrops(LivingDropsEvent event) {
if (event.getSource() != CrushingWheelTileEntity.damageSource)
if (event.getSource() != CrushingWheelTileEntity.DAMAGE_SOURCE)
return;
Vec3 outSpeed = Vec3.ZERO;
for (ItemEntity outputItem : event.getDrops()) {

View file

@ -388,8 +388,8 @@ public class DeployerTileEntity extends KineticTileEntity {
}
@Override
public AABB makeRenderBoundingBox() {
return super.makeRenderBoundingBox().inflate(3);
protected AABB createRenderBoundingBox() {
return super.createRenderBoundingBox().inflate(3);
}
@Override

View file

@ -50,8 +50,8 @@ public class FlywheelTileEntity extends GeneratingKineticTileEntity {
}
@Override
public AABB makeRenderBoundingBox() {
return super.makeRenderBoundingBox().inflate(2);
protected AABB createRenderBoundingBox() {
return super.createRenderBoundingBox().inflate(2);
}
@Override

View file

@ -14,8 +14,6 @@ import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public class EngineTileEntity extends SmartTileEntity {
@ -31,14 +29,9 @@ public class EngineTileEntity extends SmartTileEntity {
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
}
protected AABB cachedBoundingBox;
@Override
@OnlyIn(Dist.CLIENT)
public AABB getRenderBoundingBox() {
if (cachedBoundingBox == null) {
cachedBoundingBox = super.getRenderBoundingBox().inflate(1.5f);
}
return cachedBoundingBox;
protected AABB createRenderBoundingBox() {
return super.createRenderBoundingBox().inflate(1.5f);
}
@Override

View file

@ -91,7 +91,7 @@ public class MechanicalMixerTileEntity extends BasinOperatingTileEntity {
}
@Override
public AABB makeRenderBoundingBox() {
protected AABB createRenderBoundingBox() {
return new AABB(worldPosition).expandTowards(0, -1.5, 0);
}

View file

@ -111,7 +111,7 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity {
}
@Override
public AABB makeRenderBoundingBox() {
protected AABB createRenderBoundingBox() {
return new AABB(worldPosition).expandTowards(0, -1.5, 0)
.expandTowards(0, 1, 0);
}

View file

@ -73,8 +73,6 @@ import net.minecraftforge.items.IItemHandler;
@MethodsReturnNonnullByDefault
public class SawTileEntity extends BlockBreakingKineticTileEntity {
private static final AABB RENDER_BOX = new AABB(0, 0, 0, 1, 1, 1);
private static final Object cuttingRecipesKey = new Object();
public static final Supplier<RecipeType<?>> woodcuttingRecipeType =
Suppliers.memoize(() -> Registry.RECIPE_TYPE.get(new ResourceLocation("druidcraft", "woodcutting")));
@ -125,9 +123,8 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity {
}
@Override
protected AABB makeRenderBoundingBox() {
return RENDER_BOX.inflate(.125f)
.move(worldPosition);
protected AABB createRenderBoundingBox() {
return new AABB(worldPosition).inflate(.125f);
}
@Override

View file

@ -34,8 +34,8 @@ public class PulleyTileEntity extends LinearActuatorTileEntity {
}
@Override
public AABB makeRenderBoundingBox() {
return super.makeRenderBoundingBox().expandTowards(0, -offset, 0);
protected AABB createRenderBoundingBox() {
return super.createRenderBoundingBox().expandTowards(0, -offset, 0);
}
@Override
@ -43,6 +43,7 @@ public class PulleyTileEntity extends LinearActuatorTileEntity {
super.tick();
if (isVirtual())
prevAnimatedOffset = offset;
invalidateRenderBoundingBox();
}
@Override

View file

@ -38,7 +38,7 @@ public class WaterWheelTileEntity extends GeneratingKineticTileEntity {
}
@Override
public AABB makeRenderBoundingBox() {
protected AABB createRenderBoundingBox() {
return new AABB(worldPosition).inflate(1);
}

View file

@ -16,8 +16,6 @@ import net.minecraft.network.chat.Component;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fluids.FluidStack;
@ -99,9 +97,8 @@ public class HosePulleyTileEntity extends KineticTileEntity {
}
@Override
@OnlyIn(Dist.CLIENT)
public AABB getRenderBoundingBox() {
return super.getRenderBoundingBox().expandTowards(0, -offset.getValue(), 0);
protected AABB createRenderBoundingBox() {
return super.createRenderBoundingBox().expandTowards(0, -offset.getValue(), 0);
}
@Override
@ -122,6 +119,7 @@ public class HosePulleyTileEntity extends KineticTileEntity {
isMoving = false;
offset.setValue(newOffset);
invalidateRenderBoundingBox();
}
@Override

View file

@ -33,8 +33,6 @@ import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fluids.FluidStack;
@ -56,14 +54,9 @@ public class SpoutTileEntity extends SmartTileEntity implements IHaveGoggleInfor
processingTicks = -1;
}
protected AABB cachedBoundingBox;
@Override
@OnlyIn(Dist.CLIENT)
public AABB getRenderBoundingBox() {
if (cachedBoundingBox == null)
cachedBoundingBox = super.getRenderBoundingBox().expandTowards(0, -2, 0);
return cachedBoundingBox;
protected AABB createRenderBoundingBox() {
return super.createRenderBoundingBox().expandTowards(0, -2, 0);
}
@Override

View file

@ -25,8 +25,6 @@ import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fluids.FluidAttributes;
@ -58,7 +56,6 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI
// For rendering purposes only
private InterpolatedChasingValue fluidLevel;
private AABB renderBoundingBox;
public FluidTankTileEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state);
@ -123,7 +120,7 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI
super.initialize();
sendData();
if (level.isClientSide)
updateRenderBoundingBox();
invalidateRenderBoundingBox();
}
private void onPositionChanged() {
@ -304,20 +301,12 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI
return isController() ? worldPosition : controller;
}
public void updateRenderBoundingBox() {
if (isController())
renderBoundingBox = super.getRenderBoundingBox().expandTowards(width - 1, height - 1, width - 1);
else
renderBoundingBox = super.getRenderBoundingBox();
}
@Override
@OnlyIn(Dist.CLIENT)
public AABB getRenderBoundingBox() {
if (renderBoundingBox == null) {
renderBoundingBox = super.getRenderBoundingBox();
}
return renderBoundingBox;
protected AABB createRenderBoundingBox() {
if (isController())
return super.createRenderBoundingBox().expandTowards(width - 1, height - 1, width - 1);
else
return super.createRenderBoundingBox();
}
@Nullable
@ -380,7 +369,7 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI
level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 16);
if (isController())
tankInventory.setCapacity(getCapacityMultiplier() * getTotalTankSize());
updateRenderBoundingBox();
invalidateRenderBoundingBox();
}
if (isController()) {
float fillState = getFillState();

View file

@ -126,6 +126,7 @@ public class BeltTileEntity extends KineticTileEntity {
lighter = new BeltLighter();
}
});
invalidateRenderBoundingBox();
getInventory().tick();
@ -160,11 +161,11 @@ public class BeltTileEntity extends KineticTileEntity {
}
@Override
public AABB makeRenderBoundingBox() {
public AABB createRenderBoundingBox() {
if (!isController())
return super.makeRenderBoundingBox();
return super.createRenderBoundingBox();
else
return super.makeRenderBoundingBox().inflate(beltLength + 1);
return super.createRenderBoundingBox().inflate(beltLength + 1);
}
protected void initializeItemHandler() {

View file

@ -17,7 +17,7 @@ public class SimpleKineticTileEntity extends KineticTileEntity {
}
@Override
public AABB makeRenderBoundingBox() {
protected AABB createRenderBoundingBox() {
return new AABB(worldPosition).inflate(1);
}

View file

@ -10,8 +10,6 @@ import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.item.ArmorMaterial;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public enum AllArmorMaterials implements ArmorMaterial {
@ -30,47 +28,54 @@ public enum AllArmorMaterials implements ArmorMaterial {
private final float knockbackResistance;
private final Supplier<Ingredient> repairMaterial;
private AllArmorMaterials(String p_i231593_3_, int p_i231593_4_, int[] p_i231593_5_, int p_i231593_6_,
SoundEvent p_i231593_7_, float p_i231593_8_, float p_i231593_9_, Supplier<Ingredient> p_i231593_10_) {
this.name = p_i231593_3_;
this.maxDamageFactor = p_i231593_4_;
this.damageReductionAmountArray = p_i231593_5_;
this.enchantability = p_i231593_6_;
this.soundEvent = p_i231593_7_;
this.toughness = p_i231593_8_;
this.knockbackResistance = p_i231593_9_;
this.repairMaterial = Suppliers.memoize(p_i231593_10_::get);
private AllArmorMaterials(String name, int maxDamageFactor, int[] damageReductionAmountArray, int enchantability,
SoundEvent soundEvent, float toughness, float knockbackResistance, Supplier<Ingredient> repairMaterial) {
this.name = name;
this.maxDamageFactor = maxDamageFactor;
this.damageReductionAmountArray = damageReductionAmountArray;
this.enchantability = enchantability;
this.soundEvent = soundEvent;
this.toughness = toughness;
this.knockbackResistance = knockbackResistance;
this.repairMaterial = Suppliers.memoize(repairMaterial::get);
}
public int getDurabilityForSlot(EquipmentSlot p_200896_1_) {
return MAX_DAMAGE_ARRAY[p_200896_1_.getIndex()] * this.maxDamageFactor;
@Override
public int getDurabilityForSlot(EquipmentSlot slot) {
return MAX_DAMAGE_ARRAY[slot.getIndex()] * this.maxDamageFactor;
}
public int getDefenseForSlot(EquipmentSlot p_200902_1_) {
return this.damageReductionAmountArray[p_200902_1_.getIndex()];
@Override
public int getDefenseForSlot(EquipmentSlot slot) {
return this.damageReductionAmountArray[slot.getIndex()];
}
@Override
public int getEnchantmentValue() {
return this.enchantability;
}
@Override
public SoundEvent getEquipSound() {
return this.soundEvent;
}
@Override
public Ingredient getRepairIngredient() {
return this.repairMaterial.get();
}
@OnlyIn(Dist.CLIENT)
@Override
public String getName() {
return this.name;
}
@Override
public float getToughness() {
return this.toughness;
}
@Override
public float getKnockbackResistance() {
return this.knockbackResistance;
}

View file

@ -127,7 +127,7 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor
}
@Override
public AABB getRenderBoundingBox() {
protected AABB createRenderBoundingBox() {
return new AABB(worldPosition).expandTowards(0, -3, 0);
}

View file

@ -40,8 +40,6 @@ import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public class ArmTileEntity extends KineticTileEntity implements ITransformableTE {
@ -160,9 +158,8 @@ public class ArmTileEntity extends KineticTileEntity implements ITransformableTE
}
@Override
@OnlyIn(Dist.CLIENT)
public AABB makeRenderBoundingBox() {
return super.makeRenderBoundingBox().inflate(3);
protected AABB createRenderBoundingBox() {
return super.createRenderBoundingBox().inflate(3);
}
private boolean checkForMusicAmong(List<ArmInteractionPoint> list) {

View file

@ -55,6 +55,8 @@ import net.minecraft.world.level.block.state.properties.BedPart;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.DoubleBlockHalf;
import net.minecraft.world.phys.AABB;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
@ -812,6 +814,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements MenuPro
}
@Override
@OnlyIn(Dist.CLIENT)
public AABB getRenderBoundingBox() {
return INFINITE_EXTENT_AABB;
}

View file

@ -1,15 +1,12 @@
package com.simibubi.create.content.schematics.client;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import com.jozufozu.flywheel.core.model.ModelUtil;
import com.jozufozu.flywheel.util.transform.TransformStack;
import com.jozufozu.flywheel.core.model.ShadeSeparatedBufferBuilder;
import com.jozufozu.flywheel.core.model.ShadeSeparatingVertexConsumer;
import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.PoseStack;
@ -23,17 +20,20 @@ import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.ItemBlockRenderTypes;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
import net.minecraft.client.renderer.block.ModelBlockRenderer;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.structure.BoundingBox;
import net.minecraftforge.client.ForgeHooksClient;
import net.minecraftforge.client.model.data.EmptyModelData;
public class SchematicRenderer {
private static final ThreadLocal<ThreadLocalObjects> THREAD_LOCAL_OBJECTS = ThreadLocal.withInitial(ThreadLocalObjects::new);
private final Map<RenderType, SuperByteBuffer> bufferCache = new HashMap<>(getLayerCount());
private final Set<RenderType> usedBlockRenderLayers = new HashSet<>(getLayerCount());
private final Set<RenderType> startedBufferBuilders = new HashSet<>(getLayerCount());
private boolean active;
private boolean changed;
protected SchematicWorld schematic;
@ -69,75 +69,81 @@ public class SchematicRenderer {
changed = false;
}
public void render(PoseStack ms, SuperRenderTypeBuffer buffer) {
public void render(PoseStack ms, SuperRenderTypeBuffer buffers) {
if (!active)
return;
for (RenderType layer : RenderType.chunkBufferLayers()) {
if (!usedBlockRenderLayers.contains(layer))
continue;
SuperByteBuffer superByteBuffer = bufferCache.get(layer);
superByteBuffer.renderInto(ms, buffer.getBuffer(layer));
}
TileEntityRenderHelper.renderTileEntities(schematic, schematic.getRenderedTileEntities(), ms, buffer);
bufferCache.forEach((layer, buffer) -> {
buffer.renderInto(ms, buffers.getBuffer(layer));
});
TileEntityRenderHelper.renderTileEntities(schematic, schematic.getRenderedTileEntities(), ms, buffers);
}
protected void redraw() {
usedBlockRenderLayers.clear();
startedBufferBuilders.clear();
final SchematicWorld blockAccess = schematic;
final BlockRenderDispatcher blockRendererDispatcher = ModelUtil.VANILLA_RENDERER;
List<BlockState> blockstates = new LinkedList<>();
Map<RenderType, BufferBuilder> buffers = new HashMap<>();
PoseStack ms = new PoseStack();
Random random = new Random();
BlockPos.betweenClosedStream(blockAccess.getBounds())
.forEach(localPos -> {
ms.pushPose();
TransformStack.cast(ms)
.translate(localPos);
BlockPos pos = localPos.offset(anchor);
BlockState state = blockAccess.getBlockState(pos);
for (RenderType blockRenderLayer : RenderType.chunkBufferLayers()) {
if (!ItemBlockRenderTypes.canRenderInLayer(state, blockRenderLayer))
continue;
ForgeHooksClient.setRenderType(blockRenderLayer);
if (!buffers.containsKey(blockRenderLayer))
buffers.put(blockRenderLayer, new BufferBuilder(512));
BufferBuilder bufferBuilder = buffers.get(blockRenderLayer);
if (startedBufferBuilders.add(blockRenderLayer))
bufferBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
BlockEntity tileEntity = blockAccess.getBlockEntity(localPos);
if (blockRendererDispatcher.renderBatched(state, pos, blockAccess, ms, bufferBuilder, true,
random, tileEntity != null ? tileEntity.getModelData() : EmptyModelData.INSTANCE)) {
usedBlockRenderLayers.add(blockRenderLayer);
}
blockstates.add(state);
}
ForgeHooksClient.setRenderType(null);
ms.popPose();
});
// finishDrawing
bufferCache.clear();
for (RenderType layer : RenderType.chunkBufferLayers()) {
if (!startedBufferBuilders.contains(layer))
continue;
BufferBuilder buf = buffers.get(layer);
buf.end();
bufferCache.put(layer, new SuperByteBuffer(buf));
SuperByteBuffer buffer = drawLayer(layer);
if (!buffer.isEmpty())
bufferCache.put(layer, buffer);
}
}
protected SuperByteBuffer drawLayer(RenderType layer) {
BlockRenderDispatcher dispatcher = ModelUtil.VANILLA_RENDERER;
ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get();
PoseStack poseStack = objects.poseStack;
Random random = objects.random;
BlockPos.MutableBlockPos mutableBlockPos = objects.mutableBlockPos;
SchematicWorld renderWorld = schematic;
BoundingBox bounds = renderWorld.getBounds();
ShadeSeparatingVertexConsumer shadeSeparatingWrapper = objects.shadeSeparatingWrapper;
ShadeSeparatedBufferBuilder builder = new ShadeSeparatedBufferBuilder(512);
BufferBuilder unshadedBuilder = objects.unshadedBuilder;
builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
unshadedBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
shadeSeparatingWrapper.prepare(builder, unshadedBuilder);
ForgeHooksClient.setRenderType(layer);
ModelBlockRenderer.enableCaching();
for (BlockPos localPos : BlockPos.betweenClosed(bounds.minX(), bounds.minY(), bounds.minZ(), bounds.maxX(), bounds.maxY(), bounds.maxZ())) {
BlockPos pos = mutableBlockPos.setWithOffset(localPos, anchor);
BlockState state = renderWorld.getBlockState(pos);
poseStack.pushPose();
poseStack.translate(localPos.getX(), localPos.getY(), localPos.getZ());
if (state.getRenderShape() == RenderShape.MODEL && ItemBlockRenderTypes.canRenderInLayer(state, layer)) {
BlockEntity tileEntity = renderWorld.getBlockEntity(localPos);
dispatcher.renderBatched(state, pos, renderWorld, poseStack, shadeSeparatingWrapper, true, random,
tileEntity != null ? tileEntity.getModelData() : EmptyModelData.INSTANCE);
}
poseStack.popPose();
}
ModelBlockRenderer.clearCache();
ForgeHooksClient.setRenderType(null);
shadeSeparatingWrapper.clear();
unshadedBuilder.end();
builder.appendUnshadedVertices(unshadedBuilder);
builder.end();
return new SuperByteBuffer(builder);
}
private static int getLayerCount() {
return RenderType.chunkBufferLayers()
.size();
}
private static class ThreadLocalObjects {
public final PoseStack poseStack = new PoseStack();
public final Random random = new Random();
public final BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
public final ShadeSeparatingVertexConsumer shadeSeparatingWrapper = new ShadeSeparatingVertexConsumer();
public final BufferBuilder unshadedBuilder = new BufferBuilder(512);
}
}

View file

@ -8,6 +8,8 @@ import java.util.Random;
import java.util.function.Consumer;
import com.jozufozu.flywheel.core.model.ModelUtil;
import com.jozufozu.flywheel.core.model.ShadeSeparatedBufferBuilder;
import com.jozufozu.flywheel.core.model.ShadeSeparatingVertexConsumer;
import com.jozufozu.flywheel.util.transform.TransformStack;
import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
@ -33,6 +35,7 @@ import net.minecraft.client.renderer.ItemBlockRenderTypes;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
import net.minecraft.client.renderer.block.ModelBlockRenderer;
import net.minecraft.client.resources.model.ModelBakery;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction.Axis;
@ -58,6 +61,8 @@ public class WorldSectionElement extends AnimatedSceneElement {
public static final SuperByteBufferCache.Compartment<Pair<Integer, Integer>> DOC_WORLD_SECTION =
new SuperByteBufferCache.Compartment<>();
private static final ThreadLocal<ThreadLocalObjects> THREAD_LOCAL_OBJECTS = ThreadLocal.withInitial(ThreadLocalObjects::new);
List<BlockEntity> renderedTileEntities;
List<Pair<BlockEntity, Consumer<Level>>> tickableTileEntities;
Selection section;
@ -401,37 +406,57 @@ public class WorldSectionElement extends AnimatedSceneElement {
}
private SuperByteBuffer buildStructureBuffer(PonderWorld world, RenderType layer) {
ForgeHooksClient.setRenderType(layer);
BlockRenderDispatcher dispatcher = ModelUtil.VANILLA_RENDERER;
PoseStack ms = new PoseStack();
Random random = new Random();
BufferBuilder builder = new BufferBuilder(512);
builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
world.setMask(this.section);
ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get();
PoseStack poseStack = objects.poseStack;
Random random = objects.random;
ShadeSeparatingVertexConsumer shadeSeparatingWrapper = objects.shadeSeparatingWrapper;
ShadeSeparatedBufferBuilder builder = new ShadeSeparatedBufferBuilder(512);
BufferBuilder unshadedBuilder = objects.unshadedBuilder;
builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
unshadedBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
shadeSeparatingWrapper.prepare(builder, unshadedBuilder);
world.setMask(this.section);
ForgeHooksClient.setRenderType(layer);
ModelBlockRenderer.enableCaching();
section.forEach(pos -> {
BlockState state = world.getBlockState(pos);
FluidState fluidState = world.getFluidState(pos);
ms.pushPose();
ms.translate(pos.getX(), pos.getY(), pos.getZ());
poseStack.pushPose();
poseStack.translate(pos.getX(), pos.getY(), pos.getZ());
if (state.getRenderShape() == RenderShape.MODEL && ItemBlockRenderTypes.canRenderInLayer(state, layer)) {
BlockEntity tileEntity = world.getBlockEntity(pos);
dispatcher.renderBatched(state, pos, world, ms, builder, true, random,
dispatcher.renderBatched(state, pos, world, poseStack, shadeSeparatingWrapper, true, random,
tileEntity != null ? tileEntity.getModelData() : EmptyModelData.INSTANCE);
}
if (!fluidState.isEmpty() && ItemBlockRenderTypes.canRenderInLayer(fluidState, layer))
dispatcher.renderLiquid(pos, world, builder, fluidState);
ms.popPose();
poseStack.popPose();
});
world.clearMask();
builder.end();
ModelBlockRenderer.clearCache();
ForgeHooksClient.setRenderType(null);
world.clearMask();
shadeSeparatingWrapper.clear();
unshadedBuilder.end();
builder.appendUnshadedVertices(unshadedBuilder);
builder.end();
return new SuperByteBuffer(builder);
}
private static class ThreadLocalObjects {
public final PoseStack poseStack = new PoseStack();
public final Random random = new Random();
public final ShadeSeparatingVertexConsumer shadeSeparatingWrapper = new ShadeSeparatingVertexConsumer();
public final BufferBuilder unshadedBuilder = new BufferBuilder(512);
}
}

View file

@ -1,7 +1,11 @@
package com.simibubi.create.foundation.render;
import java.util.function.IntPredicate;
import com.jozufozu.flywheel.api.vertex.ShadedVertexList;
import com.jozufozu.flywheel.api.vertex.VertexList;
import com.jozufozu.flywheel.backend.OptifineHandler;
import com.jozufozu.flywheel.core.model.ShadeSeparatedBufferBuilder;
import com.jozufozu.flywheel.core.vertex.BlockVertexList;
import com.jozufozu.flywheel.util.DiffuseLightCalculator;
import com.jozufozu.flywheel.util.transform.Rotate;
@ -34,6 +38,7 @@ import net.minecraft.world.level.Level;
public class SuperByteBuffer implements Scale<SuperByteBuffer>, Translate<SuperByteBuffer>, Rotate<SuperByteBuffer>, TStack<SuperByteBuffer> {
private final VertexList template;
private final IntPredicate shadedPredicate;
// Vertex Position
private final PoseStack transforms;
@ -65,7 +70,14 @@ public class SuperByteBuffer implements Scale<SuperByteBuffer>, Translate<SuperB
private static final Long2IntMap WORLD_LIGHT_CACHE = new Long2IntOpenHashMap();
public SuperByteBuffer(BufferBuilder buf) {
template = new BlockVertexList(buf);
if (buf instanceof ShadeSeparatedBufferBuilder separated) {
ShadedVertexList template = new BlockVertexList.Shaded(separated);
shadedPredicate = template::isShaded;
this.template = template;
} else {
template = new BlockVertexList(buf);
shadedPredicate = index -> true;
}
transforms = new PoseStack();
transforms.pushPose();
}
@ -142,7 +154,7 @@ public class SuperByteBuffer implements Scale<SuperByteBuffer>, Translate<SuperB
if (disableDiffuseMult) {
builder.color(r, g, b, a);
} else {
float instanceDiffuse = diffuseCalculator.getDiffuse(nx, ny, nz);
float instanceDiffuse = diffuseCalculator.getDiffuse(nx, ny, nz, shadedPredicate.test(i));
int colorR = transformColor(r, instanceDiffuse);
int colorG = transformColor(g, instanceDiffuse);
int colorB = transformColor(b, instanceDiffuse);

View file

@ -0,0 +1,35 @@
package com.simibubi.create.foundation.tileEntity;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public abstract class CachedRenderBBTileEntity extends SyncedTileEntity {
private AABB renderBoundingBox;
public CachedRenderBBTileEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state);
}
@Override
@OnlyIn(Dist.CLIENT)
public AABB getRenderBoundingBox() {
if (renderBoundingBox == null) {
renderBoundingBox = createRenderBoundingBox();
}
return renderBoundingBox;
}
protected void invalidateRenderBoundingBox() {
renderBoundingBox = null;
}
protected AABB createRenderBoundingBox() {
return super.getRenderBoundingBox();
}
}

View file

@ -23,7 +23,7 @@ import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.items.CapabilityItemHandler;
public abstract class SmartTileEntity extends SyncedTileEntity implements IPartialSafeNBT, IInteractionChecker {
public abstract class SmartTileEntity extends CachedRenderBBTileEntity implements IPartialSafeNBT, IInteractionChecker {
private final Map<BehaviourType<?>, TileEntityBehaviour> behaviours = new HashMap<>();
private boolean initialized = false;

View file

@ -13,7 +13,6 @@
"name": "Axis",
"from": [6, 0, 6],
"to": [10, 16, 10],
"shade": false,
"faces": {
"north": {"uv": [6, 0, 10, 16], "texture": "#0"},
"east": {"uv": [6, 0, 10, 16], "texture": "#0"},

View file

@ -13,7 +13,6 @@
"name": "Axis",
"from": [6, 0, 6],
"to": [10, 16, 10],
"shade": false,
"faces": {
"north": {"uv": [6, 0, 10, 16], "texture": "#0"},
"east": {"uv": [6, 0, 10, 16], "texture": "#0"},

View file

@ -139,7 +139,6 @@
"name": "Axis",
"from": [6, 6, 6],
"to": [10, 10, 16],
"shade": false,
"rotation": {"angle": 22.5, "axis": "z", "origin": [8, 8, 8]},
"faces": {
"north": {"uv": [6, 6, 10, 10], "rotation": 180, "texture": "#1_1"},

View file

@ -14,7 +14,6 @@
"name": "Axis",
"from": [6, 0, 6],
"to": [10, 16, 10],
"shade": false,
"faces": {
"north": {"uv": [6, 0, 10, 16], "texture": "#axis"},
"east": {"uv": [6, 0, 10, 16], "texture": "#axis"},

View file

@ -185,7 +185,6 @@
"name": "Axis",
"from": [6, 0, 6],
"to": [10, 16, 10],
"shade": false,
"faces": {
"north": {"uv": [6, 0, 10, 16], "texture": "#0"},
"east": {"uv": [6, 0, 10, 16], "texture": "#0"},

View file

@ -27,7 +27,6 @@
"name": "Axis",
"from": [6, 6, 0],
"to": [10, 10, 16],
"shade": false,
"faces": {
"north": {"uv": [6, 6, 10, 10], "rotation": 180, "texture": "#1_1"},
"east": {"uv": [6, 0, 10, 16], "rotation": 90, "texture": "#1_0"},

View file

@ -36,7 +36,6 @@
"name": "Axis",
"from": [6, 0, 6],
"to": [10, 16, 10],
"shade": false,
"faces": {
"north": {"uv": [6, 0, 10, 16], "texture": "#0"},
"east": {"uv": [6, 0, 10, 16], "texture": "#0"},

View file

@ -25,7 +25,6 @@
"name": "Axis",
"from": [6, 0, 6],
"to": [10, 16, 10],
"shade": false,
"faces": {
"north": {"uv": [6, 0, 10, 16], "rotation": 180, "texture": "#0"},
"east": {"uv": [6, 0, 10, 16], "rotation": 180, "texture": "#0"},

View file

@ -36,7 +36,6 @@
"name": "Axis",
"from": [6, 0, 6],
"to": [10, 16, 10],
"shade": false,
"faces": {
"north": {"uv": [6, 0, 10, 16], "texture": "#0"},
"east": {"uv": [6, 0, 10, 16], "texture": "#0"},

View file

@ -11,7 +11,6 @@
"name": "Axis",
"from": [6, 0, 6],
"to": [10, 5, 10],
"shade": false,
"faces": {
"north": {"uv": [6, 0, 10, 5], "rotation": 180, "texture": "#0"},
"east": {"uv": [6, 0, 10, 5], "rotation": 180, "texture": "#0"},

View file

@ -13,7 +13,6 @@
"name": "Axis",
"from": [6, 6, 11],
"to": [10, 10, 16],
"shade": false,
"faces": {
"east": {"uv": [6, 0, 10, 5], "rotation": 270, "texture": "#0"},
"south": {"uv": [6, 6, 10, 10], "texture": "#1"},

View file

@ -27,7 +27,6 @@
"name": "Axis",
"from": [6, 0, 6],
"to": [10, 16, 10],
"shade": false,
"faces": {
"north": {"uv": [6, 0, 10, 16], "texture": "#0"},
"east": {"uv": [6, 0, 10, 16], "texture": "#0"},

View file

@ -14,7 +14,6 @@
"name": "Axle",
"from": [6, 6, 0],
"to": [10, 10, 4],
"shade": false,
"faces": {
"north": {"uv": [6, 6, 10, 10], "texture": "#0"},
"east": {"uv": [6, 12, 10, 16], "rotation": 90, "texture": "#1"},

View file

@ -17,7 +17,6 @@
"name": "Axle",
"from": [6, 6, 0],
"to": [10, 10, 4],
"shade": false,
"faces": {
"north": {"uv": [6, 6, 10, 10], "texture": "#0"},
"east": {"uv": [6, 12, 10, 16], "rotation": 90, "texture": "#1"},

View file

@ -11,7 +11,6 @@
"name": "MixerCenter",
"from": [7, -4.5, 7],
"to": [9, 7.5, 9],
"shade": false,
"rotation": {"angle": 0, "axis": "y", "origin": [8, 7, 8]},
"faces": {
"north": {"uv": [0, 12, 12, 14], "rotation": 90, "texture": "#6"},

View file

@ -121,7 +121,6 @@
"name": "MixerCenter",
"from": [7, -4.5, 7],
"to": [9, 7.5, 9],
"shade": false,
"rotation": {"angle": 22.5, "axis": "y", "origin": [8, 7, 8]},
"faces": {
"north": {"uv": [0, 12, 12, 14], "rotation": 90, "texture": "#6"},

View file

@ -94,7 +94,6 @@
"name": "Axis",
"from": [6, 0, 6],
"to": [10, 8, 10],
"shade": false,
"faces": {
"north": {"uv": [6, 8, 10, 16], "rotation": 180, "texture": "#1_0"},
"east": {"uv": [6, 8, 10, 16], "rotation": 180, "texture": "#1_0"},

View file

@ -11,7 +11,6 @@
"name": "Axis",
"from": [ 6.0, 0.0, 6.0 ],
"to": [ 10.0, 16.0, 10.0 ],
"shade": false,
"faces": {
"north": { "texture": "#0", "uv": [ 6.0, 0.0, 10.0, 16.0 ] },
"east": { "texture": "#0", "uv": [ 6.0, 0.0, 10.0, 16.0 ] },

View file

@ -11,7 +11,6 @@
"name": "Axis",
"from": [6, 6, 8],
"to": [10, 10, 16],
"shade": false,
"faces": {
"north": {"uv": [6, 6, 10, 10], "rotation": 180, "texture": "#1"},
"east": {"uv": [6, 0, 10, 8], "rotation": 270, "texture": "#0"},

View file

@ -15,7 +15,6 @@
"name": "Axis",
"from": [6, 0, 6],
"to": [10, 7, 10],
"shade": false,
"faces": {
"north": {"uv": [6, 9, 10, 16], "texture": "#0"},
"east": {"uv": [6, 9, 10, 16], "texture": "#0"},

View file

@ -14,7 +14,6 @@
"name": "Axis",
"from": [6, 0, 6],
"to": [10, 16, 10],
"shade": false,
"faces": {
"north": {"uv": [6, 0, 10, 16], "texture": "#axis"},
"east": {"uv": [6, 0, 10, 16], "texture": "#axis"},

View file

@ -13,7 +13,6 @@
"name": "Axis",
"from": [6, 0, 6],
"to": [10, 16, 10],
"shade": false,
"faces": {
"north": {"uv": [6, 0, 10, 16], "texture": "#0"},
"east": {"uv": [6, 0, 10, 16], "texture": "#0"},

View file

@ -13,7 +13,6 @@
"name": "Axis",
"from": [6, 0, 6],
"to": [10, 16, 10],
"shade": false,
"faces": {
"north": {"uv": [6, 0, 10, 16], "texture": "#0"},
"east": {"uv": [6, 0, 10, 16], "texture": "#0"},