From 7d43bb056a66fe0689be22fec26658e93402a9db Mon Sep 17 00:00:00 2001 From: JozsefA Date: Mon, 4 Jan 2021 14:37:44 -0800 Subject: [PATCH] merge experimental rendering from 1.16 to 1.15 --- .../com/simibubi/create/AllBlockPartials.java | 27 +- .../com/simibubi/create/CreateClient.java | 11 +- .../contraptions/base/KineticBlock.java | 4 + .../contraptions/base/KineticTileEntity.java | 5 + .../base/KineticTileEntityRenderer.java | 39 ++- .../components/actors/DrillRenderer.java | 7 +- .../components/actors/HarvesterRenderer.java | 2 +- .../PortableStorageInterfaceRenderer.java | 2 +- .../components/clock/CuckooClockRenderer.java | 9 +- .../crafter/MechanicalCrafterRenderer.java | 2 +- .../components/crank/HandCrankRenderer.java | 2 +- .../components/deployer/DeployerRenderer.java | 12 +- .../components/fan/EncasedFanRenderer.java | 45 +-- .../components/flywheel/FlywheelRenderer.java | 7 +- .../millstone/MillstoneRenderer.java | 6 +- .../mixer/MechanicalMixerRenderer.java | 2 +- .../motor/CreativeMotorRenderer.java | 6 +- .../press/MechanicalPressRenderer.java | 2 +- .../components/saw/SawRenderer.java | 18 +- .../ContraptionRenderer.java | 8 +- .../bearing/BearingRenderer.java | 7 +- .../StabilizedBearingMovementBehaviour.java | 2 +- .../pulley/AbstractPulleyRenderer.java | 2 +- .../pulley/PulleyRenderer.java | 2 +- .../train/CouplingRenderer.java | 2 +- .../contraptions/fluids/PumpRenderer.java | 7 +- .../fluids/actors/HosePulleyRenderer.java | 2 +- .../fluids/pipes/FluidValveRenderer.java | 2 +- .../burner/BlazeBurnerRenderer.java | 2 +- .../advanced/SpeedControllerRenderer.java | 10 +- .../contraptions/relays/belt/BeltModel.java | 2 +- .../relays/belt/BeltRenderer.java | 39 ++- .../relays/encased/SplitShaftRenderer.java | 33 ++- .../relays/gauge/GaugeRenderer.java | 2 +- .../relays/gearbox/GearboxRenderer.java | 37 ++- .../belts/tunnel/BeltTunnelRenderer.java | 2 +- .../diodes/AdjustableRepeaterRenderer.java | 2 +- .../block/funnel/FunnelRenderer.java | 2 +- .../block/mechanicalArm/ArmRenderer.java | 12 +- .../block/redstone/AnalogLeverRenderer.java | 2 +- .../block/SchematicannonRenderer.java | 2 +- .../schematics/client/SchematicRenderer.java | 4 +- .../simibubi/create/events/ClientEvents.java | 5 + .../block/connected/CTSpriteShiftEntry.java | 2 +- .../ColoredOverlayTileEntityRenderer.java | 2 +- .../renderer/SafeTileEntityRenderer.java | 1 + .../utility/render/FastKineticRenderer.java | 185 ++++++++++++ .../utility/render/InstancedBuffer.java | 278 ++++++++++++++++++ .../{ => render}/ShadowRenderHelper.java | 2 +- .../utility/{ => render}/SuperByteBuffer.java | 86 +----- .../{ => render}/SuperByteBufferCache.java | 25 +- .../utility/render/TemplateBuffer.java | 107 +++++++ .../{ => render}/TileEntityRenderHelper.java | 3 +- .../utility/render/shader/Shader.java | 13 + .../utility/render/shader/ShaderCallback.java | 10 + .../utility/render/shader/ShaderHelper.java | 140 +++++++++ .../resources/META-INF/accesstransformer.cfg | 6 +- .../assets/create/shader/instanced.frag | 29 ++ .../assets/create/shader/instanced.vert | 60 ++++ 59 files changed, 1079 insertions(+), 268 deletions(-) create mode 100644 src/main/java/com/simibubi/create/foundation/utility/render/FastKineticRenderer.java create mode 100644 src/main/java/com/simibubi/create/foundation/utility/render/InstancedBuffer.java rename src/main/java/com/simibubi/create/foundation/utility/{ => render}/ShadowRenderHelper.java (98%) rename src/main/java/com/simibubi/create/foundation/utility/{ => render}/SuperByteBuffer.java (72%) rename src/main/java/com/simibubi/create/foundation/utility/{ => render}/SuperByteBufferCache.java (86%) create mode 100644 src/main/java/com/simibubi/create/foundation/utility/render/TemplateBuffer.java rename src/main/java/com/simibubi/create/foundation/utility/{ => render}/TileEntityRenderHelper.java (95%) create mode 100644 src/main/java/com/simibubi/create/foundation/utility/render/shader/Shader.java create mode 100644 src/main/java/com/simibubi/create/foundation/utility/render/shader/ShaderCallback.java create mode 100644 src/main/java/com/simibubi/create/foundation/utility/render/shader/ShaderHelper.java create mode 100644 src/main/resources/assets/create/shader/instanced.frag create mode 100644 src/main/resources/assets/create/shader/instanced.vert diff --git a/src/main/java/com/simibubi/create/AllBlockPartials.java b/src/main/java/com/simibubi/create/AllBlockPartials.java index ddb43ea20..2d92ff390 100644 --- a/src/main/java/com/simibubi/create/AllBlockPartials.java +++ b/src/main/java/com/simibubi/create/AllBlockPartials.java @@ -11,12 +11,10 @@ import java.util.Map; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.content.contraptions.fluids.FluidTransportBehaviour.AttachmentTypes; import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.HeatLevel; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.MatrixStacker; -import com.simibubi.create.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.utility.*; +import com.simibubi.create.foundation.utility.render.InstancedBuffer; +import com.simibubi.create.foundation.utility.render.SuperByteBuffer; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.model.IBakedModel; import net.minecraft.util.Direction; @@ -218,4 +216,23 @@ public class AllBlockPartials { return CreateClient.bufferCache.renderDirectionalPartial(this, referenceState, facing, ms); } + public InstancedBuffer renderOnInstanced(BlockState referenceState) { + return CreateClient.kineticRenderer.renderPartialInstanced(this, referenceState); + } + + public InstancedBuffer renderOnDirectionalSouthInstanced(BlockState referenceState) { + Direction facing = referenceState.get(FACING); + return renderOnDirectionalSouthInstanced(referenceState, facing); + } + public InstancedBuffer renderOnDirectionalSouthInstanced(BlockState referenceState, Direction facing) { + MatrixStack ms = new MatrixStack(); + // TODO 1.15 find a way to cache this model matrix computation + MatrixStacker.of(ms) + .centre() + .rotateY(AngleHelper.horizontalAngle(facing)) + .rotateX(AngleHelper.verticalAngle(facing)) + .unCentre(); + return CreateClient.kineticRenderer.renderDirectionalPartialInstanced(this, referenceState, facing, ms); + } + } diff --git a/src/main/java/com/simibubi/create/CreateClient.java b/src/main/java/com/simibubi/create/CreateClient.java index 51f5007e5..d5f9d9b0a 100644 --- a/src/main/java/com/simibubi/create/CreateClient.java +++ b/src/main/java/com/simibubi/create/CreateClient.java @@ -16,9 +16,11 @@ import com.simibubi.create.foundation.block.render.CustomBlockModels; import com.simibubi.create.foundation.block.render.SpriteShifter; import com.simibubi.create.foundation.item.CustomItemModels; import com.simibubi.create.foundation.item.CustomRenderedItems; -import com.simibubi.create.foundation.utility.SuperByteBufferCache; +import com.simibubi.create.foundation.utility.render.FastKineticRenderer; +import com.simibubi.create.foundation.utility.render.SuperByteBufferCache; import com.simibubi.create.foundation.utility.outliner.Outliner; +import com.simibubi.create.foundation.utility.render.shader.ShaderHelper; import net.minecraft.block.Block; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.BlockModelShapes; @@ -42,6 +44,7 @@ public class CreateClient { public static SchematicHandler schematicHandler; public static SchematicAndQuillHandler schematicAndQuillHandler; public static SuperByteBufferCache bufferCache; + public static FastKineticRenderer kineticRenderer; public static final Outliner outliner = new Outliner(); private static CustomBlockModels customBlockModels; @@ -56,6 +59,8 @@ public class CreateClient { modEventBus.addListener(CreateClient::onModelRegistry); modEventBus.addListener(CreateClient::onTextureStitch); modEventBus.addListener(AllParticleTypes::registerFactories); + + ShaderHelper.initShaders(); } public static void clientInit(FMLClientSetupEvent event) { @@ -67,6 +72,10 @@ public class CreateClient { bufferCache.registerCompartment(KineticTileEntityRenderer.KINETIC_TILE); bufferCache.registerCompartment(ContraptionRenderer.CONTRAPTION, 20); + kineticRenderer = new FastKineticRenderer(); + kineticRenderer.registerCompartment(KineticTileEntityRenderer.KINETIC_TILE); + kineticRenderer.registerCompartment(ContraptionRenderer.CONTRAPTION, 20); + AllKeys.register(); AllContainerTypes.registerScreenFactories(); //AllTileEntities.registerRenderers(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/KineticBlock.java b/src/main/java/com/simibubi/create/content/contraptions/base/KineticBlock.java index 24d713f28..24d116dbc 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/KineticBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/KineticBlock.java @@ -1,7 +1,9 @@ package com.simibubi.create.content.contraptions.base; +import com.simibubi.create.CreateClient; import com.simibubi.create.foundation.item.ItemDescription.Palette; +import com.simibubi.create.foundation.utility.render.SuperByteBufferCache; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.entity.LivingEntity; @@ -14,7 +16,9 @@ import net.minecraft.world.IBlockReader; import net.minecraft.world.IWorld; import net.minecraft.world.IWorldReader; import net.minecraft.world.World; +import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.common.ToolType; +import net.minecraftforge.fml.DistExecutor; public abstract class KineticBlock extends Block implements IRotate { diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntity.java index 8df6884c4..9914478ad 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntity.java @@ -8,6 +8,7 @@ import java.util.List; import javax.annotation.Nullable; import com.simibubi.create.Create; +import com.simibubi.create.CreateClient; import com.simibubi.create.content.contraptions.KineticNetwork; import com.simibubi.create.content.contraptions.RotationPropagator; import com.simibubi.create.content.contraptions.base.IRotate.SpeedLevel; @@ -31,9 +32,13 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntityType; import net.minecraft.util.Direction; import net.minecraft.util.Direction.AxisDirection; +import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.TextFormatting; import net.minecraft.world.World; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.common.extensions.IForgeTileEntity; +import net.minecraftforge.fml.DistExecutor; public abstract class KineticTileEntity extends SmartTileEntity implements ITickableTileEntity, IHaveGoggleInformation, IHaveHoveringInformation { diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntityRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntityRenderer.java index 5eb1aea7a..0110b2455 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntityRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntityRenderer.java @@ -1,7 +1,6 @@ package com.simibubi.create.content.contraptions.base; import com.mojang.blaze3d.matrix.MatrixStack; -import com.mojang.blaze3d.vertex.IVertexBuilder; import com.simibubi.create.AllBlocks; import com.simibubi.create.CreateClient; import com.simibubi.create.content.contraptions.KineticDebugger; @@ -9,8 +8,9 @@ import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock; import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.ColorHelper; -import com.simibubi.create.foundation.utility.SuperByteBuffer; -import com.simibubi.create.foundation.utility.SuperByteBufferCache.Compartment; +import com.simibubi.create.foundation.utility.render.InstancedBuffer; +import com.simibubi.create.foundation.utility.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.render.SuperByteBufferCache.Compartment; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; @@ -35,23 +35,36 @@ public class KineticTileEntityRenderer extends SafeTileEntityRenderer { + final BlockPos pos = te.getPos(); + Axis axis = ((IRotate) te.getBlockState() + .getBlock()).getRotationAxis(te.getBlockState()); + + data.setPackedLight(light) + .setRotationalSpeed(te.getSpeed()) + .setRotationOffset(getRotationOffsetForPosition(te, pos, axis)) + .setRotationAxis(Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis).getUnitVector()) + .setPosition(pos); + }); } public static float getAngleForTe(KineticTileEntity te, final BlockPos pos, Axis axis) { @@ -116,8 +129,8 @@ public class KineticTileEntityRenderer extends SafeTileEntityRenderer protected void renderComponents(DeployerTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { IVertexBuilder vb = buffer.getBuffer(RenderType.getSolid()); - KineticTileEntityRenderer.renderRotatingKineticBlock(te, getRenderedBlockState(te), ms, vb, light); + KineticTileEntityRenderer.renderRotatingKineticBlock(te, getRenderedBlockState(te), light); BlockState blockState = te.getBlockState(); BlockPos pos = te.getPos(); @@ -112,10 +112,10 @@ public class DeployerRenderer extends SafeTileEntityRenderer SuperByteBuffer hand = te.getHandPose() .renderOn(blockState); - transform(te.getWorld(), pole.translate(offset.x, offset.y, offset.z), blockState, pos, true).renderInto(ms, - vb); - transform(te.getWorld(), hand.translate(offset.x, offset.y, offset.z), blockState, pos, false).renderInto(ms, - vb); + transform(te.getWorld(), (SuperByteBuffer) pole.translate(offset.x, offset.y, offset.z), blockState, pos, true).renderInto(ms, + vb); + transform(te.getWorld(), (SuperByteBuffer) hand.translate(offset.x, offset.y, offset.z), blockState, pos, false).renderInto(ms, + vb); } protected Vec3d getHandOffset(DeployerTileEntity te, float partialTicks, BlockState blockState) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanRenderer.java index 957ec69e7..fc3203f19 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanRenderer.java @@ -3,18 +3,17 @@ package com.simibubi.create.content.contraptions.components.fan; import static net.minecraft.state.properties.BlockStateProperties.FACING; import com.mojang.blaze3d.matrix.MatrixStack; -import com.mojang.blaze3d.vertex.IVertexBuilder; import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.content.contraptions.base.IRotate; import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.utility.render.InstancedBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer; -import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; public class EncasedFanRenderer extends KineticTileEntityRenderer { @@ -28,27 +27,33 @@ public class EncasedFanRenderer extends KineticTileEntityRenderer { int light, int overlay) { Direction direction = te.getBlockState() .get(FACING); - IVertexBuilder vb = buffer.getBuffer(RenderType.getCutoutMipped()); int lightBehind = WorldRenderer.getLightmapCoordinates(te.getWorld(), te.getPos().offset(direction.getOpposite())); int lightInFront = WorldRenderer.getLightmapCoordinates(te.getWorld(), te.getPos().offset(direction)); - SuperByteBuffer shaftHalf = - AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouth(te.getBlockState(), direction.getOpposite()); - SuperByteBuffer fanInner = - AllBlockPartials.ENCASED_FAN_INNER.renderOnDirectionalSouth(te.getBlockState(), direction.getOpposite()); - - float time = AnimationTickHolder.getRenderTick(); - float speed = te.getSpeed() * 5; - if (speed > 0) - speed = MathHelper.clamp(speed, 80, 64 * 20); - if (speed < 0) - speed = MathHelper.clamp(speed, -64 * 20, -80); - float angle = (time * speed * 3 / 10f) % 360; - angle = angle / 180f * (float) Math.PI; + InstancedBuffer shaftHalf = + AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthInstanced(te.getBlockState(), direction.getOpposite()); + InstancedBuffer fanInner = + AllBlockPartials.ENCASED_FAN_INNER.renderOnDirectionalSouthInstanced(te.getBlockState(), direction.getOpposite()); - standardKineticRotationTransform(shaftHalf, te, lightBehind).renderInto(ms, vb); - kineticRotationTransform(fanInner, te, direction.getAxis(), angle, lightInFront).renderInto(ms, vb); + renderRotatingBuffer(te, shaftHalf, lightBehind); + fanInner.setupInstance(data -> { + final BlockPos pos = te.getPos(); + Direction.Axis axis = ((IRotate) te.getBlockState() + .getBlock()).getRotationAxis(te.getBlockState()); + + float speed = te.getSpeed() * 5; + if (speed > 0) + speed = MathHelper.clamp(speed, 80, 64 * 20); + if (speed < 0) + speed = MathHelper.clamp(speed, -64 * 20, -80); + + data.setPackedLight(lightInFront) + .setRotationalSpeed(speed) + .setRotationOffset(getRotationOffsetForPosition(te, pos, axis)) + .setRotationAxis(Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, axis).getUnitVector()) + .setPosition(pos); + }); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelRenderer.java index 9632779d4..59d7f81ec 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelRenderer.java @@ -9,7 +9,8 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.content.contraptions.components.flywheel.FlywheelBlock.ConnectionState; import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.utility.render.InstancedBuffer; +import com.simibubi.create.foundation.utility.render.SuperByteBuffer; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; @@ -74,8 +75,8 @@ public class FlywheelRenderer extends KineticTileEntityRenderer { } @Override - protected SuperByteBuffer getRotatedModel(KineticTileEntity te) { - return AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouth(te.getBlockState(), te.getBlockState() + protected InstancedBuffer getRotatedModel(KineticTileEntity te) { + return AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthInstanced(te.getBlockState(), te.getBlockState() .get(HORIZONTAL_FACING) .getOpposite()); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/millstone/MillstoneRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/millstone/MillstoneRenderer.java index 2890f16d3..a238a2ba1 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/millstone/MillstoneRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/millstone/MillstoneRenderer.java @@ -4,7 +4,7 @@ import com.simibubi.create.AllBlockPartials; 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.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.utility.render.InstancedBuffer; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; @@ -15,8 +15,8 @@ public class MillstoneRenderer extends KineticTileEntityRenderer { } @Override - protected SuperByteBuffer getRotatedModel(KineticTileEntity te) { - return CreateClient.bufferCache.renderPartial(AllBlockPartials.MILLSTONE_COG, te.getBlockState()); + protected InstancedBuffer getRotatedModel(KineticTileEntity te) { + return CreateClient.kineticRenderer.renderPartialInstanced(AllBlockPartials.MILLSTONE_COG, te.getBlockState()); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MechanicalMixerRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MechanicalMixerRenderer.java index da84d012f..5fc8e6d0f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MechanicalMixerRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MechanicalMixerRenderer.java @@ -6,7 +6,7 @@ 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.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.utility.render.SuperByteBuffer; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/motor/CreativeMotorRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/motor/CreativeMotorRenderer.java index 0993097d0..699c59186 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/motor/CreativeMotorRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/motor/CreativeMotorRenderer.java @@ -3,7 +3,7 @@ package com.simibubi.create.content.contraptions.components.motor; 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.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.utility.render.InstancedBuffer; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; @@ -14,8 +14,8 @@ public class CreativeMotorRenderer extends KineticTileEntityRenderer { } @Override - protected SuperByteBuffer getRotatedModel(KineticTileEntity te) { - return AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouth(te.getBlockState()); + protected InstancedBuffer getRotatedModel(KineticTileEntity te) { + return AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthInstanced(te.getBlockState()); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/press/MechanicalPressRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/press/MechanicalPressRenderer.java index 1a721bac8..bef8ed8e7 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/press/MechanicalPressRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/press/MechanicalPressRenderer.java @@ -4,7 +4,7 @@ import com.mojang.blaze3d.matrix.MatrixStack; 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.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.utility.render.SuperByteBuffer; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; 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 6ab63b12f..4ad2d204a 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,11 +10,10 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringRenderer; 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.SuperByteBuffer; -import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.*; +import com.simibubi.create.foundation.utility.render.InstancedBuffer; +import com.simibubi.create.foundation.utility.render.SuperByteBuffer; import net.minecraft.block.BlockState; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.IRenderTypeBuffer; @@ -79,9 +78,8 @@ public class SawRenderer extends SafeTileEntityRenderer { ms.pop(); } - protected void renderShaft(SawTileEntity te, MatrixStack ms, IRenderTypeBuffer buffer, int light, - int overlay) { - KineticTileEntityRenderer.renderRotatingBuffer(te, getRotatedModel(te), ms, buffer.getBuffer(RenderType.getSolid()), light); + protected void renderShaft(SawTileEntity te, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { + KineticTileEntityRenderer.renderRotatingBuffer(te, getRotatedModel(te), light); } protected void renderItems(SawTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light, @@ -125,11 +123,11 @@ public class SawRenderer extends SafeTileEntityRenderer { } } - protected SuperByteBuffer getRotatedModel(KineticTileEntity te) { + protected InstancedBuffer getRotatedModel(KineticTileEntity te) { BlockState state = te.getBlockState(); if (state.get(FACING).getAxis().isHorizontal()) - return AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouth(state.rotate(Rotation.CLOCKWISE_180)); - return CreateClient.bufferCache.renderBlockIn(KineticTileEntityRenderer.KINETIC_TILE, + return AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthInstanced(state.rotate(te.getWorld(), te.getPos(), Rotation.CLOCKWISE_180)); + return CreateClient.kineticRenderer.renderBlockInstanced(KineticTileEntityRenderer.KINETIC_TILE, getRenderedBlockState(te)); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionRenderer.java index 7892307d8..08307763e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionRenderer.java @@ -10,10 +10,10 @@ import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllMovementBehaviours; import com.simibubi.create.CreateClient; import com.simibubi.create.foundation.utility.MatrixStacker; -import com.simibubi.create.foundation.utility.SuperByteBuffer; -import com.simibubi.create.foundation.utility.SuperByteBufferCache; -import com.simibubi.create.foundation.utility.SuperByteBufferCache.Compartment; -import com.simibubi.create.foundation.utility.TileEntityRenderHelper; +import com.simibubi.create.foundation.utility.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.render.SuperByteBufferCache; +import com.simibubi.create.foundation.utility.render.SuperByteBufferCache.Compartment; +import com.simibubi.create.foundation.utility.render.TileEntityRenderHelper; import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; import net.minecraft.block.BlockRenderType; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingRenderer.java index e1f7978f5..fece4075f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingRenderer.java @@ -5,7 +5,8 @@ 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.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.utility.render.InstancedBuffer; +import com.simibubi.create.foundation.utility.render.SuperByteBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.RenderType; @@ -43,8 +44,8 @@ public class BearingRenderer extends KineticTileEntityRenderer { } @Override - protected SuperByteBuffer getRotatedModel(KineticTileEntity te) { - return AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouth(te.getBlockState(), te.getBlockState() + protected InstancedBuffer getRotatedModel(KineticTileEntity te) { + return AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthInstanced(te.getBlockState(), te.getBlockState() .get(BearingBlock.FACING) .getOpposite()); } 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 35df5d517..3b92c2738 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 @@ -8,7 +8,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.OrientedContraptionEntity; import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.utility.render.SuperByteBuffer; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.IRenderTypeBuffer; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/AbstractPulleyRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/AbstractPulleyRenderer.java index e93ecf899..ce1f47044 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/AbstractPulleyRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/AbstractPulleyRenderer.java @@ -7,7 +7,7 @@ import com.simibubi.create.content.contraptions.base.IRotate; import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.utility.render.SuperByteBuffer; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyRenderer.java index 0922e6ba1..ffdd25677 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyRenderer.java @@ -5,7 +5,7 @@ import com.simibubi.create.AllBlocks; import com.simibubi.create.CreateClient; import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; -import com.simibubi.create.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.utility.render.SuperByteBuffer; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; import net.minecraft.util.Direction.Axis; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingRenderer.java index 35041160d..ab60ed2a4 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingRenderer.java @@ -11,7 +11,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.tra import com.simibubi.create.foundation.utility.ColorHelper; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.MatrixStacker; -import com.simibubi.create.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.utility.render.SuperByteBuffer; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.block.BlockState; diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpRenderer.java index ff887c908..372cab409 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpRenderer.java @@ -6,7 +6,8 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.MatrixStacker; -import com.simibubi.create.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.utility.render.InstancedBuffer; +import com.simibubi.create.foundation.utility.render.SuperByteBuffer; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; @@ -51,8 +52,8 @@ public class PumpRenderer extends KineticTileEntityRenderer { } @Override - protected SuperByteBuffer getRotatedModel(KineticTileEntity te) { - return AllBlockPartials.MECHANICAL_PUMP_COG.renderOnDirectionalSouth(te.getBlockState()); + protected InstancedBuffer getRotatedModel(KineticTileEntity te) { + return AllBlockPartials.MECHANICAL_PUMP_COG.renderOnDirectionalSouthInstanced(te.getBlockState()); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/HosePulleyRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/HosePulleyRenderer.java index af76354d6..565bdb3fa 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/HosePulleyRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/HosePulleyRenderer.java @@ -3,7 +3,7 @@ package com.simibubi.create.content.contraptions.fluids.actors; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.components.structureMovement.pulley.AbstractPulleyRenderer; -import com.simibubi.create.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.utility.render.SuperByteBuffer; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; import net.minecraft.util.Direction.Axis; diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveRenderer.java index c50f78bb4..cc9d9d8d5 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveRenderer.java @@ -6,7 +6,7 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.MatrixStacker; -import com.simibubi.create.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.utility.render.SuperByteBuffer; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerRenderer.java index e9e68a582..f2469f1c2 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerRenderer.java @@ -6,7 +6,7 @@ import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlo 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.SuperByteBuffer; +import com.simibubi.create.foundation.utility.render.SuperByteBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.RenderType; diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/SpeedControllerRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/SpeedControllerRenderer.java index 0bd5d9096..dae604e77 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/SpeedControllerRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/SpeedControllerRenderer.java @@ -4,10 +4,9 @@ import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.CreateClient; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.foundation.tileEntity.renderer.SmartTileEntityRenderer; -import com.simibubi.create.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.utility.render.InstancedBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer; -import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; public class SpeedControllerRenderer extends SmartTileEntityRenderer { @@ -21,12 +20,11 @@ public class SpeedControllerRenderer extends SmartTileEntityRenderer { : start ? AllBlockPartials.BELT_START : end ? AllBlockPartials.BELT_END : AllBlockPartials.BELT_MIDDLE; - SuperByteBuffer beltBuffer = beltPartial.renderOn(blockState) - .light(light); - SpriteShiftEntry spriteShift = - diagonal ? AllSpriteShifts.BELT_DIAGONAL : bottom ? AllSpriteShifts.BELT_OFFSET : AllSpriteShifts.BELT; + InstancedBuffer beltBuffer = beltPartial.renderOnInstanced(blockState); int cycleLength = diagonal ? 12 : 16; int cycleOffset = bottom ? 8 : 0; // UV shift - float speed = te.getSpeed(); - if (speed != 0) { - float time = renderTick * axisDirection.getOffset(); + + beltBuffer.setupInstance(data -> { + float speed = te.getSpeed(); if (diagonal && (downward ^ alongX) || !sideways && !diagonal && alongX - || sideways && axisDirection == AxisDirection.NEGATIVE) + || sideways && axisDirection == AxisDirection.NEGATIVE) speed = -speed; - int textureIndex = (int) (((speed * time / 36) + cycleOffset) % cycleLength); - if (textureIndex < 0) - textureIndex += cycleLength; - beltBuffer.shiftUVtoSheet(spriteShift, (textureIndex % 4) / 4f, (textureIndex / 4) / 4f, 4); - } - - beltBuffer.renderInto(ms, vb); + data.setPackedLight(light) + .setPosition(te.getPos()) + .setRotationalSpeed(speed) + .setRotationAxis(0, 0, 0) + .setCycleLength(cycleLength) + .setCycleOffset(cycleOffset); + }); // Diagonal belt do not have a separate bottom model if (diagonal) @@ -140,10 +138,9 @@ public class BeltRenderer extends SafeTileEntityRenderer { msr.rotateX(90); msr.unCentre(); - SuperByteBuffer superBuffer = CreateClient.bufferCache - .renderDirectionalPartial(AllBlockPartials.BELT_PULLEY, blockState, dir, modelTransform); - KineticTileEntityRenderer.standardKineticRotationTransform(superBuffer, te, light) - .renderInto(ms, vb); + InstancedBuffer superBuffer = CreateClient.kineticRenderer + .renderDirectionalPartialInstanced(AllBlockPartials.BELT_PULLEY, blockState, dir, modelTransform); + KineticTileEntityRenderer.renderRotatingBuffer(te, superBuffer, light); } renderItems(te, partialTicks, ms, buffer, light, overlay); diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/SplitShaftRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/SplitShaftRenderer.java index 96186728f..3512d9572 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/SplitShaftRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/SplitShaftRenderer.java @@ -5,13 +5,11 @@ import com.simibubi.create.AllBlockPartials; import com.simibubi.create.content.contraptions.base.IRotate; import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.utility.render.InstancedBuffer; import net.minecraft.block.Block; import net.minecraft.client.renderer.IRenderTypeBuffer; -import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis; @@ -29,28 +27,31 @@ public class SplitShaftRenderer extends KineticTileEntityRenderer { Block block = te.getBlockState().getBlock(); final Axis boxAxis = ((IRotate) block).getRotationAxis(te.getBlockState()); final BlockPos pos = te.getPos(); - float time = AnimationTickHolder.getRenderTick(); for (Direction direction : Iterate.directions) { Axis axis = direction.getAxis(); if (boxAxis != axis) continue; - float offset = getRotationOffsetForPosition(te, pos, axis); - float angle = (time * te.getSpeed() * 3f / 10) % 360; - float modifier = 1; - if (te instanceof SplitShaftTileEntity) - modifier = ((SplitShaftTileEntity) te).getRotationSpeedModifier(direction); + InstancedBuffer shaft = AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthInstanced(te.getBlockState(), direction); - angle *= modifier; - angle += offset; - angle = angle / 180f * (float) Math.PI; + shaft.setupInstance(data -> { + float speed = te.getSpeed(); - SuperByteBuffer superByteBuffer = - AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouth(te.getBlockState(), direction); - kineticRotationTransform(superByteBuffer, te, axis, angle, light); - superByteBuffer.renderInto(ms, buffer.getBuffer(RenderType.getSolid())); + float modifier = 1; + + if (te instanceof SplitShaftTileEntity) + modifier = ((SplitShaftTileEntity) te).getRotationSpeedModifier(direction); + + speed *= modifier; + + data.setPackedLight(light) + .setRotationalSpeed(speed) + .setRotationOffset(getRotationOffsetForPosition(te, pos, axis)) + .setRotationAxis(Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, axis).getUnitVector()) + .setPosition(pos); + }); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeRenderer.java index 8c24f63b4..4f02505a2 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeRenderer.java @@ -7,7 +7,7 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.content.contraptions.relays.gauge.GaugeBlock.Type; import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.utility.render.SuperByteBuffer; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxRenderer.java index 7462e355c..b4e0c48be 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxRenderer.java @@ -4,12 +4,10 @@ import com.mojang.blaze3d.matrix.MatrixStack; 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.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.utility.render.InstancedBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer; -import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.util.Direction; @@ -27,31 +25,32 @@ public class GearboxRenderer extends KineticTileEntityRenderer { int light, int overlay) { final Axis boxAxis = te.getBlockState().get(BlockStateProperties.AXIS); final BlockPos pos = te.getPos(); - float time = AnimationTickHolder.getRenderTick(); for (Direction direction : Iterate.directions) { final Axis axis = direction.getAxis(); if (boxAxis == axis) continue; - SuperByteBuffer shaft = AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouth(te.getBlockState(), direction); - float offset = getRotationOffsetForPosition(te, pos, axis); - float angle = (time * te.getSpeed() * 3f / 10) % 360; + InstancedBuffer shaft = AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthInstanced(te.getBlockState(), direction); - if (te.getSpeed() != 0 && te.hasSource()) { - BlockPos source = te.source.subtract(te.getPos()); - Direction sourceFacing = Direction.getFacingFromVector(source.getX(), source.getY(), source.getZ()); - if (sourceFacing.getAxis() == direction.getAxis()) - angle *= sourceFacing == direction ? 1 : -1; - else if (sourceFacing.getAxisDirection() == direction.getAxisDirection()) - angle *= -1; - } + shaft.setupInstance(data -> { + float speed = te.getSpeed(); - angle += offset; - angle = angle / 180f * (float) Math.PI; + if (te.getSpeed() != 0 && te.hasSource()) { + BlockPos source = te.source.subtract(te.getPos()); + Direction sourceFacing = Direction.getFacingFromVector(source.getX(), source.getY(), source.getZ()); + if (sourceFacing.getAxis() == direction.getAxis()) + speed *= sourceFacing == direction ? 1 : -1; + else if (sourceFacing.getAxisDirection() == direction.getAxisDirection()) + speed *= -1; + } - kineticRotationTransform(shaft, te, axis, angle, light); - shaft.renderInto(ms, buffer.getBuffer(RenderType.getSolid())); + data.setPackedLight(light) + .setRotationalSpeed(speed) + .setRotationOffset(getRotationOffsetForPosition(te, pos, axis)) + .setRotationAxis(Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, axis).getUnitVector()) + .setPosition(pos); + }); } } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelRenderer.java b/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelRenderer.java index 5b3bd9dbc..6b52d157d 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelRenderer.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelRenderer.java @@ -7,7 +7,7 @@ import com.simibubi.create.foundation.tileEntity.renderer.SmartTileEntityRendere import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.MatrixStacker; -import com.simibubi.create.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.utility.render.SuperByteBuffer; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.client.renderer.IRenderTypeBuffer; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/diodes/AdjustableRepeaterRenderer.java b/src/main/java/com/simibubi/create/content/logistics/block/diodes/AdjustableRepeaterRenderer.java index 86b1b43e5..72d235388 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/diodes/AdjustableRepeaterRenderer.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/diodes/AdjustableRepeaterRenderer.java @@ -3,7 +3,7 @@ package com.simibubi.create.content.logistics.block.diodes; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.foundation.tileEntity.renderer.ColoredOverlayTileEntityRenderer; import com.simibubi.create.foundation.utility.ColorHelper; -import com.simibubi.create.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.utility.render.SuperByteBuffer; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelRenderer.java b/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelRenderer.java index ed0f46a09..8e61a8675 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelRenderer.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelRenderer.java @@ -6,7 +6,7 @@ import com.simibubi.create.AllBlockPartials; import com.simibubi.create.foundation.tileEntity.renderer.SmartTileEntityRenderer; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.MatrixStacker; -import com.simibubi.create.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.utility.render.SuperByteBuffer; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.client.renderer.IRenderTypeBuffer; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmRenderer.java b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmRenderer.java index f770012ed..bab767872 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmRenderer.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmRenderer.java @@ -6,12 +6,10 @@ 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.logistics.block.mechanicalArm.ArmTileEntity.Phase; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.ColorHelper; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.MatrixStacker; -import com.simibubi.create.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.utility.*; +import com.simibubi.create.foundation.utility.render.InstancedBuffer; +import com.simibubi.create.foundation.utility.render.SuperByteBuffer; import net.minecraft.block.BlockState; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.IRenderTypeBuffer; @@ -118,8 +116,8 @@ public class ArmRenderer extends KineticTileEntityRenderer { } @Override - protected SuperByteBuffer getRotatedModel(KineticTileEntity te) { - return AllBlockPartials.ARM_COG.renderOn(te.getBlockState()); + protected InstancedBuffer getRotatedModel(KineticTileEntity te) { + return AllBlockPartials.ARM_COG.renderOnInstanced(te.getBlockState()); } } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/AnalogLeverRenderer.java b/src/main/java/com/simibubi/create/content/logistics/block/redstone/AnalogLeverRenderer.java index dcc0521c8..716cf1648 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/AnalogLeverRenderer.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/redstone/AnalogLeverRenderer.java @@ -6,7 +6,7 @@ import com.simibubi.create.AllBlockPartials; import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.ColorHelper; -import com.simibubi.create.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.utility.render.SuperByteBuffer; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; diff --git a/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonRenderer.java b/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonRenderer.java index 706d9d931..37898e3ff 100644 --- a/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonRenderer.java +++ b/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonRenderer.java @@ -8,7 +8,7 @@ import com.simibubi.create.AllBlockPartials; import com.simibubi.create.content.schematics.block.LaunchedItem.ForBlockState; import com.simibubi.create.content.schematics.block.LaunchedItem.ForEntity; import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; -import com.simibubi.create.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.utility.render.SuperByteBuffer; import net.minecraft.block.BlockState; import net.minecraft.client.Minecraft; 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 21971355a..063dc873a 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 @@ -13,8 +13,8 @@ import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.content.schematics.SchematicWorld; import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer; import com.simibubi.create.foundation.utility.MatrixStacker; -import com.simibubi.create.foundation.utility.SuperByteBuffer; -import com.simibubi.create.foundation.utility.TileEntityRenderHelper; +import com.simibubi.create.foundation.utility.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.render.TileEntityRenderHelper; import net.minecraft.block.BlockState; import net.minecraft.client.Minecraft; diff --git a/src/main/java/com/simibubi/create/events/ClientEvents.java b/src/main/java/com/simibubi/create/events/ClientEvents.java index e3399d191..056043cdf 100644 --- a/src/main/java/com/simibubi/create/events/ClientEvents.java +++ b/src/main/java/com/simibubi/create/events/ClientEvents.java @@ -32,6 +32,7 @@ import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollVal import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.ServerSpeedProvider; import com.simibubi.create.foundation.utility.placement.PlacementHelpers; +import com.simibubi.create.foundation.utility.render.FastKineticRenderer; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.ActiveRenderInfo; import net.minecraft.client.renderer.IRenderTypeBuffer; @@ -76,6 +77,8 @@ public class ClientEvents { if (!isGameActive()) return; + CreateClient.kineticRenderer.tick(); + CreateClient.schematicSender.tick(); CreateClient.schematicAndQuillHandler.tick(); CreateClient.schematicHandler.tick(); @@ -112,6 +115,8 @@ public class ClientEvents { @SubscribeEvent public static void onRenderWorld(RenderWorldLastEvent event) { + CreateClient.kineticRenderer.renderInstances(event); + MatrixStack ms = event.getMatrixStack(); ActiveRenderInfo info = Minecraft.getInstance().gameRenderer.getActiveRenderInfo(); Vec3d view = info.getProjectedView(); diff --git a/src/main/java/com/simibubi/create/foundation/block/connected/CTSpriteShiftEntry.java b/src/main/java/com/simibubi/create/foundation/block/connected/CTSpriteShiftEntry.java index 41741eb5b..2d2d84506 100644 --- a/src/main/java/com/simibubi/create/foundation/block/connected/CTSpriteShiftEntry.java +++ b/src/main/java/com/simibubi/create/foundation/block/connected/CTSpriteShiftEntry.java @@ -3,7 +3,7 @@ package com.simibubi.create.foundation.block.connected; import com.simibubi.create.foundation.block.connected.CTSpriteShifter.CTType; import com.simibubi.create.foundation.block.connected.ConnectedTextureBehaviour.CTContext; import com.simibubi.create.foundation.block.render.SpriteShiftEntry; -import com.simibubi.create.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.utility.render.SuperByteBuffer; public abstract class CTSpriteShiftEntry extends SpriteShiftEntry { diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/renderer/ColoredOverlayTileEntityRenderer.java b/src/main/java/com/simibubi/create/foundation/tileEntity/renderer/ColoredOverlayTileEntityRenderer.java index b8bc4b733..95648409e 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/renderer/ColoredOverlayTileEntityRenderer.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/renderer/ColoredOverlayTileEntityRenderer.java @@ -1,7 +1,7 @@ package com.simibubi.create.foundation.tileEntity.renderer; import com.mojang.blaze3d.matrix.MatrixStack; -import com.simibubi.create.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.utility.render.SuperByteBuffer; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/renderer/SafeTileEntityRenderer.java b/src/main/java/com/simibubi/create/foundation/tileEntity/renderer/SafeTileEntityRenderer.java index 6c02f67f9..bc4c0de82 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/renderer/SafeTileEntityRenderer.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/renderer/SafeTileEntityRenderer.java @@ -7,6 +7,7 @@ import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.tileentity.TileEntityRenderer; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.client.model.pipeline.LightUtil; public abstract class SafeTileEntityRenderer extends TileEntityRenderer { diff --git a/src/main/java/com/simibubi/create/foundation/utility/render/FastKineticRenderer.java b/src/main/java/com/simibubi/create/foundation/utility/render/FastKineticRenderer.java new file mode 100644 index 000000000..998c8af87 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/utility/render/FastKineticRenderer.java @@ -0,0 +1,185 @@ +package com.simibubi.create.foundation.utility.render; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.systems.RenderSystem; +import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.Create; +import com.simibubi.create.foundation.utility.render.shader.Shader; +import com.simibubi.create.foundation.utility.render.shader.ShaderHelper; +import net.minecraft.block.BlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.*; +import net.minecraft.client.renderer.model.IBakedModel; +import net.minecraft.client.renderer.texture.Texture; +import net.minecraft.inventory.container.PlayerContainer; +import net.minecraft.util.Direction; +import net.minecraft.util.math.vector.Matrix4f; +import net.minecraft.util.math.vector.Vector3d; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.client.event.RenderWorldLastEvent; +import net.minecraftforge.fml.common.Mod; +import org.apache.commons.lang3.tuple.Pair; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL40; + +import java.util.*; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; + +import static com.simibubi.create.foundation.utility.render.SuperByteBufferCache.PARTIAL; + +@Mod.EventBusSubscriber(modid = Create.ID, value = Dist.CLIENT) +public class FastKineticRenderer { + Map, Cache> cache; + + Queue runs; + + public FastKineticRenderer() { + cache = new HashMap<>(); + runs = new ConcurrentLinkedQueue<>(); + registerCompartment(SuperByteBufferCache.GENERIC_TILE); + registerCompartment(SuperByteBufferCache.PARTIAL); + registerCompartment(SuperByteBufferCache.DIRECTIONAL_PARTIAL); + } + + public void tick() { + for (Cache cache : cache.values()) { + for (InstancedBuffer renderer : cache.asMap().values()) { + renderer.clearInstanceData(); + } + } + } + + public void enqueue(Runnable run) { + runs.add(run); + } + + public void renderInstances(RenderWorldLastEvent event) { + RenderSystem.enableBlend(); + RenderSystem.blendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); + + RenderSystem.enableCull(); + + GameRenderer gameRenderer = Minecraft.getInstance().gameRenderer; + LightTexture lightManager = gameRenderer.getLightmapTextureManager(); + + ShaderHelper.useShader(Shader.ROTATING_INSTANCED, shader -> { + ShaderHelper.MATRIX_BUFFER.position(0); + event.getProjectionMatrix().write(ShaderHelper.MATRIX_BUFFER); + + int projection = GlStateManager.getUniformLocation(shader, "projection"); + GlStateManager.uniformMatrix4(projection, false, ShaderHelper.MATRIX_BUFFER); + + // view matrix + Vector3d pos = gameRenderer.getActiveRenderInfo().getProjectedView(); + Matrix4f translate = Matrix4f.translate((float) -pos.x, (float) -pos.y, (float) -pos.z); + translate.multiplyBackward(event.getMatrixStack().peek().getModel()); + + ShaderHelper.MATRIX_BUFFER.position(0); + translate.write(ShaderHelper.MATRIX_BUFFER); + int view = GlStateManager.getUniformLocation(shader, "view"); + GlStateManager.uniformMatrix4(view, false, ShaderHelper.MATRIX_BUFFER); + + Texture blockAtlasTexture = Minecraft.getInstance().textureManager.getTexture(PlayerContainer.BLOCK_ATLAS_TEXTURE); + Texture lightTexture = Minecraft.getInstance().textureManager.getTexture(lightManager.resourceLocation); + + GL40.glActiveTexture(GL40.GL_TEXTURE0); + GL40.glBindTexture(GL11.GL_TEXTURE_2D, blockAtlasTexture.getGlTextureId()); + + GL40.glActiveTexture(GL40.GL_TEXTURE0 + 1); + GL40.glBindTexture(GL11.GL_TEXTURE_2D, lightTexture.getGlTextureId()); + RenderSystem.texParameter(3553, 10241, 9729); + RenderSystem.texParameter(3553, 10240, 9729); + RenderSystem.texParameter(3553, 10242, 10496); + RenderSystem.texParameter(3553, 10243, 10496); + RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.enableTexture(); + }); + + cache.values() + .stream() + .flatMap(cache -> { + ConcurrentMap map = cache.asMap(); + + return map.values().stream(); + }) + .filter(type -> !type.isEmpty()) + .forEach(InstancedBuffer::render); + + ShaderHelper.releaseShader(); + + GL40.glActiveTexture(GL40.GL_TEXTURE0 + 1); + GL40.glBindTexture(GL11.GL_TEXTURE_2D, 0); + GL40.glActiveTexture(GL40.GL_TEXTURE0); + GL40.glBindTexture(GL11.GL_TEXTURE_2D, 0); + + RenderSystem.disableCull(); + RenderSystem.disableBlend(); + RenderSystem.defaultBlendFunc(); + + while (!runs.isEmpty()) { + runs.remove().run(); + } + } + + public void registerCompartment(SuperByteBufferCache.Compartment instance) { + cache.put(instance, CacheBuilder.newBuilder().build()); + } + + public void registerCompartment(SuperByteBufferCache.Compartment instance, long ticksUntilExpired) { + cache.put(instance, CacheBuilder.newBuilder().expireAfterAccess(ticksUntilExpired * 50, TimeUnit.MILLISECONDS).build()); + } + + public InstancedBuffer renderPartialInstanced(AllBlockPartials partial, BlockState referenceState) { + return getInstanced(PARTIAL, partial, () -> rotatingInstancedRenderer(partial.get(), referenceState)); + } + + public InstancedBuffer renderDirectionalPartialInstanced(AllBlockPartials partial, BlockState referenceState, Direction dir, + MatrixStack modelTransform) { + return getInstanced(SuperByteBufferCache.DIRECTIONAL_PARTIAL, Pair.of(dir, partial), + () -> rotatingInstancedRenderer(partial.get(), referenceState, modelTransform)); + } + + public InstancedBuffer renderBlockInstanced(SuperByteBufferCache.Compartment compartment, BlockState toRender) { + return getInstanced(compartment, toRender, () -> rotatingInstancedRenderer(toRender)); + } + + public InstancedBuffer getInstanced(SuperByteBufferCache.Compartment compartment, T key, Supplier supplier) { + Cache compartmentCache = this.cache.get(compartment); + try { + return compartmentCache.get(key, supplier::get); + } catch (ExecutionException e) { + e.printStackTrace(); + return null; + } + } + + + private InstancedBuffer rotatingInstancedRenderer(BlockState renderedState) { + BlockRendererDispatcher dispatcher = Minecraft.getInstance().getBlockRendererDispatcher(); + return rotatingInstancedRenderer(dispatcher.getModelForState(renderedState), renderedState); + } + + private InstancedBuffer rotatingInstancedRenderer(IBakedModel model, BlockState renderedState) { + return rotatingInstancedRenderer(model, renderedState, new MatrixStack()); + } + + private InstancedBuffer rotatingInstancedRenderer(IBakedModel model, BlockState referenceState, MatrixStack ms) { + BufferBuilder builder = SuperByteBufferCache.getBufferBuilder(model, referenceState, ms); + + return new InstancedBuffer(builder); + } + + public void invalidate() { + cache.values().forEach(cache -> { + cache.asMap().values().forEach(InstancedBuffer::invalidate); + cache.invalidateAll(); + }); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/utility/render/InstancedBuffer.java b/src/main/java/com/simibubi/create/foundation/utility/render/InstancedBuffer.java new file mode 100644 index 000000000..a2c0b4e6c --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/utility/render/InstancedBuffer.java @@ -0,0 +1,278 @@ +package com.simibubi.create.foundation.utility.render; + + +import com.mojang.blaze3d.platform.GlStateManager; +import com.simibubi.create.CreateClient; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.GLAllocation; +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.Vector3f; +import net.minecraft.client.renderer.vertex.VertexFormatElement; +import net.minecraft.util.math.BlockPos; +import org.lwjgl.opengl.*; + +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.function.Consumer; + +public class InstancedBuffer extends TemplateBuffer { + + public int vao, ebo, invariantVBO, instanceVBO, instanceCount; + + private final ArrayList data = new ArrayList<>(); + private boolean shouldBuild = true; + + public InstancedBuffer(BufferBuilder buf) { + super(buf); + setupMainData(); + } + + private void setupMainData() { + int floatSize = VertexFormatElement.Type.FLOAT.getSize(); + + int stride = floatSize * 8; + int invariantSize = count * stride; + + ByteBuffer constant = GLAllocation.createDirectByteBuffer(invariantSize); + constant.order(template.order()); + ((Buffer) constant).limit(invariantSize); + + int indicesSize = count * VertexFormatElement.Type.USHORT.getSize(); + ByteBuffer indices = GLAllocation.createDirectByteBuffer(indicesSize); + indices.order(template.order()); + ((Buffer) indices).limit(indicesSize); + + int vertexCount = vertexCount(template); + for (int i = 0; i < vertexCount; i++) { + constant.putFloat(getX(template, i)); + constant.putFloat(getY(template, i)); + constant.putFloat(getZ(template, i)); + + constant.putFloat(getNX(template, i)); + constant.putFloat(getNY(template, i)); + constant.putFloat(getNZ(template, i)); + + constant.putFloat(getU(template, i)); + constant.putFloat(getV(template, i)); + + indices.putShort((short) i); + } + constant.rewind(); + indices.rewind(); + + vao = GL30.glGenVertexArrays(); + GL30.glBindVertexArray(vao); + + ebo = GlStateManager.genBuffers(); + invariantVBO = GlStateManager.genBuffers(); + instanceVBO = GlStateManager.genBuffers(); + + GlStateManager.bindBuffers(GL15.GL_ARRAY_BUFFER, invariantVBO); + GlStateManager.bufferData(GL15.GL_ARRAY_BUFFER, constant, GL15.GL_STATIC_DRAW); + + GlStateManager.bindBuffers(GL15.GL_ELEMENT_ARRAY_BUFFER, ebo); + GlStateManager.bufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, indices, GL15.GL_STATIC_DRAW); + + // vertex positions + GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, stride, 0); + + // vertex normals + GL20.glVertexAttribPointer(1, 3, GL11.GL_FLOAT, false, stride, floatSize * 3L); + + // uv position + GL20.glVertexAttribPointer(2, 2, GL11.GL_FLOAT, false, stride, floatSize * 6L); + + GlStateManager.bindBuffers(GL15.GL_ARRAY_BUFFER, 0); + GlStateManager.bindBuffers(GL15.GL_ELEMENT_ARRAY_BUFFER, 0); + // Deselect (bind to 0) the VAO + GL30.glBindVertexArray(0); + } + + public int numInstances() { + return instanceCount; + } + + public boolean isEmpty() { + return numInstances() == 0; + } + + public void clearInstanceData() { + instanceCount = 0; + shouldBuild = true; + } + + public void invalidate() { + CreateClient.kineticRenderer.enqueue(() -> { + GL15.glDeleteBuffers(invariantVBO); + GL15.glDeleteBuffers(instanceVBO); + GL15.glDeleteBuffers(ebo); + GL30.glDeleteVertexArrays(vao); + + clearInstanceData(); + }); + } + + public void setupInstance(Consumer setup) { + if (!shouldBuild) return; + + InstanceData instanceData = new InstanceData(); + setup.accept(instanceData); + + data.add(instanceData); + instanceCount++; + } + + public void render() { + + GL30.glBindVertexArray(vao); + if (finishBuffering()) { + + for (int i = 0; i <= 8; i++) { + GL40.glEnableVertexAttribArray(i); + } + + GlStateManager.bindBuffers(GL15.GL_ELEMENT_ARRAY_BUFFER, ebo); + + GL40.glDrawElementsInstanced(GL11.GL_QUADS, count, GL11.GL_UNSIGNED_SHORT, 0, instanceCount); + + for (int i = 0; i <= 8; i++) { + GL40.glDisableVertexAttribArray(i); + } + } + GL30.glBindVertexArray(0); + } + + private boolean finishBuffering() { + if (!shouldBuild) return true; + + int floatSize = VertexFormatElement.Type.FLOAT.getSize(); + int intSize = VertexFormatElement.Type.INT.getSize(); + int stride = floatSize * 10 + intSize * 2; + + int instanceSize = data.size() * stride; + + if (instanceSize == 0) return false; + + ByteBuffer buffer = GLAllocation.createDirectByteBuffer(instanceSize); + buffer.order(template.order()); + ((Buffer) buffer).limit(instanceSize); + + data.forEach(instanceData -> instanceData.buffer(buffer)); + buffer.rewind(); + + GlStateManager.bindBuffers(GL15.GL_ARRAY_BUFFER, instanceVBO); + GlStateManager.bufferData(GL15.GL_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW); + + // the render position + GL20.glVertexAttribPointer(3, 3, GL11.GL_FLOAT, false, stride, 0); + + // vertex lighting + GL20.glVertexAttribPointer(4, 2, GL11.GL_FLOAT, false, stride, floatSize * 3L); + + // rotational speed and offset + GL20.glVertexAttribPointer(5, 1, GL11.GL_FLOAT, false, stride, floatSize * 5L); + GL20.glVertexAttribPointer(6, 1, GL11.GL_FLOAT, false, stride, floatSize * 6L); + // rotation axis + GL20.glVertexAttribPointer(7, 3, GL11.GL_FLOAT, false, stride, floatSize * 7L); + // uv scrolling + GL20.glVertexAttribPointer(8, 2, GL11.GL_INT, false, stride, floatSize * 10L); + + for (int i = 3; i <= 8; i++) { + GL40.glVertexAttribDivisor(i, 1); + } + + // Deselect (bind to 0) the VBO + GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0); + + shouldBuild = false; + data.clear(); + + return true; + } + + public static class InstanceData { + private float x; + private float y; + private float z; + private int packedLight = 0; + private float rotationalSpeed; + private float rotationOffset; + private float rotationAxisX; + private float rotationAxisY; + private float rotationAxisZ; + private int cycleLength; + private int cycleOffset; + + public InstanceData setPackedLight(int packedLight) { + this.packedLight = packedLight; + return this; + } + + public InstanceData setRotationalSpeed(float rotationalSpeed) { + this.rotationalSpeed = rotationalSpeed; + return this; + } + + public InstanceData setRotationOffset(float rotationOffset) { + this.rotationOffset = rotationOffset; + return this; + } + + public InstanceData setPosition(Vector3f pos) { + this.x = pos.getX(); + this.y = pos.getY(); + this.z = pos.getZ(); + return this; + } + + public InstanceData setPosition(BlockPos pos) { + this.x = pos.getX(); + this.y = pos.getY(); + this.z = pos.getZ(); + return this; + } + + public InstanceData setRotationAxis(Vector3f axis) { + this.rotationAxisX = axis.getX(); + this.rotationAxisY = axis.getY(); + this.rotationAxisZ = axis.getZ(); + return this; + } + + public InstanceData setRotationAxis(float rotationAxisX, float rotationAxisY, float rotationAxisZ) { + this.rotationAxisX = rotationAxisX; + this.rotationAxisY = rotationAxisY; + this.rotationAxisZ = rotationAxisZ; + return this; + } + + public InstanceData setCycleLength(int cycleLength) { + this.cycleLength = cycleLength; + return this; + } + + public InstanceData setCycleOffset(int cycleOffset) { + this.cycleOffset = cycleOffset; + return this; + } + + void buffer(ByteBuffer buf) { + float blockLightCoordinates = LightTexture.getBlockLightCoordinates(packedLight) / (float) 0xF; + float skyLightCoordinates = LightTexture.getSkyLightCoordinates(packedLight) / (float) 0xF; + + buf.putFloat(x); + buf.putFloat(y); + buf.putFloat(z); + buf.putFloat(blockLightCoordinates); + buf.putFloat(skyLightCoordinates); + buf.putFloat(rotationalSpeed); + buf.putFloat(rotationOffset); + buf.putFloat(rotationAxisX); + buf.putFloat(rotationAxisY); + buf.putFloat(rotationAxisZ); + buf.putInt(cycleLength); + buf.putInt(cycleOffset); + } + } +} diff --git a/src/main/java/com/simibubi/create/foundation/utility/ShadowRenderHelper.java b/src/main/java/com/simibubi/create/foundation/utility/render/ShadowRenderHelper.java similarity index 98% rename from src/main/java/com/simibubi/create/foundation/utility/ShadowRenderHelper.java rename to src/main/java/com/simibubi/create/foundation/utility/render/ShadowRenderHelper.java index 0a8f5349a..a172cefd1 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/ShadowRenderHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/render/ShadowRenderHelper.java @@ -1,4 +1,4 @@ -package com.simibubi.create.foundation.utility; +package com.simibubi.create.foundation.utility.render; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.vertex.IVertexBuilder; diff --git a/src/main/java/com/simibubi/create/foundation/utility/SuperByteBuffer.java b/src/main/java/com/simibubi/create/foundation/utility/render/SuperByteBuffer.java similarity index 72% rename from src/main/java/com/simibubi/create/foundation/utility/SuperByteBuffer.java rename to src/main/java/com/simibubi/create/foundation/utility/render/SuperByteBuffer.java index d7c8b0569..25c20d11d 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/SuperByteBuffer.java +++ b/src/main/java/com/simibubi/create/foundation/utility/render/SuperByteBuffer.java @@ -1,19 +1,16 @@ -package com.simibubi.create.foundation.utility; +package com.simibubi.create.foundation.utility.render; import java.nio.Buffer; import java.nio.ByteBuffer; -import java.nio.ByteOrder; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.vertex.IVertexBuilder; -import com.mojang.datafixers.util.Pair; import com.simibubi.create.foundation.block.render.SpriteShiftEntry; import it.unimi.dsi.fastutil.longs.Long2DoubleMap; import it.unimi.dsi.fastutil.longs.Long2DoubleOpenHashMap; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.BufferBuilder; -import net.minecraft.client.renderer.BufferBuilder.DrawState; import net.minecraft.client.renderer.GLAllocation; import net.minecraft.client.renderer.Matrix4f; import net.minecraft.client.renderer.Vector4f; @@ -23,15 +20,12 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.LightType; import net.minecraft.world.World; -public class SuperByteBuffer { +public class SuperByteBuffer extends TemplateBuffer { public interface IVertexLighter { public int getPackedLight(float x, float y, float z); } - protected ByteBuffer template; - protected int formatSize; - // Vertex Position private MatrixStack transforms; @@ -51,21 +45,7 @@ public class SuperByteBuffer { private float sheetSize; public SuperByteBuffer(BufferBuilder buf) { - Pair state = buf.popData(); - ByteBuffer rendered = state.getSecond(); - rendered.order(ByteOrder.nativeOrder()); // Vanilla bug, endianness does not carry over into sliced buffers - - formatSize = buf.getVertexFormat() - .getSize(); - int size = state.getFirst() - .getCount() * formatSize; - - template = GLAllocation.createDirectByteBuffer(size); - template.order(rendered.order()); - ((Buffer) template).limit(((Buffer) rendered).limit()); - template.put(rendered); - ((Buffer) template).rewind(); - + super(buf); transforms = new MatrixStack(); } @@ -219,66 +199,6 @@ public class SuperByteBuffer { return this; } - protected int vertexCount(ByteBuffer buffer) { - return ((Buffer) buffer).limit() / formatSize; - } - - protected int getBufferPosition(int vertexIndex) { - return vertexIndex * formatSize; - } - - protected float getX(ByteBuffer buffer, int index) { - return buffer.getFloat(getBufferPosition(index)); - } - - protected float getY(ByteBuffer buffer, int index) { - return buffer.getFloat(getBufferPosition(index) + 4); - } - - protected float getZ(ByteBuffer buffer, int index) { - return buffer.getFloat(getBufferPosition(index) + 8); - } - - protected byte getR(ByteBuffer buffer, int index) { - return buffer.get(getBufferPosition(index) + 12); - } - - protected byte getG(ByteBuffer buffer, int index) { - return buffer.get(getBufferPosition(index) + 13); - } - - protected byte getB(ByteBuffer buffer, int index) { - return buffer.get(getBufferPosition(index) + 14); - } - - protected byte getA(ByteBuffer buffer, int index) { - return buffer.get(getBufferPosition(index) + 15); - } - - protected float getU(ByteBuffer buffer, int index) { - return buffer.getFloat(getBufferPosition(index) + 16); - } - - protected float getV(ByteBuffer buffer, int index) { - return buffer.getFloat(getBufferPosition(index) + 20); - } - - protected int getLight(ByteBuffer buffer, int index) { - return buffer.getInt(getBufferPosition(index) + 24); - } - - protected byte getNX(ByteBuffer buffer, int index) { - return buffer.get(getBufferPosition(index) + 28); - } - - protected byte getNY(ByteBuffer buffer, int index) { - return buffer.get(getBufferPosition(index) + 29); - } - - protected byte getNZ(ByteBuffer buffer, int index) { - return buffer.get(getBufferPosition(index) + 30); - } - private static int getLight(World world, Vector4f lightPos) { BlockPos.Mutable pos = new BlockPos.Mutable(); double sky = 0, block = 0; diff --git a/src/main/java/com/simibubi/create/foundation/utility/SuperByteBufferCache.java b/src/main/java/com/simibubi/create/foundation/utility/render/SuperByteBufferCache.java similarity index 86% rename from src/main/java/com/simibubi/create/foundation/utility/SuperByteBufferCache.java rename to src/main/java/com/simibubi/create/foundation/utility/render/SuperByteBufferCache.java index f37b65912..db86d16fa 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/SuperByteBufferCache.java +++ b/src/main/java/com/simibubi/create/foundation/utility/render/SuperByteBufferCache.java @@ -1,11 +1,15 @@ -package com.simibubi.create.foundation.utility; +package com.simibubi.create.foundation.utility.render; -import java.util.HashMap; -import java.util.Map; +import java.util.*; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.function.Supplier; +import com.google.common.collect.Collections2; +import com.simibubi.create.CreateClient; +import com.simibubi.create.foundation.utility.VirtualEmptyModelData; +import net.minecraftforge.client.event.EntityViewRenderEvent; +import net.minecraftforge.client.event.RenderWorldLastEvent; import org.apache.commons.lang3.tuple.Pair; import org.lwjgl.opengl.GL11; @@ -50,7 +54,6 @@ public class SuperByteBufferCache { public SuperByteBuffer renderPartial(AllBlockPartials partial, BlockState referenceState) { return get(PARTIAL, partial, () -> standardModelRender(partial.get(), referenceState)); } - public SuperByteBuffer renderPartial(AllBlockPartials partial, BlockState referenceState, MatrixStack modelTransform) { return get(PARTIAL, partial, () -> standardModelRender(partial.get(), referenceState, modelTransform)); @@ -108,21 +111,27 @@ public class SuperByteBufferCache { } private SuperByteBuffer standardModelRender(IBakedModel model, BlockState referenceState, MatrixStack ms) { + BufferBuilder builder = getBufferBuilder(model, referenceState, ms); + + return new SuperByteBuffer(builder); + } + + public static BufferBuilder getBufferBuilder(IBakedModel model, BlockState referenceState, MatrixStack ms) { Minecraft mc = Minecraft.getInstance(); BlockRendererDispatcher dispatcher = mc.getBlockRendererDispatcher(); BlockModelRenderer blockRenderer = dispatcher.getBlockModelRenderer(); BufferBuilder builder = new BufferBuilder(512); builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK); - blockRenderer.renderModel(mc.world, model, referenceState, BlockPos.ZERO.up(255), ms, builder, true, - mc.world.rand, 42, OverlayTexture.DEFAULT_UV, VirtualEmptyModelData.INSTANCE); + blockRenderer.renderModel(mc.world, model, referenceState, BlockPos.ZERO.up(255), ms, builder, true, mc.world.rand, 42, OverlayTexture.DEFAULT_UV, VirtualEmptyModelData.INSTANCE); builder.finishDrawing(); - - return new SuperByteBuffer(builder); + return builder; } + public void invalidate() { cache.forEach((comp, cache) -> cache.invalidateAll()); + CreateClient.kineticRenderer.invalidate(); } } diff --git a/src/main/java/com/simibubi/create/foundation/utility/render/TemplateBuffer.java b/src/main/java/com/simibubi/create/foundation/utility/render/TemplateBuffer.java new file mode 100644 index 000000000..222e24df0 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/utility/render/TemplateBuffer.java @@ -0,0 +1,107 @@ +package com.simibubi.create.foundation.utility.render; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.datafixers.util.Pair; +import com.simibubi.create.foundation.block.render.SpriteShiftEntry; +import it.unimi.dsi.fastutil.longs.Long2DoubleMap; +import it.unimi.dsi.fastutil.longs.Long2DoubleOpenHashMap; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.GLAllocation; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.vector.Matrix4f; +import net.minecraft.util.math.vector.Vector4f; +import net.minecraft.world.LightType; +import net.minecraft.world.World; + +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.time.temporal.TemporalAccessor; + +public class TemplateBuffer { + protected ByteBuffer template; + protected int formatSize; + protected int count; + + public TemplateBuffer(BufferBuilder buf) { + Pair state = buf.popData(); + ByteBuffer rendered = state.getSecond(); + rendered.order(ByteOrder.nativeOrder()); // Vanilla bug, endianness does not carry over into sliced buffers + + formatSize = buf.getVertexFormat() + .getSize(); + count = state.getFirst().getCount(); + int size = count * formatSize; + + template = GLAllocation.createDirectByteBuffer(size); + template.order(rendered.order()); + ((Buffer)template).limit(((Buffer)rendered).limit()); + template.put(rendered); + ((Buffer)template).rewind(); + } + + public boolean isEmpty() { + return ((Buffer) template).limit() == 0; + } + + protected int vertexCount(ByteBuffer buffer) { + return ((Buffer)buffer).limit() / formatSize; + } + + protected int getBufferPosition(int vertexIndex) { + return vertexIndex * formatSize; + } + + protected float getX(ByteBuffer buffer, int index) { + return buffer.getFloat(getBufferPosition(index)); + } + + protected float getY(ByteBuffer buffer, int index) { + return buffer.getFloat(getBufferPosition(index) + 4); + } + + protected float getZ(ByteBuffer buffer, int index) { + return buffer.getFloat(getBufferPosition(index) + 8); + } + + protected byte getR(ByteBuffer buffer, int index) { + return buffer.get(getBufferPosition(index) + 12); + } + + protected byte getG(ByteBuffer buffer, int index) { + return buffer.get(getBufferPosition(index) + 13); + } + + protected byte getB(ByteBuffer buffer, int index) { + return buffer.get(getBufferPosition(index) + 14); + } + + protected byte getA(ByteBuffer buffer, int index) { + return buffer.get(getBufferPosition(index) + 15); + } + + protected float getU(ByteBuffer buffer, int index) { + return buffer.getFloat(getBufferPosition(index) + 16); + } + + protected float getV(ByteBuffer buffer, int index) { + return buffer.getFloat(getBufferPosition(index) + 20); + } + + protected int getLight(ByteBuffer buffer, int index) { + return buffer.getInt(getBufferPosition(index) + 24); + } + + protected byte getNX(ByteBuffer buffer, int index) { + return buffer.get(getBufferPosition(index) + 28); + } + + protected byte getNY(ByteBuffer buffer, int index) { + return buffer.get(getBufferPosition(index) + 29); + } + + protected byte getNZ(ByteBuffer buffer, int index) { + return buffer.get(getBufferPosition(index) + 30); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/utility/TileEntityRenderHelper.java b/src/main/java/com/simibubi/create/foundation/utility/render/TileEntityRenderHelper.java similarity index 95% rename from src/main/java/com/simibubi/create/foundation/utility/TileEntityRenderHelper.java rename to src/main/java/com/simibubi/create/foundation/utility/render/TileEntityRenderHelper.java index ea9e6e361..9dbab11a7 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/TileEntityRenderHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/render/TileEntityRenderHelper.java @@ -1,4 +1,4 @@ -package com.simibubi.create.foundation.utility; +package com.simibubi.create.foundation.utility.render; import java.util.Iterator; @@ -6,6 +6,7 @@ import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.Create; import com.simibubi.create.foundation.config.AllConfigs; +import com.simibubi.create.foundation.utility.MatrixStacker; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.Matrix4f; diff --git a/src/main/java/com/simibubi/create/foundation/utility/render/shader/Shader.java b/src/main/java/com/simibubi/create/foundation/utility/render/shader/Shader.java new file mode 100644 index 000000000..d0d3b34c1 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/utility/render/shader/Shader.java @@ -0,0 +1,13 @@ +package com.simibubi.create.foundation.utility.render.shader; + +public enum Shader { + ROTATING_INSTANCED("shader/instanced.vert", "shader/instanced.frag"); + + public final String vert; + public final String frag; + + Shader(String vert, String frag) { + this.vert = vert; + this.frag = frag; + } +} diff --git a/src/main/java/com/simibubi/create/foundation/utility/render/shader/ShaderCallback.java b/src/main/java/com/simibubi/create/foundation/utility/render/shader/ShaderCallback.java new file mode 100644 index 000000000..5ed0dbb2d --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/utility/render/shader/ShaderCallback.java @@ -0,0 +1,10 @@ +package com.simibubi.create.foundation.utility.render.shader; + +/** + * A Callback for when a shader is called. Used to define shader uniforms. + */ +@FunctionalInterface +public interface ShaderCallback { + + void call(int shader); +} diff --git a/src/main/java/com/simibubi/create/foundation/utility/render/shader/ShaderHelper.java b/src/main/java/com/simibubi/create/foundation/utility/render/shader/ShaderHelper.java new file mode 100644 index 000000000..2a58b7a2e --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/utility/render/shader/ShaderHelper.java @@ -0,0 +1,140 @@ +package com.simibubi.create.foundation.utility.render.shader; + +import com.mojang.blaze3d.platform.GlStateManager; +import com.simibubi.create.Create; +import com.simibubi.create.CreateClient; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import net.minecraft.client.MainWindow; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.ActiveRenderInfo; +import net.minecraft.client.shader.IShaderManager; +import net.minecraft.client.shader.ShaderLinkHelper; +import net.minecraft.client.shader.ShaderLoader; +import net.minecraft.resources.IReloadableResourceManager; +import net.minecraft.resources.IResourceManager; +import net.minecraft.resources.IResourceManagerReloadListener; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.client.event.EntityViewRenderEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.lwjgl.system.MemoryUtil; + +import javax.annotation.Nullable; +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.FloatBuffer; +import java.util.EnumMap; +import java.util.Locale; +import java.util.Map; + +public class ShaderHelper { + + public static final Logger log = LogManager.getLogger("shader"); + + public static final FloatBuffer FLOAT_BUFFER = MemoryUtil.memAllocFloat(1); + public static final FloatBuffer MATRIX_BUFFER = MemoryUtil.memAllocFloat(16); + + private static final Map PROGRAMS = new EnumMap<>(Shader.class); + + @SuppressWarnings("deprecation") + public static void initShaders() { + // Can be null when running datagenerators due to the unfortunate time we call this + if (Minecraft.getInstance() != null + && Minecraft.getInstance().getResourceManager() instanceof IReloadableResourceManager) { + ((IReloadableResourceManager) Minecraft.getInstance().getResourceManager()).addReloadListener( + (IResourceManagerReloadListener) manager -> { + PROGRAMS.values().forEach(ShaderLinkHelper::deleteShader); + PROGRAMS.clear(); + for (Shader shader : Shader.values()) { + createProgram(manager, shader); + } + }); + } + } + + public static void useShader(Shader shader) { + useShader(shader, null); + } + + public static void useShader(Shader shader, @Nullable ShaderCallback cb) { + ShaderProgram prog = PROGRAMS.get(shader); + if (prog == null) { + return; + } + + int program = prog.getProgram(); + ShaderLinkHelper.useProgram(program); + + int time = GlStateManager.getUniformLocation(program, "time"); + FLOAT_BUFFER.position(0); + FLOAT_BUFFER.put(0, AnimationTickHolder.getRenderTick()); + GlStateManager.uniform1(time, FLOAT_BUFFER); + + int ticks = GlStateManager.getUniformLocation(program, "ticks"); + GlStateManager.uniform1(ticks, AnimationTickHolder.ticks); + + if (cb != null) { + cb.call(program); + } + } + + public static void releaseShader() { + ShaderLinkHelper.useProgram(0); + } + + private static void createProgram(IResourceManager manager, Shader shader) { + try { + ShaderLoader vert = createShader(manager, shader.vert, ShaderLoader.ShaderType.VERTEX); + ShaderLoader frag = createShader(manager, shader.frag, ShaderLoader.ShaderType.FRAGMENT); + int progId = ShaderLinkHelper.createProgram(); + ShaderProgram prog = new ShaderProgram(progId, vert, frag); + ShaderLinkHelper.linkProgram(prog); + PROGRAMS.put(shader, prog); + + log.info("Loaded program {}", shader.name()); + } catch (IOException ex) { + log.error("Failed to load program {}", shader.name(), ex); + } + } + + private static ShaderLoader createShader(IResourceManager manager, String filename, ShaderLoader.ShaderType shaderType) throws IOException { + ResourceLocation loc = new ResourceLocation(Create.ID, filename); + try (InputStream is = new BufferedInputStream(manager.getResource(loc).getInputStream())) { + return ShaderLoader.func_216534_a(shaderType, loc.toString(), is, shaderType.name().toLowerCase(Locale.ROOT)); + } + } + + private static class ShaderProgram implements IShaderManager { + private final int program; + private final ShaderLoader vert; + private final ShaderLoader frag; + + private ShaderProgram(int program, ShaderLoader vert, ShaderLoader frag) { + this.program = program; + this.vert = vert; + this.frag = frag; + } + + @Override + public int getProgram() { + return program; + } + + @Override + public void markDirty() { + + } + + @Override + public ShaderLoader getVertexShaderLoader() { + return vert; + } + + @Override + public ShaderLoader getFragmentShaderLoader() { + return frag; + } + } +} diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index 98de531a9..fdc144a8b 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -23,4 +23,8 @@ public net.minecraft.tileentity.BeaconTileEntity field_174909_f # beamSegments # Server Tick List (For stopping placed fluids from spilling) public net.minecraft.world.server.ServerTickList field_205374_d # pendingTickListEntriesHashSet -public net.minecraft.world.server.ServerTickList field_205375_e # pendingTickListEntriesTreeSet \ No newline at end of file +public net.minecraft.world.server.ServerTickList field_205375_e # pendingTickListEntriesTreeSet + +# Lightmap information for instanced rendering +public net.minecraft.client.renderer.LightTexture field_205112_c #resourceLocation +public net.minecraft.client.Minecraft field_193996_ah #renderPartialTicksPaused \ No newline at end of file diff --git a/src/main/resources/assets/create/shader/instanced.frag b/src/main/resources/assets/create/shader/instanced.frag new file mode 100644 index 000000000..81596480c --- /dev/null +++ b/src/main/resources/assets/create/shader/instanced.frag @@ -0,0 +1,29 @@ +#version 440 core +in vec2 TexCoords; +in vec2 Light; + +out vec4 fragColor; + +layout(binding=0) uniform sampler2D BlockAtlas; +layout(binding=1) uniform sampler2D LightMap; + +float blendDarken(float base, float blend) { + return min(blend,base); +} + +vec3 blendDarken(vec3 base, vec3 blend) { + return vec3(blendDarken(base.r,blend.r),blendDarken(base.g,blend.g),blendDarken(base.b,blend.b)); +} + +vec3 blendDarken(vec3 base, vec3 blend, float opacity) { + return (blendDarken(base, blend) * opacity + base * (1.0 - opacity)); +} + +void main() +{ + vec4 tex = texture2D(BlockAtlas, TexCoords); + + vec4 light = texture2D(LightMap, Light); + + fragColor = vec4(blendDarken(tex.rgb, light.rgb, light.a), tex.a); +} \ No newline at end of file diff --git a/src/main/resources/assets/create/shader/instanced.vert b/src/main/resources/assets/create/shader/instanced.vert new file mode 100644 index 000000000..c34947ac9 --- /dev/null +++ b/src/main/resources/assets/create/shader/instanced.vert @@ -0,0 +1,60 @@ +#version 330 core +#define PI 3.1415926538 +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; +layout (location = 2) in vec2 aTexCoords; + +layout (location = 3) in vec3 instancePos; +layout (location = 4) in vec2 light; +layout (location = 5) in float speed; +layout (location = 6) in float rotationOffset; +layout (location = 7) in vec3 rotationAxis; +layout (location = 8) in int[2] uvScroll; // uvScroll[0] <- cycleLength, uvScroll[1] <- cycleOffset + +out vec2 TexCoords; +out vec2 Light; + +uniform float time; +uniform int ticks; +uniform mat4 projection; +uniform mat4 view; + +mat4 rotationMatrix(vec3 axis, float angle) +{ + axis = normalize(axis); + float s = sin(angle); + float c = cos(angle); + float oc = 1.0 - c; + + return mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0., + oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0., + oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0., + 0., 0., 0., 1.); +} + +void main() +{ + vec4 renderPos; + int textureIndex = 0; + if (abs(rotationAxis.x) + abs(rotationAxis.y) + abs(rotationAxis.z) < 0.2) { + renderPos = vec4(aPos + instancePos, 1f); + + textureIndex = int((speed * time / 36) + uvScroll[1]) % uvScroll[0]; + if (textureIndex < 0) { + textureIndex += uvScroll[0]; + } + + } else { + float degrees = rotationOffset + time * speed * 3./10.; + float angle = fract(-degrees / 360.) * PI * 2.; + + renderPos = rotationMatrix(rotationAxis, angle) * vec4(aPos - vec3(0.5), 1f); + + renderPos += vec4(instancePos + vec3(0.5), 0); + } + + TexCoords = aTexCoords + vec2(float(textureIndex % 4) / 4f, float(textureIndex / 4) / 4f); + + gl_Position = projection * view * renderPos; + Light = light; +} \ No newline at end of file