diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillMovementBehaviour.java index 5ebac5064..34ab5045f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillMovementBehaviour.java @@ -3,11 +3,12 @@ package com.simibubi.create.content.contraptions.components.actors; import javax.annotation.Nullable; import com.jozufozu.flywheel.backend.Backend; -import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; @@ -34,10 +35,10 @@ public class DrillMovementBehaviour extends BlockBreakingMovementBehaviour { @Override @OnlyIn(value = Dist.CLIENT) - public void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, - IRenderTypeBuffer buffer) { + public void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld, + ContraptionMatrices matrices, IRenderTypeBuffer buffer) { if (!Backend.canUseInstancing()) - DrillRenderer.renderInContraption(context, ms, msLocal, buffer); + DrillRenderer.renderInContraption(context, renderWorld, matrices, buffer); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillRenderer.java index 3734c3509..df1e668d9 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillRenderer.java @@ -5,12 +5,15 @@ import com.simibubi.create.AllBlockPartials; import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; import com.simibubi.create.foundation.render.PartialBufferer; import com.simibubi.create.foundation.render.SuperByteBuffer; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.MatrixStacker; import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; @@ -29,9 +32,8 @@ public class DrillRenderer extends KineticTileEntityRenderer { return PartialBufferer.getFacing(AllBlockPartials.DRILL_HEAD, te.getBlockState()); } - public static void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, - IRenderTypeBuffer buffer) { - MatrixStack[] matrixStacks = new MatrixStack[]{ms, msLocal}; + public static void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld, + ContraptionMatrices matrices, IRenderTypeBuffer buffer) { BlockState state = context.state; SuperByteBuffer superBuffer = PartialBufferer.get(AllBlockPartials.DRILL_HEAD, state); Direction facing = state.get(DrillBlock.FACING); @@ -42,18 +44,22 @@ public class DrillRenderer extends KineticTileEntityRenderer { float time = AnimationTickHolder.getRenderTime() / 20; float angle = (float) (((time * speed) % 360)); - for (MatrixStack m : matrixStacks) - MatrixStacker.of(m) - .centre() - .rotateY(AngleHelper.horizontalAngle(facing)) - .rotateX(AngleHelper.verticalAngle(facing)) - .rotateZ(angle) - .unCentre(); + MatrixStack m = matrices.contraptionStack; + m.push(); + MatrixStacker.of(m) + .centre() + .rotateY(AngleHelper.horizontalAngle(facing)) + .rotateX(AngleHelper.verticalAngle(facing)) + .rotateZ(angle) + .unCentre(); superBuffer - .light(msLocal.peek() - .getModel()) - .renderInto(ms, buffer.getBuffer(RenderType.getSolid())); + .transform(m) + .light(matrices.entityMatrix, + ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) + .renderInto(matrices.entityStack, buffer.getBuffer(RenderType.getSolid())); + + m.pop(); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterMovementBehaviour.java index 88433f8e8..a0a993c24 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterMovementBehaviour.java @@ -7,13 +7,14 @@ import javax.annotation.Nullable; import org.apache.commons.lang3.mutable.MutableBoolean; import com.jozufozu.flywheel.backend.Backend; -import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; import com.simibubi.create.foundation.utility.BlockHelper; import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; @@ -52,10 +53,10 @@ public class HarvesterMovementBehaviour extends MovementBehaviour { } @Override - public void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, - IRenderTypeBuffer buffers) { + public void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld, + ContraptionMatrices matrices, IRenderTypeBuffer buffers) { if (!Backend.canUseInstancing()) - HarvesterRenderer.renderInContraption(context, ms, msLocal, buffers); + HarvesterRenderer.renderInContraption(context, renderWorld, matrices, buffers); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterRenderer.java index 44cf29765..3ab34b532 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterRenderer.java @@ -5,6 +5,7 @@ import static net.minecraft.state.properties.BlockStateProperties.HORIZONTAL_FAC import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; import com.simibubi.create.foundation.render.PartialBufferer; import com.simibubi.create.foundation.render.SuperByteBuffer; @@ -12,6 +13,7 @@ import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; @@ -39,8 +41,8 @@ public class HarvesterRenderer extends SafeTileEntityRenderer sbb.light(msLocal.peek() - .getModel(), ContraptionRenderDispatcher.getLightOnContraption(context)) - .renderInto(ms, vb), ms, msLocal); + render(blockState, progress, lit, sbb -> sbb.transform(matrices.contraptionStack) + .disableDiffuseTransform() + .light(matrices.entityMatrix, + ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) + .renderInto(matrices.entityStack, vb), matrices.contraptionStack); } private static void render(BlockState blockState, float progress, boolean lit, - Consumer drawCallback, MatrixStack... matrixStacks) { - for (MatrixStack ms : matrixStacks) - ms.push(); + Consumer drawCallback, MatrixStack ms) { + ms.push(); SuperByteBuffer middle = PartialBufferer.get(getMiddleForState(blockState, lit), blockState); SuperByteBuffer top = PartialBufferer.get(getTopForState(blockState), blockState); Direction facing = blockState.get(PortableStorageInterfaceBlock.FACING); - for (MatrixStack ms : matrixStacks) - MatrixStacker.of(ms) - .centre() - .rotateY(AngleHelper.horizontalAngle(facing)) - .rotateX(facing == Direction.UP ? 0 : facing == Direction.DOWN ? 180 : 90) - .unCentre(); + MatrixStacker.of(ms) + .centre() + .rotateY(AngleHelper.horizontalAngle(facing)) + .rotateX(facing == Direction.UP ? 0 : facing == Direction.DOWN ? 180 : 90) + .unCentre(); - for (MatrixStack ms : matrixStacks) { - ms.translate(0, progress / 2f, 0); - ms.push(); - ms.translate(0, 6 / 16f, 0); - } + ms.translate(0, progress / 2f, 0); + ms.push(); + ms.translate(0, 6 / 16f, 0); drawCallback.accept(middle); - for (MatrixStack ms : matrixStacks) { - ms.pop(); - ms.translate(0, progress / 2f, 0); - } + ms.pop(); + ms.translate(0, progress / 2f, 0); drawCallback.accept(top); - for (MatrixStack ms : matrixStacks) - ms.pop(); + ms.pop(); } protected static PortableStorageInterfaceTileEntity getTargetPSI(MovementContext context) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/SawMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/SawMovementBehaviour.java index e8ec8a692..375445b5f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/SawMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/SawMovementBehaviour.java @@ -1,12 +1,13 @@ package com.simibubi.create.content.contraptions.components.actors; -import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.content.contraptions.components.saw.SawBlock; import com.simibubi.create.content.contraptions.components.saw.SawRenderer; import com.simibubi.create.content.contraptions.components.saw.SawTileEntity; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; import com.simibubi.create.foundation.utility.TreeCutter; import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; @@ -75,9 +76,9 @@ public class SawMovementBehaviour extends BlockBreakingMovementBehaviour { @Override @OnlyIn(value = Dist.CLIENT) - public void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, - IRenderTypeBuffer buffer) { - SawRenderer.renderInContraption(context, ms, msLocal, buffer); + public void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld, + ContraptionMatrices matrices, IRenderTypeBuffer buffer) { + SawRenderer.renderInContraption(context, renderWorld, matrices, buffer); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerMovementBehaviour.java index e7d38b5e1..a8d81c209 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerMovementBehaviour.java @@ -8,7 +8,6 @@ import javax.annotation.Nullable; import org.apache.commons.lang3.tuple.Pair; import com.jozufozu.flywheel.backend.Backend; -import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; import com.simibubi.create.AllTags.AllBlockTags; @@ -18,6 +17,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Mov import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; import com.simibubi.create.content.logistics.item.filter.FilterItem; import com.simibubi.create.content.schematics.ItemRequirement; import com.simibubi.create.content.schematics.SchematicWorld; @@ -27,6 +27,7 @@ import com.simibubi.create.foundation.item.ItemHelper.ExtractionCountMode; import com.simibubi.create.foundation.utility.BlockHelper; import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.NBTProcessors; +import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; @@ -254,10 +255,10 @@ public class DeployerMovementBehaviour extends MovementBehaviour { } @Override - public void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, - IRenderTypeBuffer buffers) { + public void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld, + ContraptionMatrices matrices, IRenderTypeBuffer buffers) { if (!Backend.canUseInstancing()) - DeployerRenderer.renderInContraption(context, ms, msLocal, buffers); + DeployerRenderer.renderInContraption(context, renderWorld, matrices, buffers); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerRenderer.java index 75cd6f14b..ccac8329a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerRenderer.java @@ -12,6 +12,7 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.content.contraptions.components.deployer.DeployerTileEntity.Mode; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; import com.simibubi.create.foundation.render.PartialBufferer; import com.simibubi.create.foundation.render.SuperByteBuffer; @@ -21,6 +22,7 @@ import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; import net.minecraft.block.BlockState; import net.minecraft.client.Minecraft; @@ -35,7 +37,6 @@ import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; -import net.minecraft.util.math.vector.Matrix4f; import net.minecraft.util.math.vector.Vector3d; import net.minecraft.util.math.vector.Vector3f; import net.minecraft.world.World; @@ -154,9 +155,8 @@ public class DeployerRenderer extends SafeTileEntityRenderer return buffer; } - public static void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, - IRenderTypeBuffer buffer) { - MatrixStack[] matrixStacks = new MatrixStack[]{ms, msLocal}; + public static void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld, + ContraptionMatrices matrices, IRenderTypeBuffer buffer) { IVertexBuilder builder = buffer.getBuffer(RenderType.getSolid()); BlockState blockState = context.state; BlockPos pos = BlockPos.ZERO; @@ -166,8 +166,6 @@ public class DeployerRenderer extends SafeTileEntityRenderer SuperByteBuffer pole = PartialBufferer.get(AllBlockPartials.DEPLOYER_POLE, blockState); SuperByteBuffer hand = PartialBufferer.get(handPose, blockState); - pole = transform(world, pole, blockState, pos, true); - hand = transform(world, hand, blockState, pos, false); double factor; if (context.contraption.stalled || context.position == null || context.data.contains("StationaryTimer")) { @@ -183,14 +181,21 @@ public class DeployerRenderer extends SafeTileEntityRenderer Vector3d offset = Vector3d.of(blockState.get(FACING) .getDirectionVec()).scale(factor); - Matrix4f lighting = msLocal.peek() - .getModel(); - for (MatrixStack m : matrixStacks) - m.translate(offset.x, offset.y, offset.z); - pole.light(lighting, ContraptionRenderDispatcher.getLightOnContraption(context)) - .renderInto(ms, builder); - hand.light(lighting, ContraptionRenderDispatcher.getLightOnContraption(context)) - .renderInto(ms, builder); + MatrixStack m = matrices.contraptionStack; + m.push(); + m.translate(offset.x, offset.y, offset.z); + + pole.transform(m); + hand.transform(m); + pole = transform(world, pole, blockState, pos, true); + hand = transform(world, hand, blockState, pos, false); + + pole.light(matrices.entityMatrix, ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) + .renderInto(matrices.entityStack, builder); + hand.light(matrices.entityMatrix, ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) + .renderInto(matrices.entityStack, builder); + + m.pop(); } static PartialModel getHandPose(DeployerTileEntity.Mode mode) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawRenderer.java index 81a646166..bba81950a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawRenderer.java @@ -10,6 +10,7 @@ import com.simibubi.create.CreateClient; import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; import com.simibubi.create.foundation.render.PartialBufferer; import com.simibubi.create.foundation.render.SuperByteBuffer; @@ -18,6 +19,7 @@ import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.MatrixStacker; import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; import net.minecraft.block.BlockState; import net.minecraft.client.Minecraft; @@ -151,11 +153,9 @@ public class SawRenderer extends SafeTileEntityRenderer { return KineticTileEntityRenderer.shaft(KineticTileEntityRenderer.getRotationAxisOf(te)); } - public static void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, - IRenderTypeBuffer buffer) { - MatrixStack[] matrixStacks = new MatrixStack[] { ms, msLocal }; + public static void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld, + ContraptionMatrices matrices, IRenderTypeBuffer buffer) { BlockState state = context.state; - SuperByteBuffer superBuffer; Direction facing = state.get(SawBlock.FACING); Vector3d facingVec = Vector3d.of(context.state.get(SawBlock.FACING) @@ -171,6 +171,7 @@ public class SawRenderer extends SafeTileEntityRenderer { boolean shouldAnimate = (context.contraption.stalled && horizontal) || (!context.contraption.stalled && !backwards && moving); + SuperByteBuffer superBuffer; if (SawBlock.isHorizontal(state)) { if (shouldAnimate) superBuffer = PartialBufferer.get(AllBlockPartials.SAW_BLADE_HORIZONTAL_ACTIVE, state); @@ -183,22 +184,26 @@ public class SawRenderer extends SafeTileEntityRenderer { superBuffer = PartialBufferer.get(AllBlockPartials.SAW_BLADE_VERTICAL_INACTIVE, state); } - for (MatrixStack m : matrixStacks) { + MatrixStack m = matrices.contraptionStack; + m.push(); + MatrixStacker.of(m) + .centre() + .rotateY(AngleHelper.horizontalAngle(facing)) + .rotateX(AngleHelper.verticalAngle(facing)); + if (!SawBlock.isHorizontal(state)) MatrixStacker.of(m) - .centre() - .rotateY(AngleHelper.horizontalAngle(facing)) - .rotateX(AngleHelper.verticalAngle(facing)); - if (!SawBlock.isHorizontal(state)) - MatrixStacker.of(m) - .rotateZ(state.get(SawBlock.AXIS_ALONG_FIRST_COORDINATE) ? 0 : 90); - MatrixStacker.of(m) - .unCentre(); - } + .rotateZ(state.get(SawBlock.AXIS_ALONG_FIRST_COORDINATE) ? 0 : 90); + MatrixStacker.of(m) + .unCentre(); superBuffer - .light(msLocal.peek() - .getModel(), ContraptionRenderDispatcher.getLightOnContraption(context)) - .renderInto(ms, buffer.getBuffer(RenderType.getCutoutMipped())); + .transform(m) + .disableDiffuseTransform() + .light(matrices.entityMatrix, + ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) + .renderInto(matrices.entityStack, buffer.getBuffer(RenderType.getCutoutMipped())); + + m.pop(); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionEntityRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionEntityRenderer.java index 271319b91..8d8ed3b62 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionEntityRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionEntityRenderer.java @@ -1,20 +1,19 @@ package com.simibubi.create.content.contraptions.components.structureMovement; import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; -import com.simibubi.create.foundation.utility.AnimationTickHolder; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.culling.ClippingHelper; import net.minecraft.client.renderer.entity.EntityRenderer; import net.minecraft.client.renderer.entity.EntityRendererManager; import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.MathHelper; public class ContraptionEntityRenderer extends EntityRenderer { - public ContraptionEntityRenderer(EntityRendererManager p_i46179_1_) { - super(p_i46179_1_); + public ContraptionEntityRenderer(EntityRendererManager manager) { + super(manager); } @Override @@ -23,42 +22,26 @@ public class ContraptionEntityRenderer exte } @Override - public boolean shouldRender(C entity, ClippingHelper clippingHelper, double p_225626_3_, double p_225626_5_, - double p_225626_7_) { + public boolean shouldRender(C entity, ClippingHelper clippingHelper, double cameraX, double cameraY, + double cameraZ) { if (entity.getContraption() == null) return false; if (!entity.isAlive()) return false; - return super.shouldRender(entity, clippingHelper, p_225626_3_, p_225626_5_, p_225626_7_); + return super.shouldRender(entity, clippingHelper, cameraX, cameraY, cameraZ); } - + @Override public void render(C entity, float yaw, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffers, int overlay) { super.render(entity, yaw, partialTicks, ms, buffers, overlay); - // Keep a copy of the transforms in order to determine correct lighting - MatrixStack msLocal = translateTo(entity, AnimationTickHolder.getPartialTicks()); - MatrixStack[] matrixStacks = new MatrixStack[] { ms, msLocal }; - - ms.push(); - entity.doLocalTransforms(partialTicks, matrixStacks); + ContraptionMatrices matrices = new ContraptionMatrices(ms, entity); Contraption contraption = entity.getContraption(); if (contraption != null) { - ContraptionRenderDispatcher.render(entity, ms, buffers, msLocal, contraption); + ContraptionRenderDispatcher.render(entity, contraption, matrices, buffers); } - ms.pop(); - - } - - protected MatrixStack translateTo(AbstractContraptionEntity entity, float pt) { - MatrixStack matrixStack = new MatrixStack(); - double x = MathHelper.lerp(pt, entity.lastTickPosX, entity.getX()); - double y = MathHelper.lerp(pt, entity.lastTickPosY, entity.getY()); - double z = MathHelper.lerp(pt, entity.lastTickPosZ, entity.getZ()); - matrixStack.translate(x, y, z); - return matrixStack; } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovementBehaviour.java index 9b17ea7f5..5c33522eb 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovementBehaviour.java @@ -2,9 +2,10 @@ package com.simibubi.create.content.contraptions.components.structureMovement; import javax.annotation.Nullable; -import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; +import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.entity.item.ItemEntity; @@ -60,8 +61,8 @@ public abstract class MovementBehaviour { } @OnlyIn(Dist.CLIENT) - public void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, - IRenderTypeBuffer buffer) {} + public void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld, + ContraptionMatrices matrices, IRenderTypeBuffer buffer) {} @OnlyIn(Dist.CLIENT) @Nullable diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/StabilizedBearingMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/StabilizedBearingMovementBehaviour.java index 91b0cf846..8afaa8bcc 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/StabilizedBearingMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/StabilizedBearingMovementBehaviour.java @@ -4,7 +4,6 @@ import javax.annotation.Nullable; import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.core.PartialModel; -import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity; @@ -13,10 +12,12 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Mov import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; import com.simibubi.create.foundation.render.PartialBufferer; import com.simibubi.create.foundation.render.SuperByteBuffer; import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.RenderType; @@ -31,8 +32,8 @@ public class StabilizedBearingMovementBehaviour extends MovementBehaviour { @Override @OnlyIn(Dist.CLIENT) - public void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, - IRenderTypeBuffer buffer) { + public void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld, + ContraptionMatrices matrices, IRenderTypeBuffer buffer) { if (Backend.canUseInstancing()) return; Direction facing = context.state.get(BlockStateProperties.FACING); @@ -52,12 +53,14 @@ public class StabilizedBearingMovementBehaviour extends MovementBehaviour { orientation = rotation; + superBuffer.transform(matrices.contraptionStack); superBuffer.rotateCentered(orientation); // render - superBuffer.light(msLocal.peek() - .getModel(), ContraptionRenderDispatcher.getLightOnContraption(context)); - superBuffer.renderInto(ms, buffer.getBuffer(RenderType.getSolid())); + superBuffer + .light(matrices.entityMatrix, + ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) + .renderInto(matrices.entityStack, buffer.getBuffer(RenderType.getSolid())); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionMatrices.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionMatrices.java new file mode 100644 index 000000000..d6e82d17d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionMatrices.java @@ -0,0 +1,65 @@ +package com.simibubi.create.content.contraptions.components.structureMovement.render; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; +import com.simibubi.create.foundation.utility.AnimationTickHolder; + +import net.minecraft.entity.Entity; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.vector.Matrix3f; +import net.minecraft.util.math.vector.Matrix4f; + +public class ContraptionMatrices { + public final MatrixStack entityStack; + public final MatrixStack contraptionStack; + public final Matrix4f entityMatrix; + + public ContraptionMatrices(MatrixStack entityStack, AbstractContraptionEntity entity) { + this.entityStack = entityStack; + this.contraptionStack = new MatrixStack(); + float partialTicks = AnimationTickHolder.getPartialTicks(); + entity.doLocalTransforms(partialTicks, new MatrixStack[] { this.contraptionStack }); + entityMatrix = translateTo(entity, partialTicks); + } + + public MatrixStack getFinalStack() { + MatrixStack finalStack = new MatrixStack(); + transform(finalStack, entityStack); + transform(finalStack, contraptionStack); + return finalStack; + } + + public Matrix4f getFinalModel() { + Matrix4f finalModel = entityStack.peek().getModel().copy(); + finalModel.multiply(contraptionStack.peek().getModel()); + return finalModel; + } + + public Matrix3f getFinalNormal() { + Matrix3f finalNormal = entityStack.peek().getNormal().copy(); + finalNormal.multiply(contraptionStack.peek().getNormal()); + return finalNormal; + } + + public Matrix4f getFinalLight() { + Matrix4f lightTransform = entityMatrix.copy(); + lightTransform.multiply(contraptionStack.peek().getModel()); + return lightTransform; + } + + public static Matrix4f translateTo(Entity entity, float partialTicks) { + double x = MathHelper.lerp(partialTicks, entity.lastTickPosX, entity.getX()); + double y = MathHelper.lerp(partialTicks, entity.lastTickPosY, entity.getY()); + double z = MathHelper.lerp(partialTicks, entity.lastTickPosZ, entity.getZ()); + return Matrix4f.translate((float) x, (float) y, (float) z); + } + + public static void transform(MatrixStack ms, MatrixStack transform) { + ms.peek().getModel() + .multiply(transform.peek() + .getModel()); + ms.peek().getNormal() + .multiply(transform.peek() + .getNormal()); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderDispatcher.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderDispatcher.java index d98369b87..8f0a922e3 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderDispatcher.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderDispatcher.java @@ -1,12 +1,12 @@ package com.simibubi.create.content.contraptions.components.structureMovement.render; -import static org.lwjgl.opengl.GL13.GL_QUADS; +import static org.lwjgl.opengl.GL11.GL_QUADS; +import static org.lwjgl.opengl.GL11.glDisable; +import static org.lwjgl.opengl.GL11.glEnable; +import static org.lwjgl.opengl.GL12.GL_TEXTURE_3D; import static org.lwjgl.opengl.GL13.GL_TEXTURE0; import static org.lwjgl.opengl.GL13.GL_TEXTURE4; -import static org.lwjgl.opengl.GL13.GL_TEXTURE_3D; import static org.lwjgl.opengl.GL13.glActiveTexture; -import static org.lwjgl.opengl.GL13.glDisable; -import static org.lwjgl.opengl.GL13.glEnable; import java.util.List; import java.util.Random; @@ -36,7 +36,7 @@ import net.minecraft.block.BlockState; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.ActiveRenderInfo; import net.minecraft.client.renderer.BlockModelRenderer; -import net.minecraft.client.renderer.BlockRendererDispatcher; +import net.minecraft.client.renderer.BlockModelShapes; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.IRenderTypeBuffer; @@ -44,7 +44,6 @@ import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderTypeLookup; import net.minecraft.client.renderer.WorldRenderer; -import net.minecraft.client.renderer.model.IBakedModel; import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.client.world.ClientWorld; @@ -57,25 +56,35 @@ import net.minecraftforge.client.ForgeHooksClient; import net.minecraftforge.client.model.data.EmptyModelData; public class ContraptionRenderDispatcher { - public static final Int2ObjectMap renderers = new Int2ObjectOpenHashMap<>(); + private static final BlockModelRenderer MODEL_RENDERER = new BlockModelRenderer(Minecraft.getInstance().getBlockColors()); + private static final BlockModelShapes BLOCK_MODELS = Minecraft.getInstance().getModelManager().getBlockModelShapes(); + private static int worldHolderRefreshCounter; + + public static final Int2ObjectMap RENDERERS = new Int2ObjectOpenHashMap<>(); + public static final Int2ObjectMap WORLD_HOLDERS = new Int2ObjectOpenHashMap<>(); public static final Compartment> CONTRAPTION = new Compartment<>(); - protected static PlacementSimulationWorld renderWorld; public static void tick() { if (Minecraft.getInstance().isGamePaused()) return; - for (RenderedContraption contraption : renderers.values()) { + for (RenderedContraption contraption : RENDERERS.values()) { contraption.getLighter().tick(contraption); contraption.kinetics.tick(); } + + worldHolderRefreshCounter++; + if (worldHolderRefreshCounter >= 20) { + removeDeadHolders(); + worldHolderRefreshCounter = 0; + } } public static void beginFrame(ClientWorld world, MatrixStack stack, ActiveRenderInfo info, GameRenderer gameRenderer, LightTexture lightTexture) { double camX = info.getProjectedView().x; double camY = info.getProjectedView().y; double camZ = info.getProjectedView().z; - for (RenderedContraption renderer : renderers.values()) { + for (RenderedContraption renderer : RENDERERS.values()) { renderer.beginFrame(info, camX, camY, camZ); } } @@ -83,7 +92,7 @@ public class ContraptionRenderDispatcher { public static void renderLayer(ClientWorld world, RenderType layer, Matrix4f viewProjection, double camX, double camY, double camZ) { removeDeadContraptions(); - if (renderers.isEmpty()) return; + if (RENDERERS.isEmpty()) return; layer.startDrawing(); glEnable(GL_TEXTURE_3D); @@ -96,13 +105,13 @@ public class ContraptionRenderDispatcher { structureShader.uploadViewProjection(viewProjection); structureShader.uploadCameraPos(camX, camY, camZ); - for (RenderedContraption renderer : renderers.values()) { + for (RenderedContraption renderer : RENDERERS.values()) { renderer.doRenderLayer(layer, structureShader); } } if (Backend.canUseInstancing()) { - for (RenderedContraption renderer : renderers.values()) { + for (RenderedContraption renderer : RENDERERS.values()) { renderer.kinetics.render(layer, viewProjection, camX, camY, camZ, renderer::setup); renderer.teardown(); } @@ -113,70 +122,81 @@ public class ContraptionRenderDispatcher { glActiveTexture(GL_TEXTURE0); } + public static void render(AbstractContraptionEntity entity, Contraption contraption, + ContraptionMatrices matrices, IRenderTypeBuffer buffers) { + World world = entity.world; + if (Backend.canUseVBOs() && Backend.isFlywheelWorld(world)) { + RenderedContraption renderer = getRenderer(world, contraption); + PlacementSimulationWorld renderWorld = renderer.renderWorld; + + ContraptionRenderDispatcher.renderDynamic(world, renderWorld, contraption, matrices, buffers); + } else { + ContraptionWorldHolder holder = getWorldHolder(world, contraption); + PlacementSimulationWorld renderWorld = holder.renderWorld; + + ContraptionRenderDispatcher.renderDynamic(world, renderWorld, contraption, matrices, buffers); + ContraptionRenderDispatcher.renderStructure(world, renderWorld, contraption, matrices, buffers); + } + } + private static RenderedContraption getRenderer(World world, Contraption c) { int entityId = c.entity.getEntityId(); - RenderedContraption contraption = renderers.get(entityId); + RenderedContraption contraption = RENDERERS.get(entityId); if (contraption == null) { - contraption = new RenderedContraption(world, c); - renderers.put(entityId, contraption); + PlacementSimulationWorld renderWorld = setupRenderWorld(world, c); + contraption = new RenderedContraption(world, renderWorld, c); + RENDERERS.put(entityId, contraption); } return contraption; } - public static void render(AbstractContraptionEntity entity, MatrixStack ms, IRenderTypeBuffer buffers, - MatrixStack msLocal, Contraption contraption) { - if (Backend.canUseVBOs() && Backend.isFlywheelWorld(entity.world)) { - ContraptionRenderDispatcher.renderDynamic(entity.world, contraption, ms, msLocal, buffers); - } else { - ContraptionRenderDispatcher.renderDynamic(entity.world, contraption, ms, msLocal, buffers); - ContraptionRenderDispatcher.renderStructure(entity.world, contraption, ms, msLocal, buffers); + private static ContraptionWorldHolder getWorldHolder(World world, Contraption c) { + int entityId = c.entity.getEntityId(); + ContraptionWorldHolder holder = WORLD_HOLDERS.get(entityId); + + if (holder == null) { + PlacementSimulationWorld renderWorld = setupRenderWorld(world, c); + holder = new ContraptionWorldHolder(c, renderWorld); + WORLD_HOLDERS.put(entityId, holder); } + + return holder; } - public static void renderStructure(World world, Contraption c, MatrixStack ms, MatrixStack msLocal, - IRenderTypeBuffer buffer) { - SuperByteBufferCache bufferCache = CreateClient.bufferCache; - List blockLayers = RenderType.getBlockLayers(); + public static PlacementSimulationWorld setupRenderWorld(World world, Contraption c) { + PlacementSimulationWorld renderWorld = new PlacementSimulationWorld(world); - buffer.getBuffer(RenderType.getSolid()); - for (int i = 0; i < blockLayers.size(); i++) { - RenderType layer = blockLayers.get(i); - Pair key = Pair.of(c, i); - SuperByteBuffer contraptionBuffer = bufferCache.get(CONTRAPTION, key, () -> buildStructureBuffer(c, layer)); - if (contraptionBuffer.isEmpty()) - continue; - Matrix4f model = msLocal.peek() - .getModel(); - contraptionBuffer.light(model) - .renderInto(ms, buffer.getBuffer(layer)); - } + renderWorld.setTileEntities(c.presentTileEntities.values()); + + for (Template.BlockInfo info : c.getBlocks() + .values()) + // Skip individual lighting updates to prevent lag with large contraptions + renderWorld.setBlockState(info.pos, info.state, 128); + + renderWorld.updateLightSources(); + renderWorld.lighter.tick(Integer.MAX_VALUE, false, false); + + return renderWorld; } - public static void renderDynamic(World world, Contraption c, MatrixStack ms, MatrixStack msLocal, - IRenderTypeBuffer buffer) { - renderTileEntities(world, c, ms, msLocal, buffer); + public static void renderDynamic(World world, PlacementSimulationWorld renderWorld, Contraption c, + ContraptionMatrices matrices, IRenderTypeBuffer buffer) { + renderTileEntities(world, renderWorld, c, matrices, buffer); if (buffer instanceof IRenderTypeBuffer.Impl) ((IRenderTypeBuffer.Impl) buffer).draw(); - renderActors(world, c, ms, msLocal, buffer); + renderActors(world, renderWorld, c, matrices, buffer); } - public static void renderTileEntities(World world, Contraption c, MatrixStack ms, MatrixStack msLocal, - IRenderTypeBuffer buffer) { - PlacementSimulationWorld renderWorld = null; - if (Backend.canUseVBOs() && Backend.isFlywheelWorld(world)) { - RenderedContraption renderer = getRenderer(world, c); - - renderWorld = renderer.renderWorld; - } - TileEntityRenderHelper.renderTileEntities(world, renderWorld, c.specialRenderedTileEntities, ms, msLocal, buffer); - + public static void renderTileEntities(World world, PlacementSimulationWorld renderWorld, Contraption c, + ContraptionMatrices matrices, IRenderTypeBuffer buffer) { + TileEntityRenderHelper.renderTileEntities(world, renderWorld, c.specialRenderedTileEntities, + matrices.getFinalStack(), matrices.getFinalLight(), buffer); } - protected static void renderActors(World world, Contraption c, MatrixStack ms, MatrixStack msLocal, - IRenderTypeBuffer buffer) { - MatrixStack[] matrixStacks = new MatrixStack[]{ms, msLocal}; + protected static void renderActors(World world, PlacementSimulationWorld renderWorld, Contraption c, + ContraptionMatrices matrices, IRenderTypeBuffer buffer) { for (Pair actor : c.getActors()) { MovementContext context = actor.getRight(); if (context == null) @@ -184,123 +204,108 @@ public class ContraptionRenderDispatcher { if (context.world == null) context.world = world; Template.BlockInfo blockInfo = actor.getLeft(); - for (MatrixStack m : matrixStacks) { - m.push(); - MatrixStacker.of(m) - .translate(blockInfo.pos); - } + + MatrixStack m = matrices.contraptionStack; + m.push(); + MatrixStacker.of(m) + .translate(blockInfo.pos); MovementBehaviour movementBehaviour = AllMovementBehaviours.of(blockInfo.state); if (movementBehaviour != null) - movementBehaviour.renderInContraption(context, ms, msLocal, buffer); + movementBehaviour.renderInContraption(context, renderWorld, matrices, buffer); - for (MatrixStack m : matrixStacks) - m.pop(); + m.pop(); } } - private static SuperByteBuffer buildStructureBuffer(Contraption c, RenderType layer) { - BufferBuilder builder = buildStructure(c, layer); + public static void renderStructure(World world, PlacementSimulationWorld renderWorld, Contraption c, + ContraptionMatrices matrices, IRenderTypeBuffer buffer) { + SuperByteBufferCache bufferCache = CreateClient.bufferCache; + List blockLayers = RenderType.getBlockLayers(); + + buffer.getBuffer(RenderType.getSolid()); + for (int i = 0; i < blockLayers.size(); i++) { + RenderType layer = blockLayers.get(i); + Pair key = Pair.of(c, i); + SuperByteBuffer contraptionBuffer = bufferCache.get(CONTRAPTION, key, () -> buildStructureBuffer(renderWorld, c, layer)); + if (contraptionBuffer.isEmpty()) + continue; + contraptionBuffer + .transform(matrices.contraptionStack) + .light(matrices.entityMatrix) + .hybridLight() + .renderInto(matrices.entityStack, buffer.getBuffer(layer)); + } + } + + private static SuperByteBuffer buildStructureBuffer(PlacementSimulationWorld renderWorld, Contraption c, RenderType layer) { + BufferBuilder builder = buildStructure(renderWorld, c, layer); return new SuperByteBuffer(builder); } - public static BufferBuilder buildStructure(Contraption c, RenderType layer) { - if (renderWorld == null || renderWorld.getWorld() != Minecraft.getInstance().world) - renderWorld = new PlacementSimulationWorld(Minecraft.getInstance().world); - - ForgeHooksClient.setRenderLayer(layer); + public static BufferBuilder buildStructure(PlacementSimulationWorld renderWorld, Contraption c, RenderType layer) { MatrixStack ms = new MatrixStack(); - BlockRendererDispatcher dispatcher = Minecraft.getInstance() - .getBlockRendererDispatcher(); - BlockModelRenderer blockRenderer = dispatcher.getBlockModelRenderer(); Random random = new Random(); BufferBuilder builder = new BufferBuilder(DefaultVertexFormats.BLOCK.getIntegerSize()); builder.begin(GL_QUADS, DefaultVertexFormats.BLOCK); - renderWorld.setTileEntities(c.presentTileEntities.values()); + ForgeHooksClient.setRenderLayer(layer); + BlockModelRenderer.enableCache(); for (Template.BlockInfo info : c.getBlocks() - .values()) - renderWorld.setBlockState(info.pos, info.state); - - for (Template.BlockInfo info : c.getBlocks() - .values()) { + .values()) { BlockState state = info.state; - if (state.getRenderType() == BlockRenderType.ENTITYBLOCK_ANIMATED) - continue; - if (!RenderTypeLookup.canRenderInLayer(state, layer)) - continue; + if (state.getRenderType() != BlockRenderType.MODEL) + continue; + if (!RenderTypeLookup.canRenderInLayer(state, layer)) + continue; - IBakedModel originalModel = dispatcher.getModelForState(state); - ms.push(); - ms.translate(info.pos.getX(), info.pos.getY(), info.pos.getZ()); - blockRenderer.renderModel(renderWorld, originalModel, state, info.pos, ms, builder, true, random, 42, - OverlayTexture.DEFAULT_UV, EmptyModelData.INSTANCE); - ms.pop(); - } + BlockPos pos = info.pos; - builder.finishDrawing(); - renderWorld.clear(); - renderWorld = null; - return builder; - } - - public static int getLight(World world, float lx, float ly, float lz) { - BlockPos.Mutable pos = new BlockPos.Mutable(); - float sky = 0, block = 0; - float offset = 1 / 8f; - - for (float zOffset = offset; zOffset >= -offset; zOffset -= 2 * offset) - for (float yOffset = offset; yOffset >= -offset; yOffset -= 2 * offset) - for (float xOffset = offset; xOffset >= -offset; xOffset -= 2 * offset) { - pos.setPos(lx + xOffset, ly + yOffset, lz + zOffset); - sky += world.getLightLevel(LightType.SKY, pos) / 8f; - block += world.getLightLevel(LightType.BLOCK, pos) / 8f; - } - - return ((int) sky) << 20 | ((int) block) << 4; - } - - public static int getLightOnContraption(World world, PlacementSimulationWorld renderWorld, BlockPos pos, BlockPos lightPos) { - int worldLight = WorldRenderer.getLightmapCoordinates(world, lightPos); - - if (renderWorld != null) - return getMaxBlockLight(worldLight, renderWorld.getLightLevel(LightType.BLOCK, pos)); - - return worldLight; - } - - public static int getMaxBlockLight(int packedLight, int blockLightValue) { - int unpackedBlockLight = LightTexture.getBlockLightCoordinates(packedLight); - - if (blockLightValue > unpackedBlockLight) { - packedLight = (packedLight & 0xFFFF0000) | (blockLightValue << 4); - } - - return packedLight; - } - - public static int getLightOnContraption(MovementContext context) { - int entityId = context.contraption.entity.getEntityId(); - - RenderedContraption renderedContraption = renderers.get(entityId); - if (renderedContraption != null) { - return renderedContraption.renderWorld.getLightLevel(LightType.BLOCK, context.localPos); - } else { - return -1; + ms.push(); + ms.translate(pos.getX(), pos.getY(), pos.getZ()); + MODEL_RENDERER.renderModel(renderWorld, BLOCK_MODELS.getModel(state), state, pos, ms, builder, true, + random, 42, OverlayTexture.DEFAULT_UV, EmptyModelData.INSTANCE); + ms.pop(); } + BlockModelRenderer.disableCache(); + ForgeHooksClient.setRenderLayer(null); + + builder.finishDrawing(); + return builder; + } + + public static int getLight(World world, float lx, float ly, float lz) { + BlockPos.Mutable pos = new BlockPos.Mutable(); + float block = 0, sky = 0; + float offset = 1 / 8f; + + for (float zOffset = offset; zOffset >= -offset; zOffset -= 2 * offset) + for (float yOffset = offset; yOffset >= -offset; yOffset -= 2 * offset) + for (float xOffset = offset; xOffset >= -offset; xOffset -= 2 * offset) { + pos.setPos(lx + xOffset, ly + yOffset, lz + zOffset); + block += world.getLightLevel(LightType.BLOCK, pos) / 8f; + sky += world.getLightLevel(LightType.SKY, pos) / 8f; + } + + return LightTexture.pack((int) block, (int) sky); + } + + public static int getContraptionWorldLight(MovementContext context, PlacementSimulationWorld renderWorld) { + return WorldRenderer.getLightmapCoordinates(renderWorld, context.localPos); } public static void invalidateAll() { - for (RenderedContraption renderer : renderers.values()) { + for (RenderedContraption renderer : RENDERERS.values()) { renderer.invalidate(); } - renderers.clear(); + RENDERERS.clear(); + WORLD_HOLDERS.clear(); } public static void removeDeadContraptions() { - renderers.values().removeIf(renderer -> { + RENDERERS.values().removeIf(renderer -> { if (renderer.isDead()) { renderer.invalidate(); return true; @@ -308,4 +313,8 @@ public class ContraptionRenderDispatcher { return false; }); } + + public static void removeDeadHolders() { + WORLD_HOLDERS.values().removeIf(ContraptionWorldHolder::isDead); + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionWorldHolder.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionWorldHolder.java new file mode 100644 index 000000000..4ae414016 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionWorldHolder.java @@ -0,0 +1,22 @@ +package com.simibubi.create.content.contraptions.components.structureMovement.render; + +import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; +import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; + +public class ContraptionWorldHolder { + public final Contraption contraption; + public final PlacementSimulationWorld renderWorld; + + public ContraptionWorldHolder(Contraption contraption, PlacementSimulationWorld renderWorld) { + this.contraption = contraption; + this.renderWorld = renderWorld; + } + + public int getEntityId() { + return contraption.entity.getEntityId(); + } + + public boolean isDead() { + return !contraption.entity.isAlive(); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/LightVolumeDebugger.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/LightVolumeDebugger.java index e2a3cc684..c8d78bcf0 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/LightVolumeDebugger.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/LightVolumeDebugger.java @@ -11,7 +11,7 @@ import com.simibubi.create.foundation.utility.outliner.AABBOutline; public class LightVolumeDebugger { public static void render(MatrixStack ms, SuperRenderTypeBuffer buffer) { - ContraptionRenderDispatcher.renderers.values() + ContraptionRenderDispatcher.RENDERERS.values() .stream() .flatMap(r -> { GridAlignedBB texture = r.getLighter().lightVolume.getTextureVolume(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/RenderedContraption.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/RenderedContraption.java index 079ae0524..f47a90de5 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/RenderedContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/RenderedContraption.java @@ -6,12 +6,9 @@ import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Random; import javax.annotation.Nullable; -import org.lwjgl.opengl.GL11; - import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.core.IndexedModel; import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat; @@ -25,147 +22,121 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Con import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; -import net.minecraft.block.BlockRenderType; -import net.minecraft.block.BlockState; -import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.ActiveRenderInfo; -import net.minecraft.client.renderer.BlockModelRenderer; -import net.minecraft.client.renderer.BlockModelShapes; -import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.RenderTypeLookup; -import net.minecraft.client.renderer.texture.OverlayTexture; -import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.vector.Matrix4f; import net.minecraft.world.World; -import net.minecraft.world.gen.feature.template.Template; -import net.minecraftforge.client.ForgeHooksClient; -import net.minecraftforge.client.model.data.EmptyModelData; -public class RenderedContraption { +public class RenderedContraption extends ContraptionWorldHolder { public static final VertexFormat FORMAT = VertexFormat.builder() .addAttributes(ContraptionAttributes.class) .build(); - private static final BlockModelRenderer MODEL_RENDERER = new BlockModelRenderer(Minecraft.getInstance().getBlockColors()); - private static final BlockModelShapes BLOCK_MODELS = Minecraft.getInstance().getModelManager().getBlockModelShapes(); - - public Contraption contraption; private final ContraptionLighter lighter; public final ContraptionKineticRenderer kinetics; - public final PlacementSimulationWorld renderWorld; private final Map renderLayers = new HashMap<>(); private Matrix4f model; - private AxisAlignedBB lightBox; + private AxisAlignedBB lightBox; - public RenderedContraption(World world, Contraption contraption) { - this.contraption = contraption; - this.lighter = contraption.makeLighter(); - this.kinetics = new ContraptionKineticRenderer(this); - this.renderWorld = setupRenderWorld(world, contraption); + public RenderedContraption(World world, PlacementSimulationWorld renderWorld, Contraption contraption) { + super(contraption, renderWorld); + this.lighter = contraption.makeLighter(); + this.kinetics = new ContraptionKineticRenderer(this); - buildLayers(); - if (Backend.canUseInstancing()) { - buildInstancedTiles(); - buildActors(); - } - } + buildLayers(); + if (Backend.canUseInstancing()) { + buildInstancedTiles(); + buildActors(); + } + } - public int getEntityId() { - return contraption.entity.getEntityId(); - } + public ContraptionLighter getLighter() { + return lighter; + } - public boolean isDead() { - return !contraption.entity.isAlive(); - } - - public ContraptionLighter getLighter() { - return lighter; - } - - public void doRenderLayer(RenderType layer, ContraptionProgram shader) { + public void doRenderLayer(RenderType layer, ContraptionProgram shader) { IndexedModel structure = renderLayers.get(layer); - if (structure != null) { - setup(shader); - structure.render(); - teardown(); - } - } + if (structure != null) { + setup(shader); + structure.render(); + teardown(); + } + } - public void beginFrame(ActiveRenderInfo info, double camX, double camY, double camZ) { - kinetics.beginFrame(info); + public void beginFrame(ActiveRenderInfo info, double camX, double camY, double camZ) { + kinetics.beginFrame(info); - AbstractContraptionEntity entity = contraption.entity; - float pt = AnimationTickHolder.getPartialTicks(); + AbstractContraptionEntity entity = contraption.entity; + float pt = AnimationTickHolder.getPartialTicks(); - MatrixStack stack = new MatrixStack(); + MatrixStack stack = new MatrixStack(); - double x = MathHelper.lerp(pt, entity.lastTickPosX, entity.getX()) - camX; - double y = MathHelper.lerp(pt, entity.lastTickPosY, entity.getY()) - camY; - double z = MathHelper.lerp(pt, entity.lastTickPosZ, entity.getZ()) - camZ; - stack.translate(x, y, z); + double x = MathHelper.lerp(pt, entity.lastTickPosX, entity.getX()) - camX; + double y = MathHelper.lerp(pt, entity.lastTickPosY, entity.getY()) - camY; + double z = MathHelper.lerp(pt, entity.lastTickPosZ, entity.getZ()) - camZ; + stack.translate(x, y, z); - entity.doLocalTransforms(pt, new MatrixStack[]{ stack }); + entity.doLocalTransforms(pt, new MatrixStack[] { stack }); - model = stack.peek().getModel(); + model = stack.peek().getModel(); - AxisAlignedBB lightBox = GridAlignedBB.toAABB(lighter.lightVolume.getTextureVolume()); + AxisAlignedBB lightBox = GridAlignedBB.toAABB(lighter.lightVolume.getTextureVolume()); - this.lightBox = lightBox.offset(-camX, -camY, -camZ); - } + this.lightBox = lightBox.offset(-camX, -camY, -camZ); + } - void setup(ContraptionProgram shader) { - if (model == null || lightBox == null) return; - shader.bind(model, lightBox); - lighter.lightVolume.bind(); - } + void setup(ContraptionProgram shader) { + if (model == null || lightBox == null) return; + shader.bind(model, lightBox); + lighter.lightVolume.bind(); + } - void teardown() { - lighter.lightVolume.unbind(); - } + void teardown() { + lighter.lightVolume.unbind(); + } - void invalidate() { + void invalidate() { for (IndexedModel buffer : renderLayers.values()) { buffer.delete(); } - renderLayers.clear(); + renderLayers.clear(); - lighter.lightVolume.delete(); + lighter.lightVolume.delete(); - kinetics.invalidate(); - } + kinetics.invalidate(); + } - private void buildLayers() { + private void buildLayers() { for (IndexedModel buffer : renderLayers.values()) { buffer.delete(); } - renderLayers.clear(); + renderLayers.clear(); - List blockLayers = RenderType.getBlockLayers(); + List blockLayers = RenderType.getBlockLayers(); - for (RenderType layer : blockLayers) { + for (RenderType layer : blockLayers) { IndexedModel layerModel = buildStructureModel(renderWorld, contraption, layer); if (layerModel != null) renderLayers.put(layer, layerModel); } - } + } - private void buildInstancedTiles() { - Collection tileEntities = contraption.maybeInstancedTileEntities; - if (!tileEntities.isEmpty()) { - for (TileEntity te : tileEntities) { - if (te instanceof IInstanceRendered) { - World world = te.getWorld(); - BlockPos pos = te.getPos(); - te.setLocation(renderWorld, pos); - kinetics.add(te); + private void buildInstancedTiles() { + Collection tileEntities = contraption.maybeInstancedTileEntities; + if (!tileEntities.isEmpty()) { + for (TileEntity te : tileEntities) { + if (te instanceof IInstanceRendered) { + World world = te.getWorld(); + BlockPos pos = te.getPos(); + te.setLocation(renderWorld, pos); + kinetics.add(te); te.setLocation(world, pos); } } @@ -178,7 +149,7 @@ public class RenderedContraption { @Nullable private static IndexedModel buildStructureModel(PlacementSimulationWorld renderWorld, Contraption c, RenderType layer) { - BufferBuilderReader reader = new BufferBuilderReader(buildStructure(renderWorld, c, layer)); + BufferBuilderReader reader = new BufferBuilderReader(ContraptionRenderDispatcher.buildStructure(renderWorld, c, layer)); int vertexCount = reader.getVertexCount(); if (vertexCount == 0) return null; @@ -218,52 +189,4 @@ public class RenderedContraption { return new IndexedModel(format, to, vertexCount); } - - private static PlacementSimulationWorld setupRenderWorld(World world, Contraption c) { - PlacementSimulationWorld renderWorld = new PlacementSimulationWorld(world); - - renderWorld.setTileEntities(c.presentTileEntities.values()); - - for (Template.BlockInfo info : c.getBlocks() - .values()) - // Skip individual lighting updates to prevent lag with large contraptions - renderWorld.setBlockState(info.pos, info.state, 128); - - renderWorld.updateLightSources(); - renderWorld.lighter.tick(Integer.MAX_VALUE, false, false); - - return renderWorld; - } - - private static BufferBuilder buildStructure(PlacementSimulationWorld renderWorld, Contraption c, RenderType layer) { - MatrixStack ms = new MatrixStack(); - Random random = new Random(); - BufferBuilder builder = new BufferBuilder(DefaultVertexFormats.BLOCK.getIntegerSize()); - builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK); - - ForgeHooksClient.setRenderLayer(layer); - BlockModelRenderer.enableCache(); - for (Template.BlockInfo info : c.getBlocks() - .values()) { - BlockState state = info.state; - - if (state.getRenderType() != BlockRenderType.MODEL) - continue; - if (!RenderTypeLookup.canRenderInLayer(state, layer)) - continue; - - BlockPos pos = info.pos; - - ms.push(); - ms.translate(pos.getX(), pos.getY(), pos.getZ()); - MODEL_RENDERER.renderModel(renderWorld, BLOCK_MODELS.getModel(state), state, pos, ms, builder, true, - random, 42, OverlayTexture.DEFAULT_UV, EmptyModelData.INSTANCE); - ms.pop(); - } - BlockModelRenderer.disableCache(); - ForgeHooksClient.setRenderLayer(null); - - builder.finishDrawing(); - return builder; - } } diff --git a/src/main/java/com/simibubi/create/content/schematics/client/SchematicRenderer.java b/src/main/java/com/simibubi/create/content/schematics/client/SchematicRenderer.java index a585b429d..75f55c7ba 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/SchematicRenderer.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/SchematicRenderer.java @@ -78,8 +78,7 @@ public class SchematicRenderer { SuperByteBuffer superByteBuffer = bufferCache.get(layer); superByteBuffer.renderInto(ms, buffer.getBuffer(layer)); } - TileEntityRenderHelper.renderTileEntities(schematic, schematic.getRenderedTileEntities(), ms, new MatrixStack(), - buffer); + TileEntityRenderHelper.renderTileEntities(schematic, schematic.getRenderedTileEntities(), ms, buffer); } protected void redraw(Minecraft minecraft) { diff --git a/src/main/java/com/simibubi/create/foundation/ponder/elements/WorldSectionElement.java b/src/main/java/com/simibubi/create/foundation/ponder/elements/WorldSectionElement.java index 40e7d49b0..8cac03a46 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/elements/WorldSectionElement.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/elements/WorldSectionElement.java @@ -369,7 +369,7 @@ public class WorldSectionElement extends AnimatedSceneElement { private void renderTileEntities(PonderWorld world, MatrixStack ms, IRenderTypeBuffer buffer, float pt) { loadTEsIfMissing(world); - TileEntityRenderHelper.renderTileEntities(world, renderedTileEntities, ms, new MatrixStack(), buffer, pt); + TileEntityRenderHelper.renderTileEntities(world, renderedTileEntities, ms, buffer, pt); } private SuperByteBuffer buildStructureBuffer(PonderWorld world, RenderType layer) { diff --git a/src/main/java/com/simibubi/create/foundation/render/SuperByteBuffer.java b/src/main/java/com/simibubi/create/foundation/render/SuperByteBuffer.java index 94fbde2ab..3f7c941a8 100644 --- a/src/main/java/com/simibubi/create/foundation/render/SuperByteBuffer.java +++ b/src/main/java/com/simibubi/create/foundation/render/SuperByteBuffer.java @@ -3,14 +3,15 @@ package com.simibubi.create.foundation.render; import com.jozufozu.flywheel.util.BufferBuilderReader; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.vertex.IVertexBuilder; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; import com.simibubi.create.foundation.block.render.SpriteShiftEntry; import com.simibubi.create.foundation.utility.MatrixStacker; -import it.unimi.dsi.fastutil.longs.Long2DoubleMap; -import it.unimi.dsi.fastutil.longs.Long2DoubleOpenHashMap; +import it.unimi.dsi.fastutil.longs.Long2IntMap; +import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; @@ -20,28 +21,29 @@ import net.minecraft.util.math.vector.Quaternion; import net.minecraft.util.math.vector.Vector3d; import net.minecraft.util.math.vector.Vector3f; import net.minecraft.util.math.vector.Vector4f; -import net.minecraft.world.LightType; import net.minecraft.world.World; import net.minecraftforge.client.model.pipeline.LightUtil; public class SuperByteBuffer { private final BufferBuilderReader template; + // Vertex Position private MatrixStack transforms; // Vertex Texture Coords private SpriteShiftFunc spriteShiftFunc; - // Vertex Lighting - private boolean shouldLight; - private int packedLightCoords; - private int otherBlockLight; - private Matrix4f lightTransform; - // Vertex Coloring private boolean shouldColor; private int r, g, b, a; + private boolean disableDiffuseTransform; + + // Vertex Lighting + private boolean useWorldLight; + private boolean hybridLight; + private int packedLightCoords; + private Matrix4f lightTransform; public SuperByteBuffer(BufferBuilder buf) { template = new BufferBuilderReader(buf); @@ -58,8 +60,7 @@ public class SuperByteBuffer { return (v - sprite.getMinV()) / f * 16.0F; } - private static final Long2DoubleMap skyLightCache = new Long2DoubleOpenHashMap(); - private static final Long2DoubleMap blockLightCache = new Long2DoubleOpenHashMap(); + private static final Long2IntMap WORLD_LIGHT_CACHE = new Long2IntOpenHashMap(); Vector4f pos = new Vector4f(); Vector3f normal = new Vector3f(); Vector4f lightPos = new Vector4f(); @@ -71,7 +72,6 @@ public class SuperByteBuffer { Matrix3f normalMat = transforms.peek() .getNormal() .copy(); - // normalMat.multiply(transforms.peek().getNormal()); Matrix4f modelMat = input.peek() .getModel() @@ -81,11 +81,11 @@ public class SuperByteBuffer { .getModel(); modelMat.multiply(localTransforms); - if (shouldLight && lightTransform != null) { - skyLightCache.clear(); - blockLightCache.clear(); + if (useWorldLight) { + WORLD_LIGHT_CACHE.clear(); } + boolean hasDefaultLight = packedLightCoords != 0; float f = .5f; int vertexCount = template.getVertexCount(); for (int i = 0; i < vertexCount; i++) { @@ -120,7 +120,12 @@ public class SuperByteBuffer { int colorB = Math.min(255, (int) (((float) this.b) * instanceDiffuse)); builder.color(colorR, colorG, colorB, this.a); } else { - float diffuseMult = instanceDiffuse / staticDiffuse; + float diffuseMult; + if (disableDiffuseTransform) { + diffuseMult = 1.0f; + } else { + diffuseMult = instanceDiffuse / staticDiffuse; + } int colorR = Math.min(255, (int) (((float) Byte.toUnsignedInt(r)) * diffuseMult)); int colorG = Math.min(255, (int) (((float) Byte.toUnsignedInt(g)) * diffuseMult)); int colorB = Math.min(255, (int) (((float) Byte.toUnsignedInt(b)) * diffuseMult)); @@ -135,32 +140,51 @@ public class SuperByteBuffer { } else builder.texture(u, v); - if (shouldLight) { - int light = packedLightCoords; + int light; + if (useWorldLight) { + lightPos.set(((x - f) * 15 / 16f) + f, (y - f) * 15 / 16f + f, (z - f) * 15 / 16f + f, 1F); + lightPos.transform(localTransforms); if (lightTransform != null) { - lightPos.set(((x - f) * 15 / 16f) + f, (y - f) * 15 / 16f + f, (z - f) * 15 / 16f + f, 1F); - lightPos.transform(localTransforms); lightPos.transform(lightTransform); - - light = getLight(Minecraft.getInstance().world, lightPos); - if (otherBlockLight >= 0) { - light = ContraptionRenderDispatcher.getMaxBlockLight(light, otherBlockLight); - } } + + light = getLight(Minecraft.getInstance().world, lightPos); + if (hasDefaultLight) { + light = maxLight(light, packedLightCoords); + } + } else if (hasDefaultLight) { + light = packedLightCoords; + } else { + light = template.getLight(i); + } + + if (hybridLight) { + builder.light(maxLight(light, template.getLight(i))); + } else { builder.light(light); - } else - builder.light(template.getLight(i)); + } builder.normal(nx, ny, nz) .endVertex(); } - transforms = new MatrixStack(); + reset(); + } + public SuperByteBuffer reset() { + transforms = new MatrixStack(); spriteShiftFunc = null; shouldColor = false; - shouldLight = false; - otherBlockLight = -1; + r = 0; + g = 0; + b = 0; + a = 0; + disableDiffuseTransform = false; + useWorldLight = false; + hybridLight = false; + packedLightCoords = 0; + lightTransform = null; + return this; } public MatrixStacker matrixStacker() { @@ -215,6 +239,20 @@ public class SuperByteBuffer { .translate(-.5f, -.5f, -.5f); } + public SuperByteBuffer color(int color) { + shouldColor = true; + r = ((color >> 16) & 0xFF); + g = ((color >> 8) & 0xFF); + b = (color & 0xFF); + a = 255; + return this; + } + + public SuperByteBuffer disableDiffuseTransform() { + disableDiffuseTransform = true; + return this; + } + public SuperByteBuffer shiftUV(SpriteShiftEntry entry) { this.spriteShiftFunc = (builder, u, v) -> { float targetU = entry.getTarget() @@ -251,42 +289,45 @@ public class SuperByteBuffer { return this; } - public SuperByteBuffer light(int packedLightCoords) { - shouldLight = true; - lightTransform = null; - this.packedLightCoords = packedLightCoords; + public SuperByteBuffer light() { + useWorldLight = true; return this; } public SuperByteBuffer light(Matrix4f lightTransform) { - shouldLight = true; + useWorldLight = true; this.lightTransform = lightTransform; return this; } - public SuperByteBuffer light(Matrix4f lightTransform, int otherBlockLight) { - shouldLight = true; - this.lightTransform = lightTransform; - this.otherBlockLight = otherBlockLight; + public SuperByteBuffer light(int packedLightCoords) { + this.packedLightCoords = packedLightCoords; return this; } - public SuperByteBuffer color(int color) { - shouldColor = true; - r = ((color >> 16) & 0xFF); - g = ((color >> 8) & 0xFF); - b = (color & 0xFF); - a = 255; + public SuperByteBuffer light(Matrix4f lightTransform, int packedLightCoords) { + useWorldLight = true; + this.lightTransform = lightTransform; + this.packedLightCoords = packedLightCoords; return this; } + public SuperByteBuffer hybridLight() { + hybridLight = true; + return this; + } + + public static int maxLight(int packedLight1, int packedLight2) { + int blockLight1 = LightTexture.getBlockLightCoordinates(packedLight1); + int skyLight1 = LightTexture.getSkyLightCoordinates(packedLight1); + int blockLight2 = LightTexture.getBlockLightCoordinates(packedLight2); + int skyLight2 = LightTexture.getSkyLightCoordinates(packedLight2); + return LightTexture.pack(Math.max(blockLight1, blockLight2), Math.max(skyLight1, skyLight2)); + } + private static int getLight(World world, Vector4f lightPos) { - BlockPos.Mutable pos = new BlockPos.Mutable(); - double sky = 0, block = 0; - pos.setPos(lightPos.getX() + 0, lightPos.getY() + 0, lightPos.getZ() + 0); - sky += skyLightCache.computeIfAbsent(pos.toLong(), $ -> world.getLightLevel(LightType.SKY, pos)); - block += blockLightCache.computeIfAbsent(pos.toLong(), $ -> world.getLightLevel(LightType.BLOCK, pos)); - return ((int) sky) << 20 | ((int) block) << 4; + BlockPos pos = new BlockPos(lightPos.getX(), lightPos.getY(), lightPos.getZ()); + return WORLD_LIGHT_CACHE.computeIfAbsent(pos.toLong(), $ -> WorldRenderer.getLightmapCoordinates(world, pos)); } public boolean isEmpty() { @@ -298,4 +339,9 @@ public class SuperByteBuffer { void shift(IVertexBuilder builder, float u, float v); } + @FunctionalInterface + public interface IVertexLighter { + public int getPackedLight(float x, float y, float z); + } + } diff --git a/src/main/java/com/simibubi/create/foundation/render/TileEntityRenderHelper.java b/src/main/java/com/simibubi/create/foundation/render/TileEntityRenderHelper.java index efbf65cff..f00dc81b1 100644 --- a/src/main/java/com/simibubi/create/foundation/render/TileEntityRenderHelper.java +++ b/src/main/java/com/simibubi/create/foundation/render/TileEntityRenderHelper.java @@ -2,15 +2,17 @@ package com.simibubi.create.foundation.render; import java.util.Iterator; +import javax.annotation.Nullable; + import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.Create; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.MatrixStacker; import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; import net.minecraft.client.renderer.IRenderTypeBuffer; +import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.client.renderer.tileentity.TileEntityRenderer; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; @@ -23,28 +25,26 @@ import net.minecraft.world.World; public class TileEntityRenderHelper { public static void renderTileEntities(World world, Iterable customRenderTEs, MatrixStack ms, - MatrixStack localTransform, IRenderTypeBuffer buffer) { - renderTileEntities(world, null, customRenderTEs, ms, localTransform, buffer); + IRenderTypeBuffer buffer) { + renderTileEntities(world, null, customRenderTEs, ms, null, buffer); } public static void renderTileEntities(World world, Iterable customRenderTEs, MatrixStack ms, - MatrixStack localTransform, IRenderTypeBuffer buffer, float pt) { - renderTileEntities(world, null, customRenderTEs, ms, localTransform, buffer, pt); + IRenderTypeBuffer buffer, float pt) { + renderTileEntities(world, null, customRenderTEs, ms, null, buffer, pt); } - public static void renderTileEntities(World world, PlacementSimulationWorld renderWorld, - Iterable customRenderTEs, MatrixStack ms, MatrixStack localTransform, IRenderTypeBuffer buffer) { - renderTileEntities(world, renderWorld, customRenderTEs, ms, localTransform, buffer, + public static void renderTileEntities(World world, @Nullable PlacementSimulationWorld renderWorld, + Iterable customRenderTEs, MatrixStack ms, @Nullable Matrix4f lightTransform, IRenderTypeBuffer buffer) { + renderTileEntities(world, renderWorld, customRenderTEs, ms, lightTransform, buffer, AnimationTickHolder.getPartialTicks()); } - public static void renderTileEntities(World world, PlacementSimulationWorld renderWorld, - Iterable customRenderTEs, MatrixStack ms, MatrixStack localTransform, IRenderTypeBuffer buffer, - float pt) { - Matrix4f matrix = localTransform.peek() - .getModel(); - - for (Iterator iterator = customRenderTEs.iterator(); iterator.hasNext();) { + public static void renderTileEntities(World world, @Nullable PlacementSimulationWorld renderWorld, + Iterable customRenderTEs, MatrixStack ms, @Nullable Matrix4f lightTransform, IRenderTypeBuffer buffer, + float pt) { + Iterator iterator = customRenderTEs.iterator(); + while (iterator.hasNext()) { TileEntity tileEntity = iterator.next(); // if (tileEntity instanceof IInstanceRendered) continue; // TODO: some things still need to render @@ -60,10 +60,15 @@ public class TileEntityRenderHelper { .translate(pos); try { - Vector4f vec = new Vector4f(pos.getX() + .5f, pos.getY() + .5f, pos.getZ() + .5f, 1); - vec.transform(matrix); - BlockPos lightPos = new BlockPos(vec.getX(), vec.getY(), vec.getZ()); - int worldLight = ContraptionRenderDispatcher.getLightOnContraption(world, renderWorld, pos, lightPos); + BlockPos lightPos; + if (lightTransform != null) { + Vector4f lightVec = new Vector4f(pos.getX() + .5f, pos.getY() + .5f, pos.getZ() + .5f, 1); + lightVec.transform(lightTransform); + lightPos = new BlockPos(lightVec.getX(), lightVec.getY(), lightVec.getZ()); + } else { + lightPos = pos; + } + int worldLight = getCombinedLight(world, lightPos, renderWorld, pos); renderer.render(tileEntity, pt, ms, buffer, worldLight, OverlayTexture.DEFAULT_UV); } catch (Exception e) { @@ -82,4 +87,16 @@ public class TileEntityRenderHelper { } } + public static int getCombinedLight(World world, BlockPos worldPos, @Nullable PlacementSimulationWorld renderWorld, + BlockPos renderWorldPos) { + int worldLight = WorldRenderer.getLightmapCoordinates(world, worldPos); + + if (renderWorld != null) { + int renderWorldLight = WorldRenderer.getLightmapCoordinates(renderWorld, renderWorldPos); + return SuperByteBuffer.maxLight(worldLight, renderWorldLight); + } + + return worldLight; + } + }