From a56d08b78e43983acb92ec821cc49148d797d047 Mon Sep 17 00:00:00 2001 From: JozsefA Date: Mon, 11 Jan 2021 00:29:02 -0800 Subject: [PATCH] a bunch of refactoring to make things easier later it's not any more stable but belts render on contraptions rotating things almost do actually fix a bunch of memory leaks --- .../com/simibubi/create/AllBlockPartials.java | 22 ++- .../com/simibubi/create/CreateClient.java | 8 +- .../contraptions/base/KineticTileEntity.java | 6 + .../base/KineticTileEntityRenderer.java | 42 ++--- .../components/actors/DrillRenderer.java | 7 +- .../components/clock/CuckooClockRenderer.java | 13 +- .../components/deployer/DeployerRenderer.java | 8 +- .../components/fan/EncasedFanRenderer.java | 35 ++-- .../components/flywheel/FlywheelRenderer.java | 8 +- .../millstone/MillstoneRenderer.java | 7 +- .../motor/CreativeMotorRenderer.java | 6 +- .../components/saw/SawRenderer.java | 17 +- .../bearing/BearingRenderer.java | 12 +- .../contraptions/fluids/PumpRenderer.java | 8 +- .../advanced/SpeedControllerRenderer.java | 10 +- .../relays/belt/BeltRenderer.java | 22 ++- .../relays/encased/SplitShaftRenderer.java | 23 ++- .../relays/gearbox/GearboxRenderer.java | 24 ++- .../block/mechanicalArm/ArmRenderer.java | 8 +- .../simibubi/create/events/ClientEvents.java | 19 +- .../foundation/ResourceReloadHandler.java | 4 +- .../command/ClearBufferCacheCommand.java | 4 +- .../utility/render/ContraptionBuffer.java | 81 ++++----- .../utility/render/ContraptionLighter.java | 14 +- .../render/FastContraptionRenderer.java | 141 +++++++++----- .../utility/render/FastKineticRenderer.java | 146 +++++++++------ .../utility/render/SafeDirectBuffer.java | 172 ++++++++++++++++++ .../utility/render/TemplateBuffer.java | 26 ++- .../render/TileEntityRenderHelper.java | 3 + .../utility/render/instancing/BasicData.java | 5 +- .../utility/render/instancing/BeltData.java | 6 +- .../IInstancedTileEntityRenderer.java | 8 +- .../render/instancing/InstanceBuffer.java | 122 ++++++------- .../render/instancing/InstanceContext.java | 56 ++++++ .../render/instancing/InstanceData.java | 12 +- .../render/instancing/RotatingData.java | 6 +- .../render/instancing/VertexAttribute.java | 4 +- .../utility/render/shader/Shader.java | 6 +- .../utility/render/shader/ShaderHelper.java | 22 +-- .../assets/create/shader/contraption.frag | 1 - .../assets/create/shader/contraption.vert | 18 +- .../create/shader/contraption_belt.vert | 79 ++++++++ .../create/shader/contraption_rotating.vert | 71 ++++++++ 43 files changed, 916 insertions(+), 396 deletions(-) create mode 100644 src/main/java/com/simibubi/create/foundation/utility/render/SafeDirectBuffer.java create mode 100644 src/main/java/com/simibubi/create/foundation/utility/render/instancing/InstanceContext.java create mode 100644 src/main/resources/assets/create/shader/contraption_belt.vert create mode 100644 src/main/resources/assets/create/shader/contraption_rotating.vert diff --git a/src/main/java/com/simibubi/create/AllBlockPartials.java b/src/main/java/com/simibubi/create/AllBlockPartials.java index 580b612b7..9279194c2 100644 --- a/src/main/java/com/simibubi/create/AllBlockPartials.java +++ b/src/main/java/com/simibubi/create/AllBlockPartials.java @@ -9,12 +9,13 @@ import java.util.List; import java.util.Map; import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.fluids.FluidTransportBehaviour.AttachmentTypes; import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.HeatLevel; +import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity; import com.simibubi.create.foundation.utility.*; -import com.simibubi.create.foundation.utility.render.instancing.BeltBuffer; -import com.simibubi.create.foundation.utility.render.instancing.RotatingBuffer; +import com.simibubi.create.foundation.utility.render.instancing.*; import com.simibubi.create.foundation.utility.render.SuperByteBuffer; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.model.IBakedModel; @@ -217,19 +218,20 @@ public class AllBlockPartials { return CreateClient.bufferCache.renderDirectionalPartial(this, referenceState, facing, ms); } - public RotatingBuffer renderOnRotating(BlockState referenceState) { - return CreateClient.kineticRenderer.renderPartialRotating(this, referenceState); + public InstanceBuffer renderOnRotating(InstanceContext ctx, BlockState referenceState) { + return ctx.getKinetics().renderPartialRotating(this, referenceState); } - public BeltBuffer renderOnBelt(BlockState referenceState) { - return CreateClient.kineticRenderer.renderPartialBelt(this, referenceState); + public InstanceBuffer renderOnBelt(InstanceContext ctx, BlockState referenceState) { + return ctx.getKinetics().renderPartialBelt(this, referenceState); } - public RotatingBuffer renderOnDirectionalSouthRotating(BlockState referenceState) { + public InstanceBuffer renderOnDirectionalSouthRotating(InstanceContext ctx, BlockState referenceState) { Direction facing = referenceState.get(FACING); - return renderOnDirectionalSouthRotating(referenceState, facing); + return renderOnDirectionalSouthRotating(ctx, referenceState, facing); } - public RotatingBuffer renderOnDirectionalSouthRotating(BlockState referenceState, Direction facing) { + + public InstanceBuffer renderOnDirectionalSouthRotating(InstanceContext ctx, BlockState referenceState, Direction facing) { MatrixStack ms = new MatrixStack(); // TODO 1.15 find a way to cache this model matrix computation MatrixStacker.of(ms) @@ -237,7 +239,7 @@ public class AllBlockPartials { .rotateY(AngleHelper.horizontalAngle(facing)) .rotateX(AngleHelper.verticalAngle(facing)) .unCentre(); - return CreateClient.kineticRenderer.renderDirectionalPartialInstanced(this, referenceState, facing, ms); + return ctx.getKinetics().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 d5f9d9b0a..fc635297e 100644 --- a/src/main/java/com/simibubi/create/CreateClient.java +++ b/src/main/java/com/simibubi/create/CreateClient.java @@ -16,6 +16,7 @@ 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.render.FastContraptionRenderer; import com.simibubi.create.foundation.utility.render.FastKineticRenderer; import com.simibubi.create.foundation.utility.render.SuperByteBufferCache; import com.simibubi.create.foundation.utility.outliner.Outliner; @@ -73,8 +74,6 @@ public class CreateClient { bufferCache.registerCompartment(ContraptionRenderer.CONTRAPTION, 20); kineticRenderer = new FastKineticRenderer(); - kineticRenderer.registerCompartment(KineticTileEntityRenderer.KINETIC_TILE); - kineticRenderer.registerCompartment(ContraptionRenderer.CONTRAPTION, 20); AllKeys.register(); AllContainerTypes.registerScreenFactories(); @@ -180,4 +179,9 @@ public class CreateClient { return casingConnectivity; } + public static void invalidateRenderers() { + CreateClient.bufferCache.invalidate(); + CreateClient.kineticRenderer.invalidate(); + FastContraptionRenderer.invalidateAll(); + } } 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 89382d10e..e0b1824ab 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 @@ -457,8 +457,14 @@ public abstract class KineticTileEntity extends SmartTileEntity } public static AxisAlignedBB NOWHERE_AABB = new AxisAlignedBB(Double.NaN, Double.NaN, Double.NaN, Double.NaN, Double.NaN, Double.NaN); + @Override public AxisAlignedBB getRenderBoundingBox() { return super.getRenderBoundingBox(); } + + @Override + public double getMaxRenderDistanceSquared() { + return 16384.0D; // TODO: make this a config option + } } 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 bfb3ce64e..21d520f33 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 @@ -2,21 +2,17 @@ package com.simibubi.create.content.contraptions.base; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlocks; -import com.simibubi.create.CreateClient; import com.simibubi.create.content.contraptions.KineticDebugger; 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.render.instancing.IInstancedTileEntityRenderer; -import com.simibubi.create.foundation.utility.render.instancing.RotatingBuffer; +import com.simibubi.create.foundation.utility.render.instancing.*; 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; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.RenderTypeLookup; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.util.Direction; @@ -48,32 +44,36 @@ public class KineticTileEntityRenderer extends SafeTileEntityRenderer(te)); } @Override - public void addInstanceData(KineticTileEntity te) { - renderRotatingBuffer(te, getRotatedModel(te)); + public void addInstanceData(InstanceContext ctx) { + renderRotatingBuffer(ctx, getRotatedModel(ctx)); } - public static void renderRotatingKineticBlock(KineticTileEntity te, BlockState renderedState) { - RotatingBuffer instancedRenderer = CreateClient.kineticRenderer.renderBlockInstanced(KINETIC_TILE, renderedState); - renderRotatingBuffer(te, instancedRenderer); + public static void renderRotatingKineticBlock(InstanceContext ctx, BlockState renderedState) { + InstanceBuffer instancedRenderer = ctx.getKinetics().renderBlockInstanced(KINETIC_TILE, renderedState); + renderRotatingBuffer(ctx, instancedRenderer); } - public static void renderRotatingBuffer(KineticTileEntity te, RotatingBuffer instancer) { + public static void renderRotatingBuffer(InstanceContext ctx, InstanceBuffer instancer) { instancer.setupInstance(data -> { + T te = ctx.te; final BlockPos pos = te.getPos(); Axis axis = ((IRotate) te.getBlockState() .getBlock()).getRotationAxis(te.getBlockState()); - data - .setBlockLight(te.getWorld().getLightLevel(LightType.BLOCK, te.getPos())) - .setSkyLight(te.getWorld().getLightLevel(LightType.SKY, te.getPos())) - .setRotationalSpeed(te.getSpeed()) - .setRotationOffset(getRotationOffsetForPosition(te, pos, axis)) - .setRotationAxis(Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis).getUnitVector()) - .setPosition(pos); + data.setRotationalSpeed(te.getSpeed()) + .setRotationOffset(getRotationOffsetForPosition(te, pos, axis)) + .setRotationAxis(Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis).getUnitVector()) + .setPosition(pos); + + if (ctx.checkWorldLight()) { + data.setBlockLight(te.getWorld().getLightLevel(LightType.BLOCK, te.getPos())) + .setSkyLight(te.getWorld().getLightLevel(LightType.SKY, te.getPos())); + } }); } @@ -139,8 +139,8 @@ public class KineticTileEntityRenderer extends SafeTileEntityRenderer getRotatedModel(InstanceContext ctx) { + return ctx.getKinetics().renderBlockInstanced(KINETIC_TILE, getRenderedBlockState(ctx.te)); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillRenderer.java index 636a7f89d..b0a9324f8 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillRenderer.java @@ -10,7 +10,8 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Mov import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.MatrixStacker; -import com.simibubi.create.foundation.utility.render.instancing.RotatingBuffer; +import com.simibubi.create.foundation.utility.render.instancing.InstanceBuffer; +import com.simibubi.create.foundation.utility.render.instancing.InstanceContext; import com.simibubi.create.foundation.utility.render.SuperByteBuffer; import com.simibubi.create.foundation.utility.VecHelper; @@ -28,8 +29,8 @@ public class DrillRenderer extends KineticTileEntityRenderer { } @Override - protected RotatingBuffer getRotatedModel(KineticTileEntity te) { - return AllBlockPartials.DRILL_HEAD.renderOnDirectionalSouthRotating(te.getBlockState()); + protected InstanceBuffer getRotatedModel(InstanceContext ctx) { + return AllBlockPartials.DRILL_HEAD.renderOnDirectionalSouthRotating(ctx, ctx.te.getBlockState()); } protected static SuperByteBuffer getRotatingModel(BlockState state) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/clock/CuckooClockRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/clock/CuckooClockRenderer.java index d978ac439..a3d11138a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/clock/CuckooClockRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/clock/CuckooClockRenderer.java @@ -8,7 +8,7 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.content.contraptions.components.clock.CuckooClockTileEntity.Animation; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.render.instancing.InstanceBuffer; -import com.simibubi.create.foundation.utility.render.instancing.RotatingBuffer; +import com.simibubi.create.foundation.utility.render.instancing.InstanceContext; import com.simibubi.create.foundation.utility.render.SuperByteBuffer; import com.simibubi.create.foundation.utility.render.instancing.RotatingData; @@ -93,14 +93,9 @@ public class CuckooClockRenderer extends KineticTileEntityRenderer { } @Override - protected RotatingBuffer getRotatedModel(KineticTileEntity te) { - return transform(AllBlockPartials.SHAFT_HALF, te); - } - - private RotatingBuffer transform(AllBlockPartials partial, KineticTileEntity te) { - return partial.renderOnDirectionalSouthRotating(te.getBlockState(), te.getBlockState() - .get(CuckooClockBlock.HORIZONTAL_FACING) - .getOpposite()); + protected InstanceBuffer getRotatedModel(InstanceContext ctx) { + BlockState blockState = ctx.te.getBlockState(); + return AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(ctx, blockState, blockState.get(CuckooClockBlock.HORIZONTAL_FACING).getOpposite()); } private SuperByteBuffer rotateHand(SuperByteBuffer buffer, float angle, Direction facing) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerRenderer.java index 48ff5a7d4..92b4d5273 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerRenderer.java @@ -20,6 +20,7 @@ import com.simibubi.create.foundation.utility.render.SuperByteBuffer; import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.render.instancing.IInstancedTileEntityRenderer; +import com.simibubi.create.foundation.utility.render.instancing.InstanceContext; import net.minecraft.block.BlockState; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.IRenderTypeBuffer; @@ -51,12 +52,11 @@ public class DeployerRenderer extends SafeTileEntityRenderer FilteringRenderer.renderOnTileEntity(te, partialTicks, ms, buffer, light, overlay); renderComponents(te, partialTicks, ms, buffer, light, overlay); - addInstanceData(te); } @Override - public void addInstanceData(DeployerTileEntity te) { - KineticTileEntityRenderer.renderRotatingKineticBlock(te, getRenderedBlockState(te)); + public void addInstanceData(InstanceContext ctx) { + KineticTileEntityRenderer.renderRotatingKineticBlock(ctx, getRenderedBlockState(ctx.te)); } protected void renderItem(DeployerTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, @@ -110,7 +110,7 @@ public class DeployerRenderer 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)); + KineticTileEntityRenderer.renderRotatingKineticBlock(new InstanceContext.World<>(te), getRenderedBlockState(te)); BlockState blockState = te.getBlockState(); BlockPos pos = te.getPos(); 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 e26d8b77d..d634a5823 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 @@ -8,7 +8,10 @@ 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.render.instancing.InstanceBuffer; +import com.simibubi.create.foundation.utility.render.instancing.InstanceContext; import com.simibubi.create.foundation.utility.render.instancing.RotatingBuffer; +import com.simibubi.create.foundation.utility.render.instancing.RotatingData; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; @@ -26,24 +29,21 @@ public class EncasedFanRenderer extends KineticTileEntityRenderer { @Override protected void renderSafe(KineticTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { - addInstanceData(te); + super.renderSafe(te, partialTicks, ms, buffer, light, overlay); } @Override - public void addInstanceData(KineticTileEntity te) { + public void addInstanceData(InstanceContext ctx) { + KineticTileEntity te = ctx.te; Direction direction = te.getBlockState() .get(FACING); - BlockPos inFront = te.getPos().offset(direction); - int blockLight = te.getWorld().getLightLevel(LightType.BLOCK, inFront); - int skyLight = te.getWorld().getLightLevel(LightType.SKY, inFront); + InstanceBuffer shaftHalf = + AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(ctx, te.getBlockState(), direction.getOpposite()); + InstanceBuffer fanInner = + AllBlockPartials.ENCASED_FAN_INNER.renderOnDirectionalSouthRotating(ctx, te.getBlockState(), direction.getOpposite()); - RotatingBuffer shaftHalf = - AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(te.getBlockState(), direction.getOpposite()); - RotatingBuffer fanInner = - AllBlockPartials.ENCASED_FAN_INNER.renderOnDirectionalSouthRotating(te.getBlockState(), direction.getOpposite()); - - renderRotatingBuffer(te, shaftHalf); + renderRotatingBuffer(ctx, shaftHalf); fanInner.setupInstance(data -> { final BlockPos pos = te.getPos(); Direction.Axis axis = ((IRotate) te.getBlockState() @@ -55,12 +55,19 @@ public class EncasedFanRenderer extends KineticTileEntityRenderer { if (speed < 0) speed = MathHelper.clamp(speed, -64 * 20, -80); - data.setBlockLight(blockLight) - .setSkyLight(skyLight) - .setRotationalSpeed(speed) + data.setRotationalSpeed(speed) .setRotationOffset(getRotationOffsetForPosition(te, pos, axis)) .setRotationAxis(Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, axis).getUnitVector()) .setPosition(pos); + + if (ctx.checkWorldLight()) { + BlockPos inFront = te.getPos().offset(direction); + int blockLight = te.getWorld().getLightLevel(LightType.BLOCK, inFront); + int skyLight = te.getWorld().getLightLevel(LightType.SKY, inFront); + + data.setBlockLight(blockLight) + .setSkyLight(skyLight); + } }); } } 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 563fe72b2..ae072d95d 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,10 +9,10 @@ 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.render.instancing.InstanceBuffer; import com.simibubi.create.foundation.utility.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.render.instancing.RotatingBuffer; +import com.simibubi.create.foundation.utility.render.instancing.InstanceBuffer; +import com.simibubi.create.foundation.utility.render.instancing.InstanceContext; import com.simibubi.create.foundation.utility.render.instancing.RotatingData; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; @@ -77,8 +77,8 @@ public class FlywheelRenderer extends KineticTileEntityRenderer { } @Override - protected RotatingBuffer getRotatedModel(KineticTileEntity te) { - return AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(te.getBlockState(), te.getBlockState() + protected InstanceBuffer getRotatedModel(InstanceContext ctx) { + return AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(ctx, ctx.te.getBlockState(), ctx.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 67dd39cb0..7a0e86232 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 @@ -1,12 +1,11 @@ package com.simibubi.create.content.contraptions.components.millstone; 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.render.instancing.InstanceBuffer; -import com.simibubi.create.foundation.utility.render.instancing.RotatingBuffer; +import com.simibubi.create.foundation.utility.render.instancing.InstanceContext; import com.simibubi.create.foundation.utility.render.instancing.RotatingData; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; @@ -17,8 +16,8 @@ public class MillstoneRenderer extends KineticTileEntityRenderer { } @Override - protected RotatingBuffer getRotatedModel(KineticTileEntity te) { - return CreateClient.kineticRenderer.renderPartialRotating(AllBlockPartials.MILLSTONE_COG, te.getBlockState()); + protected InstanceBuffer getRotatedModel(InstanceContext ctx) { + return AllBlockPartials.MILLSTONE_COG.renderOnRotating(ctx, ctx.te.getBlockState()); } } 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 902e25c47..a52a7d586 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 @@ -5,7 +5,7 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.foundation.utility.render.instancing.InstanceBuffer; -import com.simibubi.create.foundation.utility.render.instancing.RotatingBuffer; +import com.simibubi.create.foundation.utility.render.instancing.InstanceContext; import com.simibubi.create.foundation.utility.render.instancing.RotatingData; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; @@ -16,8 +16,8 @@ public class CreativeMotorRenderer extends KineticTileEntityRenderer { } @Override - protected RotatingBuffer getRotatedModel(KineticTileEntity te) { - return AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(te.getBlockState()); + protected InstanceBuffer getRotatedModel(InstanceContext ctx) { + return AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(ctx, ctx.te.getBlockState()); } } 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 05d1ba113..299173139 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 @@ -12,8 +12,7 @@ import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringRe import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; import com.simibubi.create.foundation.utility.*; -import com.simibubi.create.foundation.utility.render.instancing.IInstancedTileEntityRenderer; -import com.simibubi.create.foundation.utility.render.instancing.RotatingBuffer; +import com.simibubi.create.foundation.utility.render.instancing.*; import com.simibubi.create.foundation.utility.render.SuperByteBuffer; import net.minecraft.block.BlockState; import net.minecraft.client.Minecraft; @@ -43,12 +42,11 @@ public class SawRenderer extends SafeTileEntityRenderer implement renderItems(te, partialTicks, ms, buffer, light, overlay); FilteringRenderer.renderOnTileEntity(te, partialTicks, ms, buffer, light, overlay); - addInstanceData(te); } @Override - public void addInstanceData(SawTileEntity te) { - KineticTileEntityRenderer.renderRotatingBuffer(te, getRotatedModel(te)); + public void addInstanceData(InstanceContext ctx) { + KineticTileEntityRenderer.renderRotatingBuffer(ctx, getRotatedModel(ctx)); } protected void renderBlade(SawTileEntity te, MatrixStack ms, IRenderTypeBuffer buffer, int light){ @@ -86,7 +84,7 @@ public class SawRenderer extends SafeTileEntityRenderer implement } protected void renderShaft(SawTileEntity te, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { - KineticTileEntityRenderer.renderRotatingBuffer(te, getRotatedModel(te)); + //KineticTileEntityRenderer.renderRotatingBuffer(te, getRotatedModel(te)); } protected void renderItems(SawTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light, @@ -130,11 +128,12 @@ public class SawRenderer extends SafeTileEntityRenderer implement } } - protected RotatingBuffer getRotatedModel(KineticTileEntity te) { + protected InstanceBuffer getRotatedModel(InstanceContext ctx) { + KineticTileEntity te = ctx.te; BlockState state = te.getBlockState(); if (state.get(FACING).getAxis().isHorizontal()) - return AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(state.rotate(te.getWorld(), te.getPos(), Rotation.CLOCKWISE_180)); - return CreateClient.kineticRenderer.renderBlockInstanced(KineticTileEntityRenderer.KINETIC_TILE, + return AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(ctx, state.rotate(te.getWorld(), te.getPos(), Rotation.CLOCKWISE_180)); + return ctx.getKinetics().renderBlockInstanced(KineticTileEntityRenderer.KINETIC_TILE, getRenderedBlockState(te)); } 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 b53ea6f5f..1af98d926 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,11 +5,12 @@ 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.render.instancing.InstanceBuffer; import com.simibubi.create.foundation.utility.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.render.instancing.RotatingBuffer; +import com.simibubi.create.foundation.utility.render.instancing.InstanceBuffer; +import com.simibubi.create.foundation.utility.render.instancing.InstanceContext; import com.simibubi.create.foundation.utility.render.instancing.RotatingData; +import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; @@ -46,10 +47,9 @@ public class BearingRenderer extends KineticTileEntityRenderer { } @Override - protected RotatingBuffer getRotatedModel(KineticTileEntity te) { - return AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(te.getBlockState(), te.getBlockState() - .get(BearingBlock.FACING) - .getOpposite()); + protected InstanceBuffer getRotatedModel(InstanceContext ctx) { + BlockState blockState = ctx.te.getBlockState(); + return AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(ctx, blockState, blockState.get(BearingBlock.FACING).getOpposite()); } } 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 fee2c8993..89c8ec4ea 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,10 +6,10 @@ 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.render.instancing.InstanceBuffer; import com.simibubi.create.foundation.utility.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.render.instancing.RotatingBuffer; +import com.simibubi.create.foundation.utility.render.instancing.InstanceBuffer; +import com.simibubi.create.foundation.utility.render.instancing.InstanceContext; import com.simibubi.create.foundation.utility.render.instancing.RotatingData; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; @@ -54,8 +54,8 @@ public class PumpRenderer extends KineticTileEntityRenderer { } @Override - protected RotatingBuffer getRotatedModel(KineticTileEntity te) { - return AllBlockPartials.MECHANICAL_PUMP_COG.renderOnDirectionalSouthRotating(te.getBlockState()); + protected InstanceBuffer getRotatedModel(InstanceContext ctx) { + return AllBlockPartials.MECHANICAL_PUMP_COG.renderOnDirectionalSouthRotating(ctx, ctx.te.getBlockState()); } } 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 25cf15b8f..f16a7e9a8 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 @@ -5,8 +5,7 @@ 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.render.instancing.IInstancedTileEntityRenderer; -import com.simibubi.create.foundation.utility.render.instancing.RotatingBuffer; +import com.simibubi.create.foundation.utility.render.instancing.*; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; @@ -21,15 +20,14 @@ public class SpeedControllerRenderer extends SmartTileEntityRenderer ctx) { + KineticTileEntityRenderer.renderRotatingBuffer(ctx, getRotatedModel(ctx.te)); } - private RotatingBuffer getRotatedModel(SpeedControllerTileEntity te) { + private InstanceBuffer getRotatedModel(SpeedControllerTileEntity te) { return CreateClient.kineticRenderer.renderBlockInstanced(KineticTileEntityRenderer.KINETIC_TILE, KineticTileEntityRenderer.shaft(KineticTileEntityRenderer.getRotationAxisOf(te))); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltRenderer.java index 6e7731d36..38a7d6587 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltRenderer.java @@ -1,6 +1,8 @@ package com.simibubi.create.content.contraptions.relays.belt; import java.util.Random; +import java.util.function.BiFunction; +import java.util.function.Function; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; @@ -13,9 +15,9 @@ import com.simibubi.create.foundation.block.render.SpriteShiftEntry; import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.MatrixStacker; -import com.simibubi.create.foundation.utility.render.instancing.BeltBuffer; -import com.simibubi.create.foundation.utility.render.instancing.IInstancedTileEntityRenderer; -import com.simibubi.create.foundation.utility.render.instancing.RotatingBuffer; +import com.simibubi.create.foundation.utility.render.FastContraptionRenderer; +import com.simibubi.create.foundation.utility.render.FastKineticRenderer; +import com.simibubi.create.foundation.utility.render.instancing.*; import com.simibubi.create.foundation.utility.render.ShadowRenderHelper; import net.minecraft.block.BlockState; @@ -51,13 +53,13 @@ public class BeltRenderer extends SafeTileEntityRenderer impleme if (!AllBlocks.BELT.has(blockState)) return; - addInstanceData(te); - + addInstanceData(new InstanceContext.World<>(te)); renderItems(te, partialTicks, ms, buffer, light, overlay); } @Override - public void addInstanceData(BeltTileEntity te) { + public void addInstanceData(InstanceContext ctx) { + BeltTileEntity te = ctx.te; BlockState blockState = te.getBlockState(); if (!AllBlocks.BELT.has(blockState)) return; @@ -83,6 +85,8 @@ public class BeltRenderer extends SafeTileEntityRenderer impleme end = b; } + FastKineticRenderer fastKineticRenderer = ctx.getKinetics(); + for (boolean bottom : Iterate.trueAndFalse) { AllBlockPartials beltPartial = diagonal @@ -94,7 +98,7 @@ public class BeltRenderer extends SafeTileEntityRenderer impleme : start ? AllBlockPartials.BELT_START : end ? AllBlockPartials.BELT_END : AllBlockPartials.BELT_MIDDLE; - BeltBuffer beltBuffer = beltPartial.renderOnBelt(blockState); + InstanceBuffer beltBuffer = beltPartial.renderOnBelt(ctx, blockState); SpriteShiftEntry spriteShift = diagonal ? AllSpriteShifts.BELT_DIAGONAL : bottom ? AllSpriteShifts.BELT_OFFSET : AllSpriteShifts.BELT; @@ -139,9 +143,9 @@ public class BeltRenderer extends SafeTileEntityRenderer impleme msr.rotateX(90); msr.unCentre(); - RotatingBuffer rotatingBuffer = CreateClient.kineticRenderer + InstanceBuffer rotatingBuffer = fastKineticRenderer .renderDirectionalPartialInstanced(AllBlockPartials.BELT_PULLEY, blockState, dir, modelTransform); - KineticTileEntityRenderer.renderRotatingBuffer(te, rotatingBuffer); + KineticTileEntityRenderer.renderRotatingBuffer(ctx, rotatingBuffer); } } 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 2b9660e6a..6785f5660 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 @@ -7,7 +7,10 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.render.instancing.InstanceBuffer; +import com.simibubi.create.foundation.utility.render.instancing.InstanceContext; import com.simibubi.create.foundation.utility.render.instancing.RotatingBuffer; +import com.simibubi.create.foundation.utility.render.instancing.RotatingData; import net.minecraft.block.Block; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; @@ -25,18 +28,26 @@ public class SplitShaftRenderer extends KineticTileEntityRenderer { @Override protected void renderSafe(KineticTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { - - addInstanceData(te); + super.renderSafe(te, partialTicks, ms, buffer, light, overlay); } @Override - public void addInstanceData(KineticTileEntity te) { + public void addInstanceData(InstanceContext ctx) { + KineticTileEntity te = ctx.te; Block block = te.getBlockState().getBlock(); final Axis boxAxis = ((IRotate) block).getRotationAxis(te.getBlockState()); final BlockPos pos = te.getPos(); - int blockLight = te.getWorld().getLightLevel(LightType.BLOCK, te.getPos()); - int skyLight = te.getWorld().getLightLevel(LightType.SKY, te.getPos()); + int blockLight; + int skyLight; + + if (ctx.checkWorldLight()) { + blockLight = te.getWorld().getLightLevel(LightType.BLOCK, te.getPos()); + skyLight = te.getWorld().getLightLevel(LightType.SKY, te.getPos()); + } else { + blockLight = 0; + skyLight = 0; + } for (Direction direction : Iterate.directions) { Axis axis = direction.getAxis(); @@ -44,7 +55,7 @@ public class SplitShaftRenderer extends KineticTileEntityRenderer { continue; - RotatingBuffer shaft = AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(te.getBlockState(), direction); + InstanceBuffer shaft = AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(ctx, te.getBlockState(), direction); shaft.setupInstance(data -> { float speed = te.getSpeed(); 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 94705946b..00b74854d 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 @@ -6,7 +6,10 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.render.instancing.InstanceBuffer; +import com.simibubi.create.foundation.utility.render.instancing.InstanceContext; import com.simibubi.create.foundation.utility.render.instancing.RotatingBuffer; +import com.simibubi.create.foundation.utility.render.instancing.RotatingData; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; import net.minecraft.state.properties.BlockStateProperties; @@ -24,18 +27,32 @@ public class GearboxRenderer extends KineticTileEntityRenderer { @Override protected void renderSafe(KineticTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { + super.renderSafe(te, partialTicks, ms, buffer, light, overlay); + } + + @Override + public void addInstanceData(InstanceContext ctx) { + KineticTileEntity te = ctx.te; final Axis boxAxis = te.getBlockState().get(BlockStateProperties.AXIS); final BlockPos pos = te.getPos(); - int blockLight = te.getWorld().getLightLevel(LightType.BLOCK, te.getPos()); - int skyLight = te.getWorld().getLightLevel(LightType.SKY, te.getPos()); + int blockLight; + int skyLight; + + if (ctx.checkWorldLight()) { + blockLight = te.getWorld().getLightLevel(LightType.BLOCK, te.getPos()); + skyLight = te.getWorld().getLightLevel(LightType.SKY, te.getPos()); + } else { + blockLight = 0; + skyLight = 0; + } for (Direction direction : Iterate.directions) { final Axis axis = direction.getAxis(); if (boxAxis == axis) continue; - RotatingBuffer shaft = AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(te.getBlockState(), direction); + InstanceBuffer shaft = AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(ctx, te.getBlockState(), direction); shaft.setupInstance(data -> { float speed = te.getSpeed(); @@ -58,5 +75,4 @@ public class GearboxRenderer extends KineticTileEntityRenderer { }); } } - } 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 a41f7a4cc..c89f6b956 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 @@ -8,9 +8,9 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.content.logistics.block.mechanicalArm.ArmTileEntity.Phase; import com.simibubi.create.foundation.utility.*; -import com.simibubi.create.foundation.utility.render.instancing.InstanceBuffer; import com.simibubi.create.foundation.utility.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.render.instancing.RotatingBuffer; +import com.simibubi.create.foundation.utility.render.instancing.InstanceBuffer; +import com.simibubi.create.foundation.utility.render.instancing.InstanceContext; import com.simibubi.create.foundation.utility.render.instancing.RotatingData; import net.minecraft.block.BlockState; import net.minecraft.client.Minecraft; @@ -118,8 +118,8 @@ public class ArmRenderer extends KineticTileEntityRenderer { } @Override - protected RotatingBuffer getRotatedModel(KineticTileEntity te) { - return AllBlockPartials.ARM_COG.renderOnRotating(te.getBlockState()); + protected InstanceBuffer getRotatedModel(InstanceContext ctx) { + return AllBlockPartials.ARM_COG.renderOnRotating(ctx, ctx.te.getBlockState()); } } diff --git a/src/main/java/com/simibubi/create/events/ClientEvents.java b/src/main/java/com/simibubi/create/events/ClientEvents.java index 7c4aec461..2a88508ee 100644 --- a/src/main/java/com/simibubi/create/events/ClientEvents.java +++ b/src/main/java/com/simibubi/create/events/ClientEvents.java @@ -37,6 +37,7 @@ import com.simibubi.create.foundation.utility.render.RenderWork; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.ActiveRenderInfo; import net.minecraft.client.renderer.IRenderTypeBuffer; +import net.minecraft.client.renderer.Matrix4f; import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.fluid.Fluid; import net.minecraft.fluid.IFluidState; @@ -112,21 +113,25 @@ public class ClientEvents { @SubscribeEvent public static void onLoadWorld(WorldEvent.Load event) { - CreateClient.bufferCache.invalidate(); - CreateClient.kineticRenderer.invalidate(); - FastContraptionRenderer.invalidateAll(); + CreateClient.invalidateRenderers(); } @SubscribeEvent public static void onRenderWorld(RenderWorldLastEvent event) { - CreateClient.kineticRenderer.renderInstances(event); - FastContraptionRenderer.renderAll(event); + Matrix4f projection = event.getProjectionMatrix(); + // view matrix + Vec3d cameraPos = Minecraft.getInstance().gameRenderer.getActiveRenderInfo().getProjectedView(); + + Matrix4f view = Matrix4f.translate((float) -cameraPos.x, (float) -cameraPos.y, (float) -cameraPos.z); + view.multiplyBackward(event.getMatrixStack().peek().getModel()); + + CreateClient.kineticRenderer.renderInstancesAsWorld(projection, view); + FastContraptionRenderer.renderAll(projection, view); MatrixStack ms = event.getMatrixStack(); ActiveRenderInfo info = Minecraft.getInstance().gameRenderer.getActiveRenderInfo(); - Vec3d view = info.getProjectedView(); ms.push(); - ms.translate(-view.getX(), -view.getY(), -view.getZ()); + ms.translate(-cameraPos.getX(), -cameraPos.getY(), -cameraPos.getZ()); SuperRenderTypeBuffer buffer = SuperRenderTypeBuffer.getInstance(); CouplingRenderer.renderAll(ms, buffer); diff --git a/src/main/java/com/simibubi/create/foundation/ResourceReloadHandler.java b/src/main/java/com/simibubi/create/foundation/ResourceReloadHandler.java index 7809c8bc5..a5ee6a1c7 100644 --- a/src/main/java/com/simibubi/create/foundation/ResourceReloadHandler.java +++ b/src/main/java/com/simibubi/create/foundation/ResourceReloadHandler.java @@ -18,9 +18,7 @@ public class ResourceReloadHandler extends ReloadListener { @Override protected void apply(Object $, IResourceManager resourceManagerIn, IProfiler profilerIn) { SpriteShifter.reloadUVs(); - CreateClient.bufferCache.invalidate(); - CreateClient.kineticRenderer.invalidate(); - FastContraptionRenderer.invalidateAll(); + CreateClient.invalidateRenderers(); } } diff --git a/src/main/java/com/simibubi/create/foundation/command/ClearBufferCacheCommand.java b/src/main/java/com/simibubi/create/foundation/command/ClearBufferCacheCommand.java index 159f96861..3dc3d23a3 100644 --- a/src/main/java/com/simibubi/create/foundation/command/ClearBufferCacheCommand.java +++ b/src/main/java/com/simibubi/create/foundation/command/ClearBufferCacheCommand.java @@ -23,8 +23,6 @@ public class ClearBufferCacheCommand { @OnlyIn(Dist.CLIENT) private static void execute() { - CreateClient.bufferCache.invalidate(); - CreateClient.kineticRenderer.invalidate(); - FastContraptionRenderer.invalidateAll(); + CreateClient.invalidateRenderers(); } } diff --git a/src/main/java/com/simibubi/create/foundation/utility/render/ContraptionBuffer.java b/src/main/java/com/simibubi/create/foundation/utility/render/ContraptionBuffer.java index 9f4e0f697..5c2a8f2c5 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/render/ContraptionBuffer.java +++ b/src/main/java/com/simibubi/create/foundation/utility/render/ContraptionBuffer.java @@ -1,11 +1,9 @@ package com.simibubi.create.foundation.utility.render; import com.mojang.blaze3d.platform.GlStateManager; -import com.simibubi.create.CreateClient; import com.simibubi.create.foundation.utility.render.instancing.VertexFormat; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.GLAllocation; -import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.client.renderer.vertex.VertexFormatElement; import org.lwjgl.opengl.*; import org.lwjgl.system.MemoryUtil; @@ -43,7 +41,7 @@ public class ContraptionBuffer extends TemplateBuffer { GlStateManager.bindBuffers(GL15.GL_ELEMENT_ARRAY_BUFFER, ebo); - GL40.glDrawElements(GL11.GL_QUADS, count, GL11.GL_UNSIGNED_SHORT, 0); + GL40.glDrawElements(GL11.GL_QUADS, vertexCount, GL11.GL_UNSIGNED_SHORT, 0); for (int i = 0; i <= FORMAT.getNumAttributes(); i++) { GL40.glDisableVertexAttribArray(i); @@ -55,55 +53,50 @@ public class ContraptionBuffer extends TemplateBuffer { private void setup() { int stride = FORMAT.getStride(); - int invariantSize = count * stride; + int invariantSize = vertexCount * stride; - ByteBuffer constant = GLAllocation.createDirectByteBuffer(invariantSize); - constant.order(template.order()); - ((Buffer) constant).limit(invariantSize); + GlStateManager.bindBuffers(GL15.GL_ARRAY_BUFFER, 0); + GlStateManager.bindBuffers(GL15.GL_ELEMENT_ARRAY_BUFFER, 0); + // Deselect (bind to 0) the VAO + GL30.glBindVertexArray(0); - int indicesSize = count * VertexFormatElement.Type.USHORT.getSize(); - ByteBuffer indices = GLAllocation.createDirectByteBuffer(indicesSize); - indices.order(template.order()); - ((Buffer) indices).limit(indicesSize); + try (SafeDirectBuffer constant = new SafeDirectBuffer(invariantSize)) { + constant.order(template.order()); + constant.limit(invariantSize); - 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)); + 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.put(getNX(template, i)); + constant.put(getNY(template, i)); + constant.put(getNZ(template, i)); - constant.putFloat(getU(template, i)); - constant.putFloat(getV(template, i)); + constant.putFloat(getU(template, i)); + constant.putFloat(getV(template, i)); - constant.putFloat(getR(template, i) / 255f); - constant.putFloat(getG(template, i) / 255f); - constant.putFloat(getB(template, i) / 255f); - constant.putFloat(getA(template, i) / 255f); + constant.put(getR(template, i)); + constant.put(getG(template, i)); + constant.put(getB(template, i)); + constant.put(getA(template, i)); + } + constant.rewind(); + + vao = GL30.glGenVertexArrays(); + GL30.glBindVertexArray(vao); + + ebo = GlStateManager.genBuffers(); + vbo = GlStateManager.genBuffers(); + + GlStateManager.bindBuffers(GL15.GL_ARRAY_BUFFER, vbo); + GlStateManager.bufferData(GL15.GL_ARRAY_BUFFER, constant.getBacking(), GL15.GL_STATIC_DRAW); + buildEBO(ebo); + + FORMAT.informAttributes(0); + } catch (Exception e) { - indices.putShort((short) i); } - constant.rewind(); - indices.rewind(); - - vao = GL30.glGenVertexArrays(); - GL30.glBindVertexArray(vao); - - ebo = GlStateManager.genBuffers(); - vbo = GlStateManager.genBuffers(); - - GlStateManager.bindBuffers(GL15.GL_ARRAY_BUFFER, vbo); - GlStateManager.bufferData(GL15.GL_ARRAY_BUFFER, constant, GL15.GL_STATIC_DRAW); - MemoryUtil.memFree(constant); - - GlStateManager.bindBuffers(GL15.GL_ELEMENT_ARRAY_BUFFER, ebo); - GlStateManager.bufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, indices, GL15.GL_STATIC_DRAW); - MemoryUtil.memFree(indices); - - FORMAT.informAttributes(0); GlStateManager.bindBuffers(GL15.GL_ARRAY_BUFFER, 0); GlStateManager.bindBuffers(GL15.GL_ELEMENT_ARRAY_BUFFER, 0); diff --git a/src/main/java/com/simibubi/create/foundation/utility/render/ContraptionLighter.java b/src/main/java/com/simibubi/create/foundation/utility/render/ContraptionLighter.java index d4907f697..083924da3 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/render/ContraptionLighter.java +++ b/src/main/java/com/simibubi/create/foundation/utility/render/ContraptionLighter.java @@ -2,6 +2,7 @@ package com.simibubi.create.foundation.utility.render; import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; import net.minecraft.client.renderer.GLAllocation; +import net.minecraft.client.renderer.RenderType; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; @@ -132,22 +133,19 @@ public class ContraptionLighter { public void use() { if (texture == 0 || lightVolume == null) return; - GL13.glEnable(GL31.GL_TEXTURE_3D); - GL13.glActiveTexture(GL40.GL_TEXTURE0 + 4); GL12.glBindTexture(GL12.GL_TEXTURE_3D, texture); + GL11.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_MIN_FILTER, GL13.GL_LINEAR); + GL11.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_MAG_FILTER, GL13.GL_LINEAR); + GL11.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_WRAP_S, GL13.GL_CLAMP); + GL11.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_WRAP_R, GL13.GL_CLAMP); + GL11.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_WRAP_T, GL13.GL_CLAMP); if (dirty) { GL12.glTexImage3D(GL12.GL_TEXTURE_3D, 0, GL40.GL_RG8, sizeX, sizeY, sizeZ, 0, GL40.GL_RG, GL40.GL_UNSIGNED_BYTE, lightVolume); dirty = false; } - GL40.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_MIN_FILTER, GL13.GL_LINEAR); - GL40.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_MAG_FILTER, GL13.GL_LINEAR); - GL40.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_WRAP_S, GL13.GL_CLAMP); - GL40.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_WRAP_R, GL13.GL_CLAMP); - GL40.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_WRAP_T, GL13.GL_CLAMP); } public void release() { - GL13.glActiveTexture(GL40.GL_TEXTURE0 + 4); GL12.glBindTexture(GL12.GL_TEXTURE_3D, 0); } } diff --git a/src/main/java/com/simibubi/create/foundation/utility/render/FastContraptionRenderer.java b/src/main/java/com/simibubi/create/foundation/utility/render/FastContraptionRenderer.java index 8aeaa533c..465946b71 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/render/FastContraptionRenderer.java +++ b/src/main/java/com/simibubi/create/foundation/utility/render/FastContraptionRenderer.java @@ -1,16 +1,23 @@ package com.simibubi.create.foundation.utility.render; import com.mojang.blaze3d.platform.GlStateManager; -import com.simibubi.create.CreateClient; import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionRenderer; +import com.simibubi.create.foundation.utility.render.instancing.IInstanceRendered; +import com.simibubi.create.foundation.utility.render.instancing.IInstancedTileEntityRenderer; import com.simibubi.create.foundation.utility.render.shader.Shader; +import com.simibubi.create.foundation.utility.render.shader.ShaderCallback; import com.simibubi.create.foundation.utility.render.shader.ShaderHelper; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.*; +import net.minecraft.client.renderer.tileentity.TileEntityRenderer; +import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; +import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -import net.minecraftforge.client.event.RenderWorldLastEvent; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL13; +import org.lwjgl.opengl.GL40; import java.nio.FloatBuffer; import java.util.ArrayList; @@ -25,6 +32,8 @@ public class FastContraptionRenderer extends ContraptionRenderer { private ContraptionLighter lighter; + public final FastKineticRenderer kinetics; + private Contraption c; private Vec3d renderPos; @@ -33,18 +42,49 @@ public class FastContraptionRenderer extends ContraptionRenderer { public FastContraptionRenderer(World world, Contraption c) { this.c = c; this.lighter = new ContraptionLighter(c); + this.kinetics = new FastKineticRenderer(); - buildLayers(); + buildLayers(c); + buildInstancedTiles(c); + } + + private void buildLayers(Contraption c) { + for (ContraptionBuffer buffer : renderLayers) { + buffer.delete(); + } + + renderLayers.clear(); + + List blockLayers = RenderType.getBlockLayers(); + + for (RenderType layer : blockLayers) { + renderLayers.add(buildStructureBuffer(c, layer)); + } + } + + private void buildInstancedTiles(Contraption c) { + List tileEntities = c.renderedTileEntities; + if (!tileEntities.isEmpty()) { + for (TileEntity te : tileEntities) { + if (te instanceof IInstanceRendered) { + TileEntityRenderer renderer = TileEntityRendererDispatcher.instance.getRenderer(te); + + if (renderer instanceof IInstancedTileEntityRenderer) { + kinetics.addInstancedData(this, te, (IInstancedTileEntityRenderer) renderer); + } + } + } + } + + kinetics.markAllDirty(); } public static void tick() { if (Minecraft.getInstance().isGamePaused()) return; - RenderWork.enqueue(() -> { - for (FastContraptionRenderer renderer : renderers.values()) { - renderer.lighter.update(renderer.c); - } - }); + for (FastContraptionRenderer renderer : renderers.values()) { + renderer.lighter.update(renderer.c); + } } private void setRenderSettings(Vec3d position, Vec3d rotation) { @@ -52,9 +92,16 @@ public class FastContraptionRenderer extends ContraptionRenderer { renderRot = rotation; } - private void render(int shader) { + private void setup(int shader) { + setupShaderUniforms(shader); lighter.use(); + } + private void teardown() { + lighter.release(); + } + + private void setupShaderUniforms(int shader) { FloatBuffer buf = ShaderHelper.VEC3_BUFFER; int lightBoxSize = GlStateManager.getUniformLocation(shader, "lightBoxSize"); @@ -84,26 +131,6 @@ public class FastContraptionRenderer extends ContraptionRenderer { buf.put(2, (float) renderRot.z); buf.rewind(); GlStateManager.uniform3(cRot, buf); - - for (ContraptionBuffer layer : renderLayers) { - layer.render(); - } - - lighter.release(); - } - - private void buildLayers() { - for (ContraptionBuffer buffer : renderLayers) { - buffer.delete(); - } - - renderLayers.clear(); - - List blockLayers = RenderType.getBlockLayers(); - - for (RenderType layer : blockLayers) { - renderLayers.add(buildStructureBuffer(c, layer)); - } } private void invalidate() { @@ -113,6 +140,8 @@ public class FastContraptionRenderer extends ContraptionRenderer { lighter.delete(); + kinetics.invalidate(); + renderLayers.clear(); } @@ -133,26 +162,56 @@ public class FastContraptionRenderer extends ContraptionRenderer { return renderer; } - public static void renderAll(RenderWorldLastEvent event) { + public static void renderAll(Matrix4f projectionMat, Matrix4f viewMat) { + removeDeadContraptions(); + + if (renderers.isEmpty()) return; + GameRenderer gameRenderer = Minecraft.getInstance().gameRenderer; - CreateClient.kineticRenderer.setup(gameRenderer); - GlStateManager.enableCull(); + FastKineticRenderer.setup(gameRenderer); + GL11.glEnable(GL13.GL_TEXTURE_3D); + GL13.glActiveTexture(GL40.GL_TEXTURE4); - ShaderHelper.useShader(Shader.CONTRAPTION_STRUCTURE, ShaderHelper.getViewProjectionCallback(event)); - int shader = ShaderHelper.getShaderHandle(Shader.CONTRAPTION_STRUCTURE); - - ArrayList toRemove = new ArrayList<>(); + ShaderCallback callback = ShaderHelper.getViewProjectionCallback(projectionMat, viewMat); + int structureShader = ShaderHelper.useShader(Shader.CONTRAPTION_STRUCTURE, callback); for (FastContraptionRenderer renderer : renderers.values()) { - if (renderer.c.entity.isAlive()) - renderer.render(shader); - else - toRemove.add(renderer.c.entity.getEntityId()); + renderer.setup(structureShader); + for (ContraptionBuffer layer : renderer.renderLayers) { + layer.render(); + } + renderer.teardown(); + } + + int rotatingShader = ShaderHelper.useShader(Shader.CONTRAPTION_ROTATING, callback); + for (FastContraptionRenderer renderer : renderers.values()) { + renderer.setup(rotatingShader); + renderer.kinetics.renderRotating(); + renderer.teardown(); + } + + int beltShader = ShaderHelper.useShader(Shader.CONTRAPTION_BELT, callback); + for (FastContraptionRenderer renderer : renderers.values()) { + renderer.setup(beltShader); + renderer.kinetics.renderBelts(); + renderer.teardown(); } ShaderHelper.releaseShader(); - CreateClient.kineticRenderer.teardown(); + GL11.glDisable(GL13.GL_TEXTURE_3D); + FastKineticRenderer.teardown(); + } + + public static void removeDeadContraptions() { + ArrayList toRemove = new ArrayList<>(); + + for (FastContraptionRenderer renderer : renderers.values()) { + if (!renderer.c.entity.isAlive()) { + toRemove.add(renderer.c.entity.getEntityId()); + renderer.invalidate(); + } + } for (Integer id : toRemove) { renderers.remove(id); 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 index c014d274d..d28dccf9a 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/render/FastKineticRenderer.java +++ b/src/main/java/com/simibubi/create/foundation/utility/render/FastKineticRenderer.java @@ -3,9 +3,9 @@ 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.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.foundation.utility.render.instancing.*; import com.simibubi.create.foundation.utility.render.shader.Shader; import com.simibubi.create.foundation.utility.render.shader.ShaderCallback; @@ -21,7 +21,6 @@ import net.minecraft.inventory.container.PlayerContainer; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Direction; import net.minecraft.world.World; -import net.minecraftforge.client.event.RenderWorldLastEvent; import org.apache.commons.lang3.tuple.Pair; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL13; @@ -35,8 +34,8 @@ import java.util.function.Supplier; import static com.simibubi.create.foundation.utility.render.SuperByteBufferCache.PARTIAL; public class FastKineticRenderer { - Map, Cache> rotating; - Map, Cache> belts; + Map, Cache>> rotating; + Map, Cache>> belts; boolean rebuild; @@ -46,6 +45,7 @@ public class FastKineticRenderer { registerCompartment(SuperByteBufferCache.GENERIC_TILE); registerCompartment(SuperByteBufferCache.PARTIAL); registerCompartment(SuperByteBufferCache.DIRECTIONAL_PARTIAL); + registerCompartment(KineticTileEntityRenderer.KINETIC_TILE); } public void buildTileEntityBuffers(World world) { @@ -65,66 +65,102 @@ public class FastKineticRenderer { } } - private void addInstancedData(T te, IInstancedTileEntityRenderer renderer) { - renderer.addInstanceData(te); + void addInstancedData(T te, IInstancedTileEntityRenderer renderer) { + renderer.addInstanceData(new InstanceContext.World<>(te)); + } + + void addInstancedData(FastContraptionRenderer c, T te, IInstancedTileEntityRenderer renderer) { + renderer.addInstanceData(new InstanceContext.Contraption<>(te, c)); + } + + /** + * This function should be called after building instances. + * It must be called either on the render thread before committing to rendering, or in a place where there are + * guaranteed to be no race conditions with the render thread, i.e. when constructing a FastContraptionRenderer. + */ + public void markAllDirty() { + for (Cache> cache : rotating.values()) { + for (InstanceBuffer renderer : cache.asMap().values()) { + renderer.markDirty(); + } + } + + for (Cache> cache : belts.values()) { + for (InstanceBuffer renderer : cache.asMap().values()) { + renderer.markDirty(); + } + } } public void tick() { // TODO: (later) detect changes in lighting with a mixin (or forge hook) to ClientChunkProvider.markLightChanged() - for (Cache cache : rotating.values()) { - for (RotatingBuffer renderer : cache.asMap().values()) { + for (Cache> cache : rotating.values()) { + for (InstanceBuffer renderer : cache.asMap().values()) { renderer.clearInstanceData(); } } - for (Cache cache : belts.values()) { - for (BeltBuffer renderer : cache.asMap().values()) { + for (Cache> cache : belts.values()) { + for (InstanceBuffer renderer : cache.asMap().values()) { renderer.clearInstanceData(); } } -// rebuild = true; + //buildTileEntityBuffers(Minecraft.getInstance().world); + + rebuild = true; } - public void renderInstances(RenderWorldLastEvent event) { + void renderBelts() { + for (Cache> cache : belts.values()) { + for (InstanceBuffer type : cache.asMap().values()) { + if (!type.isEmpty()) { + type.render(); + } + } + } + } + + void renderRotating() { + for (Cache> cache : rotating.values()) { + for (InstanceBuffer rotatingDataInstanceBuffer : cache.asMap().values()) { + if (!rotatingDataInstanceBuffer.isEmpty()) { + rotatingDataInstanceBuffer.render(); + } + } + } + } + + public void renderInstancesAsWorld(Matrix4f projection, Matrix4f view) { GameRenderer gameRenderer = Minecraft.getInstance().gameRenderer; -// -// if (rebuild) { -// buildTileEntityBuffers(Minecraft.getInstance().world); -// rebuild = false; -// } + + if (rebuild) { + markAllDirty(); + rebuild = false; + } setup(gameRenderer); - ShaderCallback callback = ShaderHelper.getViewProjectionCallback(event); + ShaderCallback callback = ShaderHelper.getViewProjectionCallback(projection, view); - ShaderHelper.useShader(Shader.ROTATING_INSTANCED, callback); + ShaderHelper.useShader(Shader.ROTATING, callback); + renderRotating(); - rotating.values() - .stream() - .flatMap(cache -> cache.asMap().values().stream()) - .filter(type -> !type.isEmpty()) - .forEach(InstanceBuffer::render); - - ShaderHelper.useShader(Shader.BELT_INSTANCED, callback); - - belts.values() - .stream() - .flatMap(cache -> cache.asMap().values().stream()) - .filter(type -> !type.isEmpty()) - .forEach(InstanceBuffer::render); + ShaderHelper.useShader(Shader.BELT, callback); + renderBelts(); ShaderHelper.releaseShader(); teardown(); } - public void setup(GameRenderer gameRenderer) { + public static void setup(GameRenderer gameRenderer) { RenderSystem.enableBlend(); - RenderSystem.blendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); + RenderSystem.defaultBlendFunc(); RenderSystem.enableLighting(); RenderSystem.enableDepthTest(); + RenderSystem.enableCull(); GL11.glCullFace(GL11.GL_BACK); LightTexture lightManager = gameRenderer.getLightmapTextureManager(); @@ -149,9 +185,9 @@ public class FastKineticRenderer { RenderSystem.enableTexture(); } - public void teardown() { + public static void teardown() { - GL13.glActiveTexture(GL40.GL_TEXTURE0 + 1); + GL13.glActiveTexture(GL40.GL_TEXTURE1); GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0); GL13.glActiveTexture(GL40.GL_TEXTURE0); @@ -175,26 +211,26 @@ public class FastKineticRenderer { belts.put(instance, CacheBuilder.newBuilder().expireAfterAccess(ticksUntilExpired * 50, TimeUnit.MILLISECONDS).build()); } - public RotatingBuffer renderPartialRotating(AllBlockPartials partial, BlockState referenceState) { + public InstanceBuffer renderPartialRotating(AllBlockPartials partial, BlockState referenceState) { return getRotating(PARTIAL, partial, () -> rotatingInstancedRenderer(partial.get(), referenceState)); } - public BeltBuffer renderPartialBelt(AllBlockPartials partial, BlockState referenceState) { + public InstanceBuffer renderPartialBelt(AllBlockPartials partial, BlockState referenceState) { return getBelt(PARTIAL, partial, () -> beltInstancedRenderer(partial.get(), referenceState)); } - public RotatingBuffer renderDirectionalPartialInstanced(AllBlockPartials partial, BlockState referenceState, Direction dir, + public InstanceBuffer renderDirectionalPartialInstanced(AllBlockPartials partial, BlockState referenceState, Direction dir, MatrixStack modelTransform) { return getRotating(SuperByteBufferCache.DIRECTIONAL_PARTIAL, Pair.of(dir, partial), () -> rotatingInstancedRenderer(partial.get(), referenceState, modelTransform)); } - public RotatingBuffer renderBlockInstanced(SuperByteBufferCache.Compartment compartment, BlockState toRender) { + public InstanceBuffer renderBlockInstanced(SuperByteBufferCache.Compartment compartment, BlockState toRender) { return getRotating(compartment, toRender, () -> rotatingInstancedRenderer(toRender)); } - public RotatingBuffer getRotating(SuperByteBufferCache.Compartment compartment, T key, Supplier supplier) { - Cache compartmentCache = this.rotating.get(compartment); + public InstanceBuffer getRotating(SuperByteBufferCache.Compartment compartment, T key, Supplier> supplier) { + Cache> compartmentCache = this.rotating.get(compartment); try { return compartmentCache.get(key, supplier::get); } catch (ExecutionException e) { @@ -203,8 +239,8 @@ public class FastKineticRenderer { } } - public BeltBuffer getBelt(SuperByteBufferCache.Compartment compartment, T key, Supplier supplier) { - Cache compartmentCache = this.belts.get(compartment); + public InstanceBuffer getBelt(SuperByteBufferCache.Compartment compartment, T key, Supplier> supplier) { + Cache> compartmentCache = this.belts.get(compartment); try { return compartmentCache.get(key, supplier::get); } catch (ExecutionException e) { @@ -214,40 +250,40 @@ public class FastKineticRenderer { } - private RotatingBuffer rotatingInstancedRenderer(BlockState renderedState) { + private InstanceBuffer rotatingInstancedRenderer(BlockState renderedState) { BlockRendererDispatcher dispatcher = Minecraft.getInstance().getBlockRendererDispatcher(); return rotatingInstancedRenderer(dispatcher.getModelForState(renderedState), renderedState); } - private RotatingBuffer rotatingInstancedRenderer(IBakedModel model, BlockState renderedState) { + private InstanceBuffer rotatingInstancedRenderer(IBakedModel model, BlockState renderedState) { return rotatingInstancedRenderer(model, renderedState, new MatrixStack()); } - private BeltBuffer beltInstancedRenderer(IBakedModel model, BlockState renderedState) { + private InstanceBuffer beltInstancedRenderer(IBakedModel model, BlockState renderedState) { return beltInstancedRenderer(model, renderedState, new MatrixStack()); } - private RotatingBuffer rotatingInstancedRenderer(IBakedModel model, BlockState referenceState, MatrixStack ms) { + private InstanceBuffer rotatingInstancedRenderer(IBakedModel model, BlockState referenceState, MatrixStack ms) { BufferBuilder builder = SuperByteBufferCache.getBufferBuilder(model, referenceState, ms); return new RotatingBuffer(builder); } - private BeltBuffer beltInstancedRenderer(IBakedModel model, BlockState referenceState, MatrixStack ms) { + private InstanceBuffer beltInstancedRenderer(IBakedModel model, BlockState referenceState, MatrixStack ms) { BufferBuilder builder = SuperByteBufferCache.getBufferBuilder(model, referenceState, ms); return new BeltBuffer(builder); } public void invalidate() { - rotating.values().forEach(cache -> { - cache.asMap().values().forEach(InstanceBuffer::delete); - cache.invalidateAll(); - }); + for (Cache> objectInstanceBufferCache : rotating.values()) { + objectInstanceBufferCache.asMap().values().forEach(InstanceBuffer::delete); + objectInstanceBufferCache.invalidateAll(); + } - belts.values().forEach(cache -> { + for (Cache> cache : belts.values()) { cache.asMap().values().forEach(InstanceBuffer::delete); cache.invalidateAll(); - }); + } } } diff --git a/src/main/java/com/simibubi/create/foundation/utility/render/SafeDirectBuffer.java b/src/main/java/com/simibubi/create/foundation/utility/render/SafeDirectBuffer.java new file mode 100644 index 000000000..07316ff04 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/utility/render/SafeDirectBuffer.java @@ -0,0 +1,172 @@ +package com.simibubi.create.foundation.utility.render; + +import net.minecraft.client.renderer.GLAllocation; +import org.lwjgl.system.MemoryStack; +import org.lwjgl.system.MemoryUtil; +import sun.misc.Cleaner; +import sun.nio.ch.DirectBuffer; + +import java.nio.*; + +public class SafeDirectBuffer implements AutoCloseable { + + private ByteBuffer wrapped; + + public SafeDirectBuffer(int capacity) { + this.wrapped = GLAllocation.createDirectByteBuffer(capacity); + } + + public void close() throws Exception { + if (wrapped instanceof DirectBuffer) { + Cleaner cleaner = ((DirectBuffer) wrapped).cleaner(); + if (!cleaner.isEnqueued()) { + cleaner.clean(); + cleaner.enqueue(); + } + } + } + + /** + * Only use this function to pass information to OpenGL. + */ + @Deprecated + public ByteBuffer getBacking() { + return wrapped; + } + + public void order(ByteOrder bo) { + wrapped.order(bo); + } + + public void limit(int limit) { + wrapped.limit(limit); + } + + public void rewind() { + wrapped.rewind(); + } + + public byte get() { + return wrapped.get(); + } + + public ByteBuffer put(byte b) { + return wrapped.put(b); + } + + public byte get(int index) { + return wrapped.get(); + } + + public ByteBuffer put(int index, byte b) { + return wrapped.put(index, b); + } + + public ByteBuffer compact() { + return wrapped.compact(); + } + + public boolean isReadOnly() { + return wrapped.isReadOnly(); + } + + public boolean isDirect() { + return wrapped.isDirect(); + } + + public char getChar() { + return wrapped.getChar(); + } + + public ByteBuffer putChar(char value) { + return wrapped.putChar(value); + } + + public char getChar(int index) { + return wrapped.getChar(index); + } + + public ByteBuffer putChar(int index, char value) { + return wrapped.putChar(index, value); + } + + public short getShort() { + return wrapped.getShort(); + } + + public ByteBuffer putShort(short value) { + return wrapped.putShort(value); + } + + public short getShort(int index) { + return wrapped.getShort(index); + } + + public ByteBuffer putShort(int index, short value) { + return wrapped.putShort(index, value); + } + + public int getInt() { + return wrapped.getInt(); + } + + public ByteBuffer putInt(int value) { + return wrapped.putInt(value); + } + + public int getInt(int index) { + return wrapped.getInt(index); + } + + public ByteBuffer putInt(int index, int value) { + return wrapped.putInt(index, value); + } + + public long getLong() { + return wrapped.getLong(); + } + + public ByteBuffer putLong(long value) { + return wrapped.putLong(value); + } + + public long getLong(int index) { + return wrapped.getLong(index); + } + + public ByteBuffer putLong(int index, long value) { + return wrapped.putLong(index, value); + } + + public float getFloat() { + return wrapped.getFloat(); + } + + public ByteBuffer putFloat(float value) { + return wrapped.putFloat(value); + } + + public float getFloat(int index) { + return wrapped.getFloat(index); + } + + public ByteBuffer putFloat(int index, float value) { + return wrapped.putFloat(index, value); + } + + public double getDouble() { + return wrapped.getDouble(); + } + + public ByteBuffer putDouble(double value) { + return wrapped.putDouble(value); + } + + public double getDouble(int index) { + return wrapped.getDouble(index); + } + + public ByteBuffer putDouble(int index, double value) { + return wrapped.putDouble(index, value); + } +} 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 index e526fe3b5..23b5afc87 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/render/TemplateBuffer.java +++ b/src/main/java/com/simibubi/create/foundation/utility/render/TemplateBuffer.java @@ -1,8 +1,10 @@ package com.simibubi.create.foundation.utility.render; +import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.datafixers.util.Pair; import net.minecraft.client.renderer.BufferBuilder; -import net.minecraft.client.renderer.GLAllocation; +import net.minecraft.client.renderer.vertex.VertexFormatElement; +import org.lwjgl.opengl.GL15; import java.nio.Buffer; import java.nio.ByteBuffer; @@ -11,7 +13,7 @@ import java.nio.ByteOrder; public class TemplateBuffer { protected ByteBuffer template; protected int formatSize; - protected int count; + protected int vertexCount; public TemplateBuffer(BufferBuilder buf) { Pair state = buf.popData(); @@ -20,8 +22,8 @@ public class TemplateBuffer { formatSize = buf.getVertexFormat() .getSize(); - count = state.getFirst().getCount(); - int size = count * formatSize; + vertexCount = state.getFirst().getCount(); + int size = vertexCount * formatSize; template = ByteBuffer.allocate(size); template.order(rendered.order()); @@ -30,6 +32,22 @@ public class TemplateBuffer { ((Buffer)template).rewind(); } + protected void buildEBO(int ebo) throws Exception { + int indicesSize = vertexCount * VertexFormatElement.Type.USHORT.getSize(); + try (SafeDirectBuffer indices = new SafeDirectBuffer(indicesSize)) { + indices.order(template.order()); + indices.limit(indicesSize); + + for (int i = 0; i < vertexCount; i++) { + indices.putShort((short) i); + } + indices.rewind(); + + GlStateManager.bindBuffers(GL15.GL_ELEMENT_ARRAY_BUFFER, ebo); + GlStateManager.bufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, indices.getBacking(), GL15.GL_STATIC_DRAW); + } + } + public boolean isEmpty() { return ((Buffer) template).limit() == 0; } diff --git a/src/main/java/com/simibubi/create/foundation/utility/render/TileEntityRenderHelper.java b/src/main/java/com/simibubi/create/foundation/utility/render/TileEntityRenderHelper.java index 9dbab11a7..2c4d2fcc2 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/render/TileEntityRenderHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/render/TileEntityRenderHelper.java @@ -7,6 +7,7 @@ import com.simibubi.create.Create; import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.utility.MatrixStacker; +import com.simibubi.create.foundation.utility.render.instancing.IInstanceRendered; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.Matrix4f; @@ -30,6 +31,8 @@ public class TileEntityRenderHelper { for (Iterator iterator = customRenderTEs.iterator(); iterator.hasNext();) { TileEntity tileEntity = iterator.next(); + if (tileEntity instanceof IInstanceRendered) continue; // TODO: some things still need to render + TileEntityRenderer renderer = TileEntityRendererDispatcher.instance.getRenderer(tileEntity); if (renderer == null) { iterator.remove(); diff --git a/src/main/java/com/simibubi/create/foundation/utility/render/instancing/BasicData.java b/src/main/java/com/simibubi/create/foundation/utility/render/instancing/BasicData.java index 082d018e1..b7df264ef 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/render/instancing/BasicData.java +++ b/src/main/java/com/simibubi/create/foundation/utility/render/instancing/BasicData.java @@ -1,10 +1,9 @@ package com.simibubi.create.foundation.utility.render.instancing; +import com.simibubi.create.foundation.utility.render.SafeDirectBuffer; import net.minecraft.client.renderer.Vector3f; import net.minecraft.util.math.BlockPos; -import java.nio.ByteBuffer; - public class BasicData> extends InstanceData { private float x; @@ -38,7 +37,7 @@ public class BasicData> extends InstanceData { } @Override - public void write(ByteBuffer buf) { + public void write(SafeDirectBuffer buf) { putVec3(buf, x, y, z); putVec2(buf, blockLight, skyLight); diff --git a/src/main/java/com/simibubi/create/foundation/utility/render/instancing/BeltData.java b/src/main/java/com/simibubi/create/foundation/utility/render/instancing/BeltData.java index a4f717903..f1e359f9c 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/render/instancing/BeltData.java +++ b/src/main/java/com/simibubi/create/foundation/utility/render/instancing/BeltData.java @@ -1,10 +1,8 @@ package com.simibubi.create.foundation.utility.render.instancing; import com.simibubi.create.foundation.block.render.SpriteShiftEntry; +import com.simibubi.create.foundation.utility.render.SafeDirectBuffer; import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.util.math.BlockPos; - -import java.nio.ByteBuffer; import static com.simibubi.create.foundation.utility.render.instancing.VertexAttribute.*; @@ -55,7 +53,7 @@ public class BeltData extends BasicData { } @Override - public void write(ByteBuffer buf) { + public void write(SafeDirectBuffer buf) { super.write(buf); putVec3(buf, rotX, rotY, rotZ); diff --git a/src/main/java/com/simibubi/create/foundation/utility/render/instancing/IInstancedTileEntityRenderer.java b/src/main/java/com/simibubi/create/foundation/utility/render/instancing/IInstancedTileEntityRenderer.java index 7b0393689..ccd123237 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/render/instancing/IInstancedTileEntityRenderer.java +++ b/src/main/java/com/simibubi/create/foundation/utility/render/instancing/IInstancedTileEntityRenderer.java @@ -1,13 +1,19 @@ package com.simibubi.create.foundation.utility.render.instancing; +import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; +import com.simibubi.create.foundation.utility.render.FastContraptionRenderer; +import net.minecraft.block.BlockState; import net.minecraft.client.renderer.tileentity.TileEntityRenderer; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; import net.minecraft.tileentity.TileEntity; +import java.util.function.BiFunction; +import java.util.function.Function; import java.util.function.Supplier; public interface IInstancedTileEntityRenderer { - void addInstanceData(T te); + void addInstanceData(InstanceContext te); } diff --git a/src/main/java/com/simibubi/create/foundation/utility/render/instancing/InstanceBuffer.java b/src/main/java/com/simibubi/create/foundation/utility/render/instancing/InstanceBuffer.java index 5a4bd4c14..0839b37b9 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/render/instancing/InstanceBuffer.java +++ b/src/main/java/com/simibubi/create/foundation/utility/render/instancing/InstanceBuffer.java @@ -2,17 +2,12 @@ package com.simibubi.create.foundation.utility.render.instancing; import com.mojang.blaze3d.platform.GlStateManager; -import com.simibubi.create.CreateClient; import com.simibubi.create.foundation.utility.render.RenderWork; +import com.simibubi.create.foundation.utility.render.SafeDirectBuffer; import com.simibubi.create.foundation.utility.render.TemplateBuffer; import net.minecraft.client.renderer.BufferBuilder; -import net.minecraft.client.renderer.GLAllocation; -import net.minecraft.client.renderer.vertex.VertexFormatElement; import org.lwjgl.opengl.*; -import org.lwjgl.system.MemoryUtil; -import java.nio.Buffer; -import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.function.Consumer; @@ -24,60 +19,53 @@ public abstract class InstanceBuffer extends TemplateBuf protected int vao, ebo, invariantVBO, instanceVBO, instanceCount; protected final ArrayList data = new ArrayList<>(); + protected boolean rebuffer = false; protected boolean shouldBuild = true; public InstanceBuffer(BufferBuilder buf) { super(buf); - setupMainData(); + setup(); } - private void setupMainData() { + private void setup() { int stride = FORMAT.getStride(); - 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(); + int invariantSize = vertexCount * stride; 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); - MemoryUtil.memFree(constant); + try (SafeDirectBuffer constant = new SafeDirectBuffer(invariantSize)) { + constant.order(template.order()); + constant.limit(invariantSize); - GlStateManager.bindBuffers(GL15.GL_ELEMENT_ARRAY_BUFFER, ebo); - GlStateManager.bufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, indices, GL15.GL_STATIC_DRAW); - MemoryUtil.memFree(indices); + for (int i = 0; i < vertexCount; i++) { + constant.putFloat(getX(template, i)); + constant.putFloat(getY(template, i)); + constant.putFloat(getZ(template, i)); - FORMAT.informAttributes(0); + constant.put(getNX(template, i)); + constant.put(getNY(template, i)); + constant.put(getNZ(template, i)); + + constant.putFloat(getU(template, i)); + constant.putFloat(getV(template, i)); + } + constant.rewind(); + + GL30.glBindVertexArray(vao); + + GlStateManager.bindBuffers(GL15.GL_ARRAY_BUFFER, invariantVBO); + GlStateManager.bufferData(GL15.GL_ARRAY_BUFFER, constant.getBacking(), GL15.GL_STATIC_DRAW); + + buildEBO(ebo); + + FORMAT.informAttributes(0); + } catch (Exception e) { + delete(); + } GlStateManager.bindBuffers(GL15.GL_ARRAY_BUFFER, 0); GlStateManager.bindBuffers(GL15.GL_ELEMENT_ARRAY_BUFFER, 0); @@ -88,7 +76,7 @@ public abstract class InstanceBuffer extends TemplateBuf protected abstract VertexFormat getInstanceFormat(); public int numInstances() { - return instanceCount; + return instanceCount + data.size(); } public boolean isEmpty() { @@ -100,14 +88,20 @@ public abstract class InstanceBuffer extends TemplateBuf shouldBuild = true; } + public void markDirty() { + rebuffer = true; + } + public void delete() { RenderWork.enqueue(() -> { GL15.glDeleteBuffers(invariantVBO); GL15.glDeleteBuffers(instanceVBO); GL15.glDeleteBuffers(ebo); GL30.glDeleteVertexArrays(vao); - - clearInstanceData(); + vao = 0; + ebo = 0; + invariantVBO = 0; + instanceVBO = 0; }); } @@ -120,10 +114,10 @@ public abstract class InstanceBuffer extends TemplateBuf setup.accept(instanceData); data.add(instanceData); - instanceCount++; } public void render() { + if (vao == 0) return; GL30.glBindVertexArray(vao); finishBuffering(); @@ -135,7 +129,7 @@ public abstract class InstanceBuffer extends TemplateBuf GlStateManager.bindBuffers(GL15.GL_ELEMENT_ARRAY_BUFFER, ebo); - GL40.glDrawElementsInstanced(GL11.GL_QUADS, count, GL11.GL_UNSIGNED_SHORT, 0, instanceCount); + GL40.glDrawElementsInstanced(GL11.GL_QUADS, vertexCount, GL11.GL_UNSIGNED_SHORT, 0, instanceCount); for (int i = 0; i <= numAttributes; i++) { GL40.glDisableVertexAttribArray(i); @@ -146,33 +140,39 @@ public abstract class InstanceBuffer extends TemplateBuf } private void finishBuffering() { - if (!shouldBuild) return; + if (!rebuffer || isEmpty()) return; + + instanceCount = data.size(); VertexFormat instanceFormat = getInstanceFormat(); int instanceSize = instanceCount * instanceFormat.getStride(); - ByteBuffer buffer = GLAllocation.createDirectByteBuffer(instanceSize); - buffer.order(template.order()); - ((Buffer) buffer).limit(instanceSize); + try (SafeDirectBuffer buffer = new SafeDirectBuffer(instanceSize)) { + buffer.order(template.order()); + buffer.limit(instanceSize); - data.forEach(instanceData -> instanceData.write(buffer)); - buffer.rewind(); + data.forEach(instanceData -> instanceData.write(buffer)); + buffer.rewind(); - GlStateManager.bindBuffers(GL15.GL_ARRAY_BUFFER, instanceVBO); - GlStateManager.bufferData(GL15.GL_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW); + GlStateManager.bindBuffers(GL15.GL_ARRAY_BUFFER, instanceVBO); + GlStateManager.bufferData(GL15.GL_ARRAY_BUFFER, buffer.getBacking(), GL15.GL_STATIC_DRAW); - int staticAttributes = FORMAT.getNumAttributes(); - instanceFormat.informAttributes(staticAttributes); + int staticAttributes = FORMAT.getNumAttributes(); + instanceFormat.informAttributes(staticAttributes); + + for (int i = 0; i < instanceFormat.getNumAttributes(); i++) { + GL40.glVertexAttribDivisor(i + staticAttributes, 1); + } + } catch (Exception e) { - for (int i = 0; i < instanceFormat.getNumAttributes(); i++) { - GL40.glVertexAttribDivisor(i + staticAttributes, 1); } // Deselect (bind to 0) the VBO GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0); shouldBuild = false; + rebuffer = false; data.clear(); } } diff --git a/src/main/java/com/simibubi/create/foundation/utility/render/instancing/InstanceContext.java b/src/main/java/com/simibubi/create/foundation/utility/render/instancing/InstanceContext.java new file mode 100644 index 000000000..e1087e9c2 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/utility/render/instancing/InstanceContext.java @@ -0,0 +1,56 @@ +package com.simibubi.create.foundation.utility.render.instancing; + +import com.simibubi.create.CreateClient; +import com.simibubi.create.foundation.utility.render.FastContraptionRenderer; +import com.simibubi.create.foundation.utility.render.FastKineticRenderer; +import net.minecraft.tileentity.TileEntity; + +public abstract class InstanceContext { + + public final T te; + + public InstanceContext(T te) { + this.te = te; + } + + public abstract FastKineticRenderer getKinetics(); + + public abstract boolean checkWorldLight(); + + public static class Contraption extends InstanceContext { + + public final FastContraptionRenderer c; + + public Contraption(T te, FastContraptionRenderer c) { + super(te); + this.c = c; + } + + @Override + public FastKineticRenderer getKinetics() { + return c.kinetics; + } + + @Override + public boolean checkWorldLight() { + return false; + } + } + + public static class World extends InstanceContext { + + public World(T te) { + super(te); + } + + @Override + public FastKineticRenderer getKinetics() { + return CreateClient.kineticRenderer; + } + + @Override + public boolean checkWorldLight() { + return true; + } + } +} diff --git a/src/main/java/com/simibubi/create/foundation/utility/render/instancing/InstanceData.java b/src/main/java/com/simibubi/create/foundation/utility/render/instancing/InstanceData.java index 22690d1fc..c7d057b4a 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/render/instancing/InstanceData.java +++ b/src/main/java/com/simibubi/create/foundation/utility/render/instancing/InstanceData.java @@ -1,30 +1,32 @@ package com.simibubi.create.foundation.utility.render.instancing; +import com.simibubi.create.foundation.utility.render.SafeDirectBuffer; + import java.nio.ByteBuffer; public abstract class InstanceData { - public abstract void write(ByteBuffer buf); + public abstract void write(SafeDirectBuffer buf); - public void putVec4(ByteBuffer buf, float x, float y, float z, float w) { + public void putVec4(SafeDirectBuffer buf, float x, float y, float z, float w) { putFloat(buf, x); putFloat(buf, y); putFloat(buf, z); putFloat(buf, w); } - public void putVec3(ByteBuffer buf, float x, float y, float z) { + public void putVec3(SafeDirectBuffer buf, float x, float y, float z) { putFloat(buf, x); putFloat(buf, y); putFloat(buf, z); } - public void putVec2(ByteBuffer buf, float x, float y) { + public void putVec2(SafeDirectBuffer buf, float x, float y) { putFloat(buf, x); putFloat(buf, y); } - public void putFloat(ByteBuffer buf, float f) { + public void putFloat(SafeDirectBuffer buf, float f) { buf.putFloat(f); } } diff --git a/src/main/java/com/simibubi/create/foundation/utility/render/instancing/RotatingData.java b/src/main/java/com/simibubi/create/foundation/utility/render/instancing/RotatingData.java index 92e60202f..164bc7610 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/render/instancing/RotatingData.java +++ b/src/main/java/com/simibubi/create/foundation/utility/render/instancing/RotatingData.java @@ -1,9 +1,7 @@ package com.simibubi.create.foundation.utility.render.instancing; +import com.simibubi.create.foundation.utility.render.SafeDirectBuffer; import net.minecraft.client.renderer.Vector3f; -import net.minecraft.util.math.BlockPos; - -import java.nio.ByteBuffer; import static com.simibubi.create.foundation.utility.render.instancing.VertexAttribute.*; @@ -41,7 +39,7 @@ public class RotatingData extends BasicData { } @Override - public void write(ByteBuffer buf) { + public void write(SafeDirectBuffer buf) { super.write(buf); putFloat(buf, rotationalSpeed); putFloat(buf, rotationOffset); diff --git a/src/main/java/com/simibubi/create/foundation/utility/render/instancing/VertexAttribute.java b/src/main/java/com/simibubi/create/foundation/utility/render/instancing/VertexAttribute.java index 60d94311d..885c1c9d0 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/render/instancing/VertexAttribute.java +++ b/src/main/java/com/simibubi/create/foundation/utility/render/instancing/VertexAttribute.java @@ -11,8 +11,8 @@ public class VertexAttribute { public static final VertexAttribute FLOAT = new VertexAttribute(VertexFormatElement.Type.FLOAT, 1); public static final VertexAttribute POSITION = VEC3; - public static final VertexAttribute NORMAL = VEC3; - public static final VertexAttribute COLOR = VEC4; + public static final VertexAttribute NORMAL = new VertexAttribute(VertexFormatElement.Type.BYTE, 3); + public static final VertexAttribute COLOR = new VertexAttribute(VertexFormatElement.Type.BYTE, 4); public static final VertexAttribute UV = VEC2; public static final VertexAttribute LIGHT= VEC2; 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 index e3f06bee5..d748693f2 100644 --- 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 @@ -1,9 +1,11 @@ package com.simibubi.create.foundation.utility.render.shader; public enum Shader { - ROTATING_INSTANCED("shader/rotating.vert", "shader/instanced.frag"), - BELT_INSTANCED("shader/belt.vert", "shader/instanced.frag"), + ROTATING("shader/rotating.vert", "shader/instanced.frag"), + BELT("shader/belt.vert", "shader/instanced.frag"), CONTRAPTION_STRUCTURE("shader/contraption.vert", "shader/contraption.frag"), + CONTRAPTION_ROTATING("shader/contraption_rotating.vert", "shader/contraption.frag"), + CONTRAPTION_BELT("shader/contraption_belt.vert", "shader/contraption.frag"), ; public final String vert; 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 index ae5d1d957..8f13561c8 100644 --- 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 @@ -58,34 +58,28 @@ public class ShaderHelper { return shaderProgram.getProgram(); } - public static ShaderCallback getViewProjectionCallback(RenderWorldLastEvent event) { + public static ShaderCallback getViewProjectionCallback(Matrix4f projectionMat, Matrix4f viewMat) { return shader -> { ShaderHelper.MATRIX_BUFFER.position(0); - event.getProjectionMatrix().write(ShaderHelper.MATRIX_BUFFER); - + projectionMat.write(ShaderHelper.MATRIX_BUFFER); int projection = GlStateManager.getUniformLocation(shader, "projection"); GlStateManager.uniformMatrix4(projection, false, ShaderHelper.MATRIX_BUFFER); - // view matrix - Vec3d pos = Minecraft.getInstance().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); + viewMat.write(ShaderHelper.MATRIX_BUFFER); int view = GlStateManager.getUniformLocation(shader, "view"); GlStateManager.uniformMatrix4(view, false, ShaderHelper.MATRIX_BUFFER); }; } - public static void useShader(Shader shader) { - useShader(shader, null); + public static int useShader(Shader shader) { + return useShader(shader, null); } - public static void useShader(Shader shader, @Nullable ShaderCallback cb) { + public static int useShader(Shader shader, @Nullable ShaderCallback cb) { ShaderProgram prog = PROGRAMS.get(shader); if (prog == null) { - return; + return -1; } int program = prog.getProgram(); @@ -102,6 +96,8 @@ public class ShaderHelper { if (cb != null) { cb.call(program); } + + return program; } public static void releaseShader() { diff --git a/src/main/resources/assets/create/shader/contraption.frag b/src/main/resources/assets/create/shader/contraption.frag index 0d5fbe4a3..80a7dec3b 100644 --- a/src/main/resources/assets/create/shader/contraption.frag +++ b/src/main/resources/assets/create/shader/contraption.frag @@ -16,7 +16,6 @@ vec4 light() { return texture2D(LightMap, lm); } - void main() { vec4 tex = texture2D(BlockAtlas, TexCoords); diff --git a/src/main/resources/assets/create/shader/contraption.vert b/src/main/resources/assets/create/shader/contraption.vert index 44d4795c7..8364cdc67 100644 --- a/src/main/resources/assets/create/shader/contraption.vert +++ b/src/main/resources/assets/create/shader/contraption.vert @@ -21,8 +21,7 @@ uniform int ticks; uniform mat4 projection; uniform mat4 view; -mat4 rotate(vec3 axis, float angle) -{ +mat4 rotate(vec3 axis, float angle) { float s = sin(angle); float c = cos(angle); float oc = 1.0 - c; @@ -47,18 +46,11 @@ float diffuse(vec3 normal) { void main() { mat4 rotation = contraptionRotation(); + vec4 worldPos = (rotation * vec4(aPos - vec3(0.5), 1)) + vec4(cPos + vec3(0.5), 0); - vec4 rotatedPos = rotation * vec4(aPos - vec3(0.5), 1); - - vec4 worldPos = rotatedPos + vec4(cPos + vec3(0.5), 0); - - vec3 boxCoord = (worldPos.xyz - lightBoxMin) / lightBoxSize; - - float df = diffuse(normalize(aNormal)); - - Diffuse = diffuse(normalize((rotation * vec4(aNormal, 0.)).xyz)); - Color = vec4(aColor.rgb / df, aColor.a); - BoxCoord = boxCoord; + BoxCoord = (worldPos.xyz - lightBoxMin) / lightBoxSize; + Diffuse = diffuse(normalize(rotation * vec4(aNormal, 0.)).xyz); + Color = aColor; TexCoords = aTexCoords; gl_Position = projection * view * worldPos; } diff --git a/src/main/resources/assets/create/shader/contraption_belt.vert b/src/main/resources/assets/create/shader/contraption_belt.vert new file mode 100644 index 000000000..65070364b --- /dev/null +++ b/src/main/resources/assets/create/shader/contraption_belt.vert @@ -0,0 +1,79 @@ +#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 vec3 rotationDegrees; +layout (location = 6) in float speed; +layout (location = 7) in vec2 sourceUV; +layout (location = 8) in vec4 scrollTexture; +layout (location = 9) in float scrollMult; + +out float Diffuse; +out vec2 TexCoords; +out vec4 Color; +out vec3 BoxCoord; + +uniform vec3 lightBoxSize; +uniform vec3 lightBoxMin; +uniform vec3 cPos; +uniform vec3 cRot; + +uniform float time; +uniform int ticks; +uniform mat4 projection; +uniform mat4 view; + +mat4 rotate(vec3 axis, float angle) +{ + 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.); +} + +mat4 rotation(vec3 rot) { + return rotate(vec3(0, 1, 0), rot.y) * rotate(vec3(0, 0, 1), rot.z) * rotate(vec3(1, 0, 0), rot.x); +} + +mat4 contraptionRotation() { + vec3 rot = -fract(cRot / 360) * PI * 2; + return rotation(rot); +} + +mat4 localRotation() { + vec3 rot = fract(rotationDegrees / 360) * PI * 2; + return rotation(rot); +} + +float diffuse(vec3 normal) { + float x = normal.x; + float y = normal.y; + float z = normal.z; + return min(x * x * 0.6f + y * y * ((3f + y) / 4f) + z * z * 0.8f, 1f); +} + +void main() { + mat4 localRotation = localRotation(); + vec4 localPos = localRotation * vec4(aPos - 0.5, 1f) + vec4(instancePos, 0); + + mat4 contraptionRotation = contraptionRotation(); + vec4 worldPos = contraptionRotation * localPos + vec4(cPos + 0.5, 0); + + float scrollSize = scrollTexture.w - scrollTexture.y; + float scroll = fract(speed * time / (36 * 16.)) * scrollSize * scrollMult; + + BoxCoord = (worldPos.xyz - lightBoxMin) / lightBoxSize; + Diffuse = diffuse(normalize(contraptionRotation * localRotation * vec4(aNormal, 0.)).xyz); + Color = vec4(1.); + TexCoords = aTexCoords - sourceUV + scrollTexture.xy + vec2(0., scroll); + gl_Position = projection * view * worldPos; +} diff --git a/src/main/resources/assets/create/shader/contraption_rotating.vert b/src/main/resources/assets/create/shader/contraption_rotating.vert new file mode 100644 index 000000000..532dc4681 --- /dev/null +++ b/src/main/resources/assets/create/shader/contraption_rotating.vert @@ -0,0 +1,71 @@ +#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; + +out float Diffuse; +out vec2 TexCoords; +out vec4 Color; +out vec3 BoxCoord; + +uniform vec3 lightBoxSize; +uniform vec3 lightBoxMin; +uniform vec3 cPos; +uniform vec3 cRot; + +uniform float time; +uniform int ticks; +uniform mat4 projection; +uniform mat4 view; + +mat4 rotate(vec3 axis, float angle) { + 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.); +} + +mat4 kineticRotation() { + float degrees = rotationOffset + time * speed * -3./10.; + float angle = fract(degrees / 360.) * PI * 2.; + + vec3 axis = normalize(rotationAxis); + return rotate(axis, angle); +} + +mat4 contraptionRotation() { + vec3 rot = -fract(cRot / 360) * PI * 2; + return rotate(vec3(0, 1, 0), rot.y) * rotate(vec3(0, 0, 1), rot.z) * rotate(vec3(1, 0, 0), rot.x); +} + +float diffuse(vec3 normal) { + float x = normal.x; + float y = normal.y; + float z = normal.z; + return min(x * x * 0.6f + y * y * ((3f + y) / 4f) + z * z * 0.8f, 1f); +} + +void main() { + mat4 kineticRotation = kineticRotation(); + vec4 localPos = kineticRotation * vec4(aPos - 0.5, 1f) + vec4(instancePos, 0); + + mat4 contraptionRotation = contraptionRotation(); + vec4 worldPos = contraptionRotation * localPos + vec4(cPos + 0.5, 0); + + BoxCoord = (worldPos.xyz - lightBoxMin) / lightBoxSize; + Diffuse = diffuse(normalize(contraptionRotation * localRotation * vec4(aNormal, 0.)).xyz); + Color = vec4(1.); + TexCoords = aTexCoords; + gl_Position = projection * view * worldPos; +} \ No newline at end of file