Refactor contraption matrices

- Create ContraptionMatrices class for better management of matrices during the contraption rendering process
- Fix diffuse lighting when rendering contraptions without Flywheel
- Clean up TileEntityRenderHelper
- Add disableDiffuseTransform to SuperByteBuffer and fix light calculation logic
This commit is contained in:
PepperBell 2021-05-16 18:42:56 -07:00
parent f33b08d996
commit 61b101f0c6
21 changed files with 314 additions and 234 deletions

View file

@ -3,10 +3,10 @@ package com.simibubi.create.content.contraptions.components.actors;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld;
@ -36,9 +36,9 @@ public class DrillMovementBehaviour extends BlockBreakingMovementBehaviour {
@Override @Override
@OnlyIn(value = Dist.CLIENT) @OnlyIn(value = Dist.CLIENT)
public void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld, public void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld,
MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffer) { ContraptionMatrices matrices, IRenderTypeBuffer buffer) {
if (!Backend.canUseInstancing()) if (!Backend.canUseInstancing())
DrillRenderer.renderInContraption(context, renderWorld, ms, msLocal, buffer); DrillRenderer.renderInContraption(context, renderWorld, matrices, buffer);
} }
@Override @Override

View file

@ -5,6 +5,7 @@ import com.simibubi.create.AllBlockPartials;
import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher;
import com.simibubi.create.foundation.render.PartialBufferer; import com.simibubi.create.foundation.render.PartialBufferer;
import com.simibubi.create.foundation.render.SuperByteBuffer; import com.simibubi.create.foundation.render.SuperByteBuffer;
@ -32,8 +33,7 @@ public class DrillRenderer extends KineticTileEntityRenderer {
} }
public static void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld, public static void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld,
MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffer) { ContraptionMatrices matrices, IRenderTypeBuffer buffer) {
MatrixStack[] matrixStacks = new MatrixStack[]{ms, msLocal};
BlockState state = context.state; BlockState state = context.state;
SuperByteBuffer superBuffer = PartialBufferer.get(AllBlockPartials.DRILL_HEAD, state); SuperByteBuffer superBuffer = PartialBufferer.get(AllBlockPartials.DRILL_HEAD, state);
Direction facing = state.get(DrillBlock.FACING); Direction facing = state.get(DrillBlock.FACING);
@ -44,7 +44,8 @@ public class DrillRenderer extends KineticTileEntityRenderer {
float time = AnimationTickHolder.getRenderTime() / 20; float time = AnimationTickHolder.getRenderTime() / 20;
float angle = (float) (((time * speed) % 360)); float angle = (float) (((time * speed) % 360));
for (MatrixStack m : matrixStacks) MatrixStack m = matrices.contraptionStack;
m.push();
MatrixStacker.of(m) MatrixStacker.of(m)
.centre() .centre()
.rotateY(AngleHelper.horizontalAngle(facing)) .rotateY(AngleHelper.horizontalAngle(facing))
@ -53,9 +54,12 @@ public class DrillRenderer extends KineticTileEntityRenderer {
.unCentre(); .unCentre();
superBuffer superBuffer
.light(msLocal.peek().getModel(), .transform(matrices.contraptionStack)
.light(matrices.entityMatrix,
ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld))
.renderInto(ms, buffer.getBuffer(RenderType.getSolid())); .renderInto(matrices.entityStack, buffer.getBuffer(RenderType.getSolid()));
m.pop();
} }
} }

View file

@ -7,11 +7,11 @@ import javax.annotation.Nullable;
import org.apache.commons.lang3.mutable.MutableBoolean; import org.apache.commons.lang3.mutable.MutableBoolean;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour;
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices;
import com.simibubi.create.foundation.utility.BlockHelper; import com.simibubi.create.foundation.utility.BlockHelper;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld;
@ -54,9 +54,9 @@ public class HarvesterMovementBehaviour extends MovementBehaviour {
@Override @Override
public void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld, public void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld,
MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffers) { ContraptionMatrices matrices, IRenderTypeBuffer buffers) {
if (!Backend.canUseInstancing()) if (!Backend.canUseInstancing())
HarvesterRenderer.renderInContraption(context, renderWorld, ms, msLocal, buffers); HarvesterRenderer.renderInContraption(context, renderWorld, matrices, buffers);
} }
@Override @Override

View file

@ -5,6 +5,7 @@ import static net.minecraft.state.properties.BlockStateProperties.HORIZONTAL_FAC
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlockPartials;
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher;
import com.simibubi.create.foundation.render.PartialBufferer; import com.simibubi.create.foundation.render.PartialBufferer;
import com.simibubi.create.foundation.render.SuperByteBuffer; import com.simibubi.create.foundation.render.SuperByteBuffer;
@ -41,7 +42,7 @@ public class HarvesterRenderer extends SafeTileEntityRenderer<HarvesterTileEntit
} }
public static void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld, public static void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld,
MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffers) { ContraptionMatrices matrices, IRenderTypeBuffer buffers) {
BlockState blockState = context.state; BlockState blockState = context.state;
Direction facing = blockState.get(HORIZONTAL_FACING); Direction facing = blockState.get(HORIZONTAL_FACING);
SuperByteBuffer superBuffer = PartialBufferer.get(AllBlockPartials.HARVESTER_BLADE, blockState); SuperByteBuffer superBuffer = PartialBufferer.get(AllBlockPartials.HARVESTER_BLADE, blockState);
@ -51,12 +52,13 @@ public class HarvesterRenderer extends SafeTileEntityRenderer<HarvesterTileEntit
if (context.contraption.stalled) if (context.contraption.stalled)
speed = 0; speed = 0;
superBuffer.transform(matrices.contraptionStack);
transform(context.world, facing, superBuffer, speed); transform(context.world, facing, superBuffer, speed);
superBuffer superBuffer
.light(msLocal.peek().getModel(), .light(matrices.entityMatrix,
ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld))
.renderInto(ms, buffers.getBuffer(RenderType.getCutoutMipped())); .renderInto(matrices.entityStack, buffers.getBuffer(RenderType.getCutoutMipped()));
} }
public static void transform(World world, Direction facing, SuperByteBuffer superBuffer, float speed) { public static void transform(World world, Direction facing, SuperByteBuffer superBuffer, float speed) {

View file

@ -2,9 +2,9 @@ package com.simibubi.create.content.contraptions.components.actors;
import java.util.Optional; import java.util.Optional;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour;
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld;
@ -33,8 +33,8 @@ public class PortableStorageInterfaceMovement extends MovementBehaviour {
@Override @Override
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld, public void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld,
MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffer) { ContraptionMatrices matrices, IRenderTypeBuffer buffer) {
PortableStorageInterfaceRenderer.renderInContraption(context, renderWorld, ms, msLocal, buffer); PortableStorageInterfaceRenderer.renderInContraption(context, renderWorld, matrices, buffer);
} }
@Override @Override

View file

@ -8,6 +8,7 @@ import com.mojang.blaze3d.vertex.IVertexBuilder;
import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlockPartials;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher;
import com.simibubi.create.foundation.render.PartialBufferer; import com.simibubi.create.foundation.render.PartialBufferer;
import com.simibubi.create.foundation.render.SuperByteBuffer; import com.simibubi.create.foundation.render.SuperByteBuffer;
@ -43,7 +44,7 @@ public class PortableStorageInterfaceRenderer extends SafeTileEntityRenderer<Por
} }
public static void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld, public static void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld,
MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffer) { ContraptionMatrices matrices, IRenderTypeBuffer buffer) {
BlockState blockState = context.state; BlockState blockState = context.state;
PortableStorageInterfaceTileEntity te = getTargetPSI(context); PortableStorageInterfaceTileEntity te = getTargetPSI(context);
IVertexBuilder vb = buffer.getBuffer(RenderType.getSolid()); IVertexBuilder vb = buffer.getBuffer(RenderType.getSolid());
@ -56,43 +57,38 @@ public class PortableStorageInterfaceRenderer extends SafeTileEntityRenderer<Por
lit = te.isConnected(); lit = te.isConnected();
} }
render(blockState, progress, lit, sbb -> sbb.light(msLocal.peek() render(blockState, progress, lit, sbb -> sbb.transform(matrices.contraptionStack)
.getModel(), ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) .disableDiffuseTransform()
.renderInto(ms, vb), ms, msLocal); .light(matrices.entityMatrix,
ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld))
.renderInto(matrices.entityStack, vb), matrices.contraptionStack);
} }
private static void render(BlockState blockState, float progress, boolean lit, private static void render(BlockState blockState, float progress, boolean lit,
Consumer<SuperByteBuffer> drawCallback, MatrixStack... matrixStacks) { Consumer<SuperByteBuffer> drawCallback, MatrixStack ms) {
for (MatrixStack ms : matrixStacks)
ms.push(); ms.push();
SuperByteBuffer middle = PartialBufferer.get(getMiddleForState(blockState, lit), blockState); SuperByteBuffer middle = PartialBufferer.get(getMiddleForState(blockState, lit), blockState);
SuperByteBuffer top = PartialBufferer.get(getTopForState(blockState), blockState); SuperByteBuffer top = PartialBufferer.get(getTopForState(blockState), blockState);
Direction facing = blockState.get(PortableStorageInterfaceBlock.FACING); Direction facing = blockState.get(PortableStorageInterfaceBlock.FACING);
for (MatrixStack ms : matrixStacks)
MatrixStacker.of(ms) MatrixStacker.of(ms)
.centre() .centre()
.rotateY(AngleHelper.horizontalAngle(facing)) .rotateY(AngleHelper.horizontalAngle(facing))
.rotateX(facing == Direction.UP ? 0 : facing == Direction.DOWN ? 180 : 90) .rotateX(facing == Direction.UP ? 0 : facing == Direction.DOWN ? 180 : 90)
.unCentre(); .unCentre();
for (MatrixStack ms : matrixStacks) {
ms.translate(0, progress / 2f, 0); ms.translate(0, progress / 2f, 0);
ms.push(); ms.push();
ms.translate(0, 6 / 16f, 0); ms.translate(0, 6 / 16f, 0);
}
drawCallback.accept(middle); drawCallback.accept(middle);
for (MatrixStack ms : matrixStacks) {
ms.pop(); ms.pop();
ms.translate(0, progress / 2f, 0); ms.translate(0, progress / 2f, 0);
}
drawCallback.accept(top); drawCallback.accept(top);
for (MatrixStack ms : matrixStacks)
ms.pop(); ms.pop();
} }

View file

@ -1,10 +1,10 @@
package com.simibubi.create.content.contraptions.components.actors; package com.simibubi.create.content.contraptions.components.actors;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.content.contraptions.components.saw.SawBlock; import com.simibubi.create.content.contraptions.components.saw.SawBlock;
import com.simibubi.create.content.contraptions.components.saw.SawRenderer; import com.simibubi.create.content.contraptions.components.saw.SawRenderer;
import com.simibubi.create.content.contraptions.components.saw.SawTileEntity; import com.simibubi.create.content.contraptions.components.saw.SawTileEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices;
import com.simibubi.create.foundation.utility.TreeCutter; import com.simibubi.create.foundation.utility.TreeCutter;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld;
@ -77,8 +77,8 @@ public class SawMovementBehaviour extends BlockBreakingMovementBehaviour {
@Override @Override
@OnlyIn(value = Dist.CLIENT) @OnlyIn(value = Dist.CLIENT)
public void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld, public void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld,
MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffer) { ContraptionMatrices matrices, IRenderTypeBuffer buffer) {
SawRenderer.renderInContraption(context, renderWorld, ms, msLocal, buffer); SawRenderer.renderInContraption(context, renderWorld, matrices, buffer);
} }
@Override @Override

View file

@ -8,7 +8,6 @@ import javax.annotation.Nullable;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.AllTags.AllBlockTags; import com.simibubi.create.AllTags.AllBlockTags;
@ -18,6 +17,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Mov
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices;
import com.simibubi.create.content.logistics.item.filter.FilterItem; import com.simibubi.create.content.logistics.item.filter.FilterItem;
import com.simibubi.create.content.schematics.ItemRequirement; import com.simibubi.create.content.schematics.ItemRequirement;
import com.simibubi.create.content.schematics.SchematicWorld; import com.simibubi.create.content.schematics.SchematicWorld;
@ -256,9 +256,9 @@ public class DeployerMovementBehaviour extends MovementBehaviour {
@Override @Override
public void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld, public void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld,
MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffers) { ContraptionMatrices matrices, IRenderTypeBuffer buffers) {
if (!Backend.canUseInstancing()) if (!Backend.canUseInstancing())
DeployerRenderer.renderInContraption(context, renderWorld, ms, msLocal, buffers); DeployerRenderer.renderInContraption(context, renderWorld, matrices, buffers);
} }
@Override @Override

View file

@ -12,6 +12,7 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.content.contraptions.components.deployer.DeployerTileEntity.Mode; import com.simibubi.create.content.contraptions.components.deployer.DeployerTileEntity.Mode;
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher;
import com.simibubi.create.foundation.render.PartialBufferer; import com.simibubi.create.foundation.render.PartialBufferer;
import com.simibubi.create.foundation.render.SuperByteBuffer; import com.simibubi.create.foundation.render.SuperByteBuffer;
@ -36,7 +37,6 @@ import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.vector.Matrix4f;
import net.minecraft.util.math.vector.Vector3d; import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.util.math.vector.Vector3f; import net.minecraft.util.math.vector.Vector3f;
import net.minecraft.world.World; import net.minecraft.world.World;
@ -156,8 +156,7 @@ public class DeployerRenderer extends SafeTileEntityRenderer<DeployerTileEntity>
} }
public static void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld, public static void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld,
MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffer) { ContraptionMatrices matrices, IRenderTypeBuffer buffer) {
MatrixStack[] matrixStacks = new MatrixStack[]{ms, msLocal};
IVertexBuilder builder = buffer.getBuffer(RenderType.getSolid()); IVertexBuilder builder = buffer.getBuffer(RenderType.getSolid());
BlockState blockState = context.state; BlockState blockState = context.state;
BlockPos pos = BlockPos.ZERO; BlockPos pos = BlockPos.ZERO;
@ -167,8 +166,6 @@ public class DeployerRenderer extends SafeTileEntityRenderer<DeployerTileEntity>
SuperByteBuffer pole = PartialBufferer.get(AllBlockPartials.DEPLOYER_POLE, blockState); SuperByteBuffer pole = PartialBufferer.get(AllBlockPartials.DEPLOYER_POLE, blockState);
SuperByteBuffer hand = PartialBufferer.get(handPose, blockState); SuperByteBuffer hand = PartialBufferer.get(handPose, blockState);
pole = transform(world, pole, blockState, pos, true);
hand = transform(world, hand, blockState, pos, false);
double factor; double factor;
if (context.contraption.stalled || context.position == null || context.data.contains("StationaryTimer")) { if (context.contraption.stalled || context.position == null || context.data.contains("StationaryTimer")) {
@ -184,14 +181,21 @@ public class DeployerRenderer extends SafeTileEntityRenderer<DeployerTileEntity>
Vector3d offset = Vector3d.of(blockState.get(FACING) Vector3d offset = Vector3d.of(blockState.get(FACING)
.getDirectionVec()).scale(factor); .getDirectionVec()).scale(factor);
Matrix4f lighting = msLocal.peek() MatrixStack m = matrices.contraptionStack;
.getModel(); m.push();
for (MatrixStack m : matrixStacks)
m.translate(offset.x, offset.y, offset.z); m.translate(offset.x, offset.y, offset.z);
pole.light(lighting, ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld))
.renderInto(ms, builder); pole.transform(m);
hand.light(lighting, ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) hand.transform(m);
.renderInto(ms, builder); pole = transform(world, pole, blockState, pos, true);
hand = transform(world, hand, blockState, pos, false);
pole.light(matrices.entityMatrix, ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld))
.renderInto(matrices.entityStack, builder);
hand.light(matrices.entityMatrix, ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld))
.renderInto(matrices.entityStack, builder);
m.pop();
} }
static PartialModel getHandPose(DeployerTileEntity.Mode mode) { static PartialModel getHandPose(DeployerTileEntity.Mode mode) {

View file

@ -10,6 +10,7 @@ import com.simibubi.create.CreateClient;
import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher;
import com.simibubi.create.foundation.render.PartialBufferer; import com.simibubi.create.foundation.render.PartialBufferer;
import com.simibubi.create.foundation.render.SuperByteBuffer; import com.simibubi.create.foundation.render.SuperByteBuffer;
@ -153,10 +154,8 @@ public class SawRenderer extends SafeTileEntityRenderer<SawTileEntity> {
} }
public static void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld, public static void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld,
MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffer) { ContraptionMatrices matrices, IRenderTypeBuffer buffer) {
MatrixStack[] matrixStacks = new MatrixStack[] { ms, msLocal };
BlockState state = context.state; BlockState state = context.state;
SuperByteBuffer superBuffer;
Direction facing = state.get(SawBlock.FACING); Direction facing = state.get(SawBlock.FACING);
Vector3d facingVec = Vector3d.of(context.state.get(SawBlock.FACING) Vector3d facingVec = Vector3d.of(context.state.get(SawBlock.FACING)
@ -172,6 +171,7 @@ public class SawRenderer extends SafeTileEntityRenderer<SawTileEntity> {
boolean shouldAnimate = boolean shouldAnimate =
(context.contraption.stalled && horizontal) || (!context.contraption.stalled && !backwards && moving); (context.contraption.stalled && horizontal) || (!context.contraption.stalled && !backwards && moving);
SuperByteBuffer superBuffer;
if (SawBlock.isHorizontal(state)) { if (SawBlock.isHorizontal(state)) {
if (shouldAnimate) if (shouldAnimate)
superBuffer = PartialBufferer.get(AllBlockPartials.SAW_BLADE_HORIZONTAL_ACTIVE, state); superBuffer = PartialBufferer.get(AllBlockPartials.SAW_BLADE_HORIZONTAL_ACTIVE, state);
@ -184,7 +184,8 @@ public class SawRenderer extends SafeTileEntityRenderer<SawTileEntity> {
superBuffer = PartialBufferer.get(AllBlockPartials.SAW_BLADE_VERTICAL_INACTIVE, state); superBuffer = PartialBufferer.get(AllBlockPartials.SAW_BLADE_VERTICAL_INACTIVE, state);
} }
for (MatrixStack m : matrixStacks) { MatrixStack m = matrices.contraptionStack;
m.push();
MatrixStacker.of(m) MatrixStacker.of(m)
.centre() .centre()
.rotateY(AngleHelper.horizontalAngle(facing)) .rotateY(AngleHelper.horizontalAngle(facing))
@ -194,12 +195,15 @@ public class SawRenderer extends SafeTileEntityRenderer<SawTileEntity> {
.rotateZ(state.get(SawBlock.AXIS_ALONG_FIRST_COORDINATE) ? 0 : 90); .rotateZ(state.get(SawBlock.AXIS_ALONG_FIRST_COORDINATE) ? 0 : 90);
MatrixStacker.of(m) MatrixStacker.of(m)
.unCentre(); .unCentre();
}
superBuffer superBuffer
.light(msLocal.peek().getModel(), .transform(m)
.disableDiffuseTransform()
.light(matrices.entityMatrix,
ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld))
.renderInto(ms, buffer.getBuffer(RenderType.getCutoutMipped())); .renderInto(matrices.entityStack, buffer.getBuffer(RenderType.getCutoutMipped()));
m.pop();
} }
} }

View file

@ -641,7 +641,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
} }
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public abstract void doLocalTransforms(float partialTicks, MatrixStack[] matrixStacks); public abstract void doLocalTransforms(float partialTicks, MatrixStack[] matrixStack);
public static class ContraptionRotationState { public static class ContraptionRotationState {
public static final ContraptionRotationState NONE = new ContraptionRotationState(); public static final ContraptionRotationState NONE = new ContraptionRotationState();

View file

@ -1,20 +1,19 @@
package com.simibubi.create.content.contraptions.components.structureMovement; package com.simibubi.create.content.contraptions.components.structureMovement;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.culling.ClippingHelper; import net.minecraft.client.renderer.culling.ClippingHelper;
import net.minecraft.client.renderer.entity.EntityRenderer; import net.minecraft.client.renderer.entity.EntityRenderer;
import net.minecraft.client.renderer.entity.EntityRendererManager; import net.minecraft.client.renderer.entity.EntityRendererManager;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.MathHelper;
public class ContraptionEntityRenderer<C extends AbstractContraptionEntity> extends EntityRenderer<C> { public class ContraptionEntityRenderer<C extends AbstractContraptionEntity> extends EntityRenderer<C> {
public ContraptionEntityRenderer(EntityRendererManager p_i46179_1_) { public ContraptionEntityRenderer(EntityRendererManager manager) {
super(p_i46179_1_); super(manager);
} }
@Override @Override
@ -23,14 +22,14 @@ public class ContraptionEntityRenderer<C extends AbstractContraptionEntity> exte
} }
@Override @Override
public boolean shouldRender(C entity, ClippingHelper clippingHelper, double p_225626_3_, double p_225626_5_, public boolean shouldRender(C entity, ClippingHelper clippingHelper, double cameraX, double cameraY,
double p_225626_7_) { double cameraZ) {
if (entity.getContraption() == null) if (entity.getContraption() == null)
return false; return false;
if (!entity.isAlive()) if (!entity.isAlive())
return false; return false;
return super.shouldRender(entity, clippingHelper, p_225626_3_, p_225626_5_, p_225626_7_); return super.shouldRender(entity, clippingHelper, cameraX, cameraY, cameraZ);
} }
@Override @Override
@ -38,27 +37,11 @@ public class ContraptionEntityRenderer<C extends AbstractContraptionEntity> exte
int overlay) { int overlay) {
super.render(entity, yaw, partialTicks, ms, buffers, overlay); super.render(entity, yaw, partialTicks, ms, buffers, overlay);
// Keep a copy of the transforms in order to determine correct lighting ContraptionMatrices matrices = new ContraptionMatrices(ms, entity);
MatrixStack msLocal = translateTo(entity, AnimationTickHolder.getPartialTicks());
MatrixStack[] matrixStacks = new MatrixStack[] { ms, msLocal };
ms.push();
entity.doLocalTransforms(partialTicks, matrixStacks);
Contraption contraption = entity.getContraption(); Contraption contraption = entity.getContraption();
if (contraption != null) { if (contraption != null) {
ContraptionRenderDispatcher.render(entity, ms, buffers, msLocal, contraption); ContraptionRenderDispatcher.render(entity, contraption, matrices, buffers);
} }
ms.pop();
}
protected MatrixStack translateTo(AbstractContraptionEntity entity, float pt) {
MatrixStack matrixStack = new MatrixStack();
double x = MathHelper.lerp(pt, entity.lastTickPosX, entity.getX());
double y = MathHelper.lerp(pt, entity.lastTickPosY, entity.getY());
double z = MathHelper.lerp(pt, entity.lastTickPosZ, entity.getZ());
matrixStack.translate(x, y, z);
return matrixStack;
} }
} }

View file

@ -2,9 +2,9 @@ package com.simibubi.create.content.contraptions.components.structureMovement;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices;
import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld;
import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer;
@ -62,7 +62,7 @@ public abstract class MovementBehaviour {
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld, public void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld,
MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffer) {} ContraptionMatrices matrices, IRenderTypeBuffer buffer) {}
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
@Nullable @Nullable

View file

@ -4,7 +4,6 @@ import javax.annotation.Nullable;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.core.PartialModel; import com.jozufozu.flywheel.backend.core.PartialModel;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlockPartials;
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity;
@ -13,6 +12,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Mov
import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher;
import com.simibubi.create.foundation.render.PartialBufferer; import com.simibubi.create.foundation.render.PartialBufferer;
import com.simibubi.create.foundation.render.SuperByteBuffer; import com.simibubi.create.foundation.render.SuperByteBuffer;
@ -33,7 +33,7 @@ public class StabilizedBearingMovementBehaviour extends MovementBehaviour {
@Override @Override
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld, public void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld,
MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffer) { ContraptionMatrices matrices, IRenderTypeBuffer buffer) {
if (Backend.canUseInstancing()) return; if (Backend.canUseInstancing()) return;
Direction facing = context.state.get(BlockStateProperties.FACING); Direction facing = context.state.get(BlockStateProperties.FACING);
@ -53,13 +53,14 @@ public class StabilizedBearingMovementBehaviour extends MovementBehaviour {
orientation = rotation; orientation = rotation;
superBuffer.transform(matrices.contraptionStack);
superBuffer.rotateCentered(orientation); superBuffer.rotateCentered(orientation);
// render // render
superBuffer superBuffer
.light(msLocal.peek().getModel(), .light(matrices.entityMatrix,
ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld))
.renderInto(ms, buffer.getBuffer(RenderType.getSolid())); .renderInto(matrices.entityStack, buffer.getBuffer(RenderType.getSolid()));
} }
@Override @Override

View file

@ -0,0 +1,65 @@
package com.simibubi.create.content.contraptions.components.structureMovement.render;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.vector.Matrix3f;
import net.minecraft.util.math.vector.Matrix4f;
public class ContraptionMatrices {
public final MatrixStack entityStack;
public final MatrixStack contraptionStack;
public final Matrix4f entityMatrix;
public ContraptionMatrices(MatrixStack entityStack, AbstractContraptionEntity entity) {
this.entityStack = entityStack;
this.contraptionStack = new MatrixStack();
float partialTicks = AnimationTickHolder.getPartialTicks();
entity.doLocalTransforms(partialTicks, new MatrixStack[] { this.contraptionStack });
entityMatrix = translateTo(entity, partialTicks);
}
public MatrixStack getFinalStack() {
MatrixStack finalStack = new MatrixStack();
transform(finalStack, entityStack);
transform(finalStack, contraptionStack);
return finalStack;
}
public Matrix4f getFinalModel() {
Matrix4f finalModel = entityStack.peek().getModel().copy();
finalModel.multiply(contraptionStack.peek().getModel());
return finalModel;
}
public Matrix3f getFinalNormal() {
Matrix3f finalNormal = entityStack.peek().getNormal().copy();
finalNormal.multiply(contraptionStack.peek().getNormal());
return finalNormal;
}
public Matrix4f getFinalLight() {
Matrix4f lightTransform = entityMatrix.copy();
lightTransform.multiply(contraptionStack.peek().getModel());
return lightTransform;
}
public static Matrix4f translateTo(Entity entity, float partialTicks) {
double x = MathHelper.lerp(partialTicks, entity.lastTickPosX, entity.getX());
double y = MathHelper.lerp(partialTicks, entity.lastTickPosY, entity.getY());
double z = MathHelper.lerp(partialTicks, entity.lastTickPosZ, entity.getZ());
return Matrix4f.translate((float) x, (float) y, (float) z);
}
public static void transform(MatrixStack ms, MatrixStack transform) {
ms.peek().getModel()
.multiply(transform.peek()
.getModel());
ms.peek().getNormal()
.multiply(transform.peek()
.getNormal());
}
}

View file

@ -122,20 +122,20 @@ public class ContraptionRenderDispatcher {
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
} }
public static void render(AbstractContraptionEntity entity, MatrixStack ms, IRenderTypeBuffer buffers, public static void render(AbstractContraptionEntity entity, Contraption contraption,
MatrixStack msLocal, Contraption contraption) { ContraptionMatrices matrices, IRenderTypeBuffer buffers) {
World world = entity.world; World world = entity.world;
if (Backend.canUseVBOs() && Backend.isFlywheelWorld(world)) { if (Backend.canUseVBOs() && Backend.isFlywheelWorld(world)) {
RenderedContraption renderer = getRenderer(world, contraption); RenderedContraption renderer = getRenderer(world, contraption);
PlacementSimulationWorld renderWorld = renderer.renderWorld; PlacementSimulationWorld renderWorld = renderer.renderWorld;
ContraptionRenderDispatcher.renderDynamic(world, renderWorld, contraption, ms, msLocal, buffers); ContraptionRenderDispatcher.renderDynamic(world, renderWorld, contraption, matrices, buffers);
} else { } else {
ContraptionWorldHolder holder = getWorldHolder(world, contraption); ContraptionWorldHolder holder = getWorldHolder(world, contraption);
PlacementSimulationWorld renderWorld = holder.renderWorld; PlacementSimulationWorld renderWorld = holder.renderWorld;
ContraptionRenderDispatcher.renderDynamic(world, renderWorld, contraption, ms, msLocal, buffers); ContraptionRenderDispatcher.renderDynamic(world, renderWorld, contraption, matrices, buffers);
ContraptionRenderDispatcher.renderStructure(world, renderWorld, contraption, ms, msLocal, buffers); ContraptionRenderDispatcher.renderStructure(world, renderWorld, contraption, matrices, buffers);
} }
} }
@ -182,21 +182,21 @@ public class ContraptionRenderDispatcher {
} }
public static void renderDynamic(World world, PlacementSimulationWorld renderWorld, Contraption c, public static void renderDynamic(World world, PlacementSimulationWorld renderWorld, Contraption c,
MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffer) { ContraptionMatrices matrices, IRenderTypeBuffer buffer) {
renderTileEntities(world, renderWorld, c, ms, msLocal, buffer); renderTileEntities(world, renderWorld, c, matrices, buffer);
if (buffer instanceof IRenderTypeBuffer.Impl) if (buffer instanceof IRenderTypeBuffer.Impl)
((IRenderTypeBuffer.Impl) buffer).draw(); ((IRenderTypeBuffer.Impl) buffer).draw();
renderActors(world, renderWorld, c, ms, msLocal, buffer); renderActors(world, renderWorld, c, matrices, buffer);
} }
public static void renderTileEntities(World world, PlacementSimulationWorld renderWorld, Contraption c, public static void renderTileEntities(World world, PlacementSimulationWorld renderWorld, Contraption c,
MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffer) { ContraptionMatrices matrices, IRenderTypeBuffer buffer) {
TileEntityRenderHelper.renderTileEntities(world, renderWorld, c.specialRenderedTileEntities, ms, msLocal, buffer); TileEntityRenderHelper.renderTileEntities(world, renderWorld, c.specialRenderedTileEntities,
matrices.getFinalStack(), matrices.getFinalLight(), buffer);
} }
protected static void renderActors(World world, PlacementSimulationWorld renderWorld, Contraption c, protected static void renderActors(World world, PlacementSimulationWorld renderWorld, Contraption c,
MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffer) { ContraptionMatrices matrices, IRenderTypeBuffer buffer) {
MatrixStack[] matrixStacks = new MatrixStack[] {ms, msLocal};
for (Pair<Template.BlockInfo, MovementContext> actor : c.getActors()) { for (Pair<Template.BlockInfo, MovementContext> actor : c.getActors()) {
MovementContext context = actor.getRight(); MovementContext context = actor.getRight();
if (context == null) if (context == null)
@ -204,23 +204,22 @@ public class ContraptionRenderDispatcher {
if (context.world == null) if (context.world == null)
context.world = world; context.world = world;
Template.BlockInfo blockInfo = actor.getLeft(); Template.BlockInfo blockInfo = actor.getLeft();
for (MatrixStack m : matrixStacks) {
MatrixStack m = matrices.contraptionStack;
m.push(); m.push();
MatrixStacker.of(m) MatrixStacker.of(m)
.translate(blockInfo.pos); .translate(blockInfo.pos);
}
MovementBehaviour movementBehaviour = AllMovementBehaviours.of(blockInfo.state); MovementBehaviour movementBehaviour = AllMovementBehaviours.of(blockInfo.state);
if (movementBehaviour != null) if (movementBehaviour != null)
movementBehaviour.renderInContraption(context, renderWorld, ms, msLocal, buffer); movementBehaviour.renderInContraption(context, renderWorld, matrices, buffer);
for (MatrixStack m : matrixStacks)
m.pop(); m.pop();
} }
} }
public static void renderStructure(World world, PlacementSimulationWorld renderWorld, Contraption c, public static void renderStructure(World world, PlacementSimulationWorld renderWorld, Contraption c,
MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffer) { ContraptionMatrices matrices, IRenderTypeBuffer buffer) {
SuperByteBufferCache bufferCache = CreateClient.bufferCache; SuperByteBufferCache bufferCache = CreateClient.bufferCache;
List<RenderType> blockLayers = RenderType.getBlockLayers(); List<RenderType> blockLayers = RenderType.getBlockLayers();
@ -231,11 +230,11 @@ public class ContraptionRenderDispatcher {
SuperByteBuffer contraptionBuffer = bufferCache.get(CONTRAPTION, key, () -> buildStructureBuffer(renderWorld, c, layer)); SuperByteBuffer contraptionBuffer = bufferCache.get(CONTRAPTION, key, () -> buildStructureBuffer(renderWorld, c, layer));
if (contraptionBuffer.isEmpty()) if (contraptionBuffer.isEmpty())
continue; continue;
Matrix4f model = msLocal.peek() contraptionBuffer
.getModel(); .transform(matrices.contraptionStack)
contraptionBuffer.light(model) .light(matrices.entityMatrix)
.hybridLight() .hybridLight()
.renderInto(ms, buffer.getBuffer(layer)); .renderInto(matrices.entityStack, buffer.getBuffer(layer));
} }
} }
@ -278,29 +277,18 @@ public class ContraptionRenderDispatcher {
public static int getLight(World world, float lx, float ly, float lz) { public static int getLight(World world, float lx, float ly, float lz) {
BlockPos.Mutable pos = new BlockPos.Mutable(); BlockPos.Mutable pos = new BlockPos.Mutable();
float sky = 0, block = 0; float block = 0, sky = 0;
float offset = 1 / 8f; float offset = 1 / 8f;
for (float zOffset = offset; zOffset >= -offset; zOffset -= 2 * offset) for (float zOffset = offset; zOffset >= -offset; zOffset -= 2 * offset)
for (float yOffset = offset; yOffset >= -offset; yOffset -= 2 * offset) for (float yOffset = offset; yOffset >= -offset; yOffset -= 2 * offset)
for (float xOffset = offset; xOffset >= -offset; xOffset -= 2 * offset) { for (float xOffset = offset; xOffset >= -offset; xOffset -= 2 * offset) {
pos.setPos(lx + xOffset, ly + yOffset, lz + zOffset); pos.setPos(lx + xOffset, ly + yOffset, lz + zOffset);
sky += world.getLightLevel(LightType.SKY, pos) / 8f;
block += world.getLightLevel(LightType.BLOCK, pos) / 8f; block += world.getLightLevel(LightType.BLOCK, pos) / 8f;
sky += world.getLightLevel(LightType.SKY, pos) / 8f;
} }
return ((int) sky) << 20 | ((int) block) << 4; return LightTexture.pack((int) block, (int) sky);
}
public static int getContraptionLightAt(World world, PlacementSimulationWorld renderWorld, BlockPos pos, BlockPos lightPos) {
int worldLight = WorldRenderer.getLightmapCoordinates(world, lightPos);
if (renderWorld != null) {
int renderWorldLight = WorldRenderer.getLightmapCoordinates(renderWorld, pos);
return SuperByteBuffer.maxLight(worldLight, renderWorldLight);
}
return worldLight;
} }
public static int getContraptionWorldLight(MovementContext context, PlacementSimulationWorld renderWorld) { public static int getContraptionWorldLight(MovementContext context, PlacementSimulationWorld renderWorld) {

View file

@ -78,8 +78,7 @@ public class SchematicRenderer {
SuperByteBuffer superByteBuffer = bufferCache.get(layer); SuperByteBuffer superByteBuffer = bufferCache.get(layer);
superByteBuffer.renderInto(ms, buffer.getBuffer(layer)); superByteBuffer.renderInto(ms, buffer.getBuffer(layer));
} }
TileEntityRenderHelper.renderTileEntities(schematic, schematic.getRenderedTileEntities(), ms, new MatrixStack(), TileEntityRenderHelper.renderTileEntities(schematic, schematic.getRenderedTileEntities(), ms, buffer);
buffer);
} }
protected void redraw(Minecraft minecraft) { protected void redraw(Minecraft minecraft) {

View file

@ -369,7 +369,7 @@ public class WorldSectionElement extends AnimatedSceneElement {
private void renderTileEntities(PonderWorld world, MatrixStack ms, IRenderTypeBuffer buffer, float pt) { private void renderTileEntities(PonderWorld world, MatrixStack ms, IRenderTypeBuffer buffer, float pt) {
loadTEsIfMissing(world); loadTEsIfMissing(world);
TileEntityRenderHelper.renderTileEntities(world, renderedTileEntities, ms, new MatrixStack(), buffer, pt); TileEntityRenderHelper.renderTileEntities(world, renderedTileEntities, ms, buffer, pt);
} }
private SuperByteBuffer buildStructureBuffer(PonderWorld world, RenderType layer) { private SuperByteBuffer buildStructureBuffer(PonderWorld world, RenderType layer) {

View file

@ -8,11 +8,12 @@ import com.mojang.blaze3d.vertex.IVertexBuilder;
import com.simibubi.create.foundation.block.render.SpriteShiftEntry; import com.simibubi.create.foundation.block.render.SpriteShiftEntry;
import com.simibubi.create.foundation.utility.MatrixStacker; import com.simibubi.create.foundation.utility.MatrixStacker;
import it.unimi.dsi.fastutil.longs.Long2DoubleMap; import it.unimi.dsi.fastutil.longs.Long2IntMap;
import it.unimi.dsi.fastutil.longs.Long2DoubleOpenHashMap; import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
@ -22,31 +23,27 @@ import net.minecraft.util.math.vector.Quaternion;
import net.minecraft.util.math.vector.Vector3d; import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.util.math.vector.Vector3f; import net.minecraft.util.math.vector.Vector3f;
import net.minecraft.util.math.vector.Vector4f; import net.minecraft.util.math.vector.Vector4f;
import net.minecraft.world.LightType;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.client.model.pipeline.LightUtil; import net.minecraftforge.client.model.pipeline.LightUtil;
public class SuperByteBuffer extends TemplateBuffer { public class SuperByteBuffer extends TemplateBuffer {
public interface IVertexLighter {
public int getPackedLight(float x, float y, float z);
}
// Vertex Position // Vertex Position
private MatrixStack transforms; private MatrixStack transforms;
// Vertex Texture Coords // Vertex Texture Coords
private SpriteShiftFunc spriteShiftFunc; private SpriteShiftFunc spriteShiftFunc;
// Vertex Lighting
private boolean shouldLight;
private boolean hybridLight;
private int packedLightCoords;
private Matrix4f lightTransform;
// Vertex Coloring // Vertex Coloring
private boolean shouldColor; private boolean shouldColor;
private int r, g, b, a; private int r, g, b, a;
private boolean disableDiffuseTransform;
// Vertex Lighting
private boolean useWorldLight;
private boolean hybridLight;
private int packedLightCoords;
private Matrix4f lightTransform;
public SuperByteBuffer(BufferBuilder buf) { public SuperByteBuffer(BufferBuilder buf) {
super(buf); super(buf);
@ -63,8 +60,7 @@ public class SuperByteBuffer extends TemplateBuffer {
return (v - sprite.getMinV()) / f * 16.0F; return (v - sprite.getMinV()) / f * 16.0F;
} }
private static final Long2DoubleMap skyLightCache = new Long2DoubleOpenHashMap(); private static final Long2IntMap WORLD_LIGHT_CACHE = new Long2IntOpenHashMap();
private static final Long2DoubleMap blockLightCache = new Long2DoubleOpenHashMap();
Vector4f pos = new Vector4f(); Vector4f pos = new Vector4f();
Vector3f normal = new Vector3f(); Vector3f normal = new Vector3f();
Vector4f lightPos = new Vector4f(); Vector4f lightPos = new Vector4f();
@ -78,7 +74,6 @@ public class SuperByteBuffer extends TemplateBuffer {
Matrix3f normalMat = transforms.peek() Matrix3f normalMat = transforms.peek()
.getNormal() .getNormal()
.copy(); .copy();
// normalMat.multiply(transforms.peek().getNormal());
Matrix4f modelMat = input.peek() Matrix4f modelMat = input.peek()
.getModel() .getModel()
@ -88,11 +83,11 @@ public class SuperByteBuffer extends TemplateBuffer {
.getModel(); .getModel();
modelMat.multiply(localTransforms); modelMat.multiply(localTransforms);
if (shouldLight && lightTransform != null) { if (useWorldLight) {
skyLightCache.clear(); WORLD_LIGHT_CACHE.clear();
blockLightCache.clear();
} }
boolean hasDefaultLight = packedLightCoords != 0;
float f = .5f; float f = .5f;
int vertexCount = vertexCount(buffer); int vertexCount = vertexCount(buffer);
for (int i = 0; i < vertexCount; i++) { for (int i = 0; i < vertexCount; i++) {
@ -127,7 +122,12 @@ public class SuperByteBuffer extends TemplateBuffer {
int colorB = Math.min(255, (int) (((float) this.b) * instanceDiffuse)); int colorB = Math.min(255, (int) (((float) this.b) * instanceDiffuse));
builder.color(colorR, colorG, colorB, this.a); builder.color(colorR, colorG, colorB, this.a);
} else { } else {
float diffuseMult = instanceDiffuse / staticDiffuse; float diffuseMult;
if (disableDiffuseTransform) {
diffuseMult = 1.0f;
} else {
diffuseMult = instanceDiffuse / staticDiffuse;
}
int colorR = Math.min(255, (int) (((float) Byte.toUnsignedInt(r)) * diffuseMult)); int colorR = Math.min(255, (int) (((float) Byte.toUnsignedInt(r)) * diffuseMult));
int colorG = Math.min(255, (int) (((float) Byte.toUnsignedInt(g)) * diffuseMult)); int colorG = Math.min(255, (int) (((float) Byte.toUnsignedInt(g)) * diffuseMult));
int colorB = Math.min(255, (int) (((float) Byte.toUnsignedInt(b)) * diffuseMult)); int colorB = Math.min(255, (int) (((float) Byte.toUnsignedInt(b)) * diffuseMult));
@ -142,23 +142,29 @@ public class SuperByteBuffer extends TemplateBuffer {
} else } else
builder.texture(u, v); builder.texture(u, v);
if (shouldLight) { int light;
int light = packedLightCoords; if (useWorldLight) {
if (lightTransform != null) {
lightPos.set(((x - f) * 15 / 16f) + f, (y - f) * 15 / 16f + f, (z - f) * 15 / 16f + f, 1F); lightPos.set(((x - f) * 15 / 16f) + f, (y - f) * 15 / 16f + f, (z - f) * 15 / 16f + f, 1F);
lightPos.transform(localTransforms); lightPos.transform(localTransforms);
if (lightTransform != null) {
lightPos.transform(lightTransform); lightPos.transform(lightTransform);
int worldLight = getLight(Minecraft.getInstance().world, lightPos);
light = maxLight(worldLight, light);
} }
if (hybridLight) light = getLight(Minecraft.getInstance().world, lightPos);
if (hasDefaultLight) {
light = maxLight(light, packedLightCoords);
}
} else if (hasDefaultLight) {
light = packedLightCoords;
} else {
light = getLight(buffer, i);
}
if (hybridLight) {
builder.light(maxLight(light, getLight(buffer, i))); builder.light(maxLight(light, getLight(buffer, i)));
else } else {
builder.light(light); builder.light(light);
} else }
builder.light(getLight(buffer, i));
builder.normal(nx, ny, nz) builder.normal(nx, ny, nz)
.endVertex(); .endVertex();
@ -170,15 +176,16 @@ public class SuperByteBuffer extends TemplateBuffer {
public SuperByteBuffer reset() { public SuperByteBuffer reset() {
transforms = new MatrixStack(); transforms = new MatrixStack();
spriteShiftFunc = null; spriteShiftFunc = null;
shouldLight = false;
hybridLight = false;
packedLightCoords = 0;
lightTransform = null;
shouldColor = false; shouldColor = false;
r = 0; r = 0;
g = 0; g = 0;
b = 0; b = 0;
a = 0; a = 0;
disableDiffuseTransform = false;
useWorldLight = false;
hybridLight = false;
packedLightCoords = 0;
lightTransform = null;
return this; return this;
} }
@ -234,6 +241,20 @@ public class SuperByteBuffer extends TemplateBuffer {
.translate(-.5f, -.5f, -.5f); .translate(-.5f, -.5f, -.5f);
} }
public SuperByteBuffer color(int color) {
shouldColor = true;
r = ((color >> 16) & 0xFF);
g = ((color >> 8) & 0xFF);
b = (color & 0xFF);
a = 255;
return this;
}
public SuperByteBuffer disableDiffuseTransform() {
disableDiffuseTransform = true;
return this;
}
public SuperByteBuffer shiftUV(SpriteShiftEntry entry) { public SuperByteBuffer shiftUV(SpriteShiftEntry entry) {
this.spriteShiftFunc = (builder, u, v) -> { this.spriteShiftFunc = (builder, u, v) -> {
float targetU = entry.getTarget() float targetU = entry.getTarget()
@ -270,20 +291,24 @@ public class SuperByteBuffer extends TemplateBuffer {
return this; return this;
} }
public SuperByteBuffer light(int packedLightCoords) { public SuperByteBuffer light() {
shouldLight = true; useWorldLight = true;
this.packedLightCoords = packedLightCoords;
return this; return this;
} }
public SuperByteBuffer light(Matrix4f lightTransform) { public SuperByteBuffer light(Matrix4f lightTransform) {
shouldLight = true; useWorldLight = true;
this.lightTransform = lightTransform; this.lightTransform = lightTransform;
return this; return this;
} }
public SuperByteBuffer light(int packedLightCoords) {
this.packedLightCoords = packedLightCoords;
return this;
}
public SuperByteBuffer light(Matrix4f lightTransform, int packedLightCoords) { public SuperByteBuffer light(Matrix4f lightTransform, int packedLightCoords) {
shouldLight = true; useWorldLight = true;
this.lightTransform = lightTransform; this.lightTransform = lightTransform;
this.packedLightCoords = packedLightCoords; this.packedLightCoords = packedLightCoords;
return this; return this;
@ -294,15 +319,6 @@ public class SuperByteBuffer extends TemplateBuffer {
return this; return this;
} }
public SuperByteBuffer color(int color) {
shouldColor = true;
r = ((color >> 16) & 0xFF);
g = ((color >> 8) & 0xFF);
b = (color & 0xFF);
a = 255;
return this;
}
public static int maxLight(int packedLight1, int packedLight2) { public static int maxLight(int packedLight1, int packedLight2) {
int blockLight1 = LightTexture.getBlockLightCoordinates(packedLight1); int blockLight1 = LightTexture.getBlockLightCoordinates(packedLight1);
int skyLight1 = LightTexture.getSkyLightCoordinates(packedLight1); int skyLight1 = LightTexture.getSkyLightCoordinates(packedLight1);
@ -312,12 +328,8 @@ public class SuperByteBuffer extends TemplateBuffer {
} }
private static int getLight(World world, Vector4f lightPos) { private static int getLight(World world, Vector4f lightPos) {
BlockPos.Mutable pos = new BlockPos.Mutable(); BlockPos pos = new BlockPos(lightPos.getX(), lightPos.getY(), lightPos.getZ());
double sky = 0, block = 0; return WORLD_LIGHT_CACHE.computeIfAbsent(pos.toLong(), $ -> WorldRenderer.getLightmapCoordinates(world, pos));
pos.setPos(lightPos.getX() + 0, lightPos.getY() + 0, lightPos.getZ() + 0);
sky += skyLightCache.computeIfAbsent(pos.toLong(), $ -> world.getLightLevel(LightType.SKY, pos));
block += blockLightCache.computeIfAbsent(pos.toLong(), $ -> world.getLightLevel(LightType.BLOCK, pos));
return ((int) sky) << 20 | ((int) block) << 4;
} }
public boolean isEmpty() { public boolean isEmpty() {
@ -329,4 +341,9 @@ public class SuperByteBuffer extends TemplateBuffer {
void shift(IVertexBuilder builder, float u, float v); void shift(IVertexBuilder builder, float u, float v);
} }
@FunctionalInterface
public interface IVertexLighter {
public int getPackedLight(float x, float y, float z);
}
} }

View file

@ -2,15 +2,17 @@ package com.simibubi.create.foundation.render;
import java.util.Iterator; import java.util.Iterator;
import javax.annotation.Nullable;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.Create; import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher;
import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.MatrixStacker; import com.simibubi.create.foundation.utility.MatrixStacker;
import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld;
import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.client.renderer.tileentity.TileEntityRenderer; import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
@ -23,28 +25,26 @@ import net.minecraft.world.World;
public class TileEntityRenderHelper { public class TileEntityRenderHelper {
public static void renderTileEntities(World world, Iterable<TileEntity> customRenderTEs, MatrixStack ms, public static void renderTileEntities(World world, Iterable<TileEntity> customRenderTEs, MatrixStack ms,
MatrixStack localTransform, IRenderTypeBuffer buffer) { IRenderTypeBuffer buffer) {
renderTileEntities(world, null, customRenderTEs, ms, localTransform, buffer); renderTileEntities(world, null, customRenderTEs, ms, null, buffer);
} }
public static void renderTileEntities(World world, Iterable<TileEntity> customRenderTEs, MatrixStack ms, public static void renderTileEntities(World world, Iterable<TileEntity> customRenderTEs, MatrixStack ms,
MatrixStack localTransform, IRenderTypeBuffer buffer, float pt) { IRenderTypeBuffer buffer, float pt) {
renderTileEntities(world, null, customRenderTEs, ms, localTransform, buffer, pt); renderTileEntities(world, null, customRenderTEs, ms, null, buffer, pt);
} }
public static void renderTileEntities(World world, PlacementSimulationWorld renderWorld, public static void renderTileEntities(World world, @Nullable PlacementSimulationWorld renderWorld,
Iterable<TileEntity> customRenderTEs, MatrixStack ms, MatrixStack localTransform, IRenderTypeBuffer buffer) { Iterable<TileEntity> customRenderTEs, MatrixStack ms, @Nullable Matrix4f lightTransform, IRenderTypeBuffer buffer) {
renderTileEntities(world, renderWorld, customRenderTEs, ms, localTransform, buffer, renderTileEntities(world, renderWorld, customRenderTEs, ms, lightTransform, buffer,
AnimationTickHolder.getPartialTicks()); AnimationTickHolder.getPartialTicks());
} }
public static void renderTileEntities(World world, PlacementSimulationWorld renderWorld, public static void renderTileEntities(World world, @Nullable PlacementSimulationWorld renderWorld,
Iterable<TileEntity> customRenderTEs, MatrixStack ms, MatrixStack localTransform, IRenderTypeBuffer buffer, Iterable<TileEntity> customRenderTEs, MatrixStack ms, @Nullable Matrix4f lightTransform, IRenderTypeBuffer buffer,
float pt) { float pt) {
Matrix4f matrix = localTransform.peek() Iterator<TileEntity> iterator = customRenderTEs.iterator();
.getModel(); while (iterator.hasNext()) {
for (Iterator<TileEntity> iterator = customRenderTEs.iterator(); iterator.hasNext();) {
TileEntity tileEntity = iterator.next(); TileEntity tileEntity = iterator.next();
// if (tileEntity instanceof IInstanceRendered) continue; // TODO: some things still need to render // if (tileEntity instanceof IInstanceRendered) continue; // TODO: some things still need to render
@ -60,10 +60,15 @@ public class TileEntityRenderHelper {
.translate(pos); .translate(pos);
try { try {
Vector4f vec = new Vector4f(pos.getX() + .5f, pos.getY() + .5f, pos.getZ() + .5f, 1); BlockPos lightPos;
vec.transform(matrix); if (lightTransform != null) {
BlockPos lightPos = new BlockPos(vec.getX(), vec.getY(), vec.getZ()); Vector4f lightVec = new Vector4f(pos.getX() + .5f, pos.getY() + .5f, pos.getZ() + .5f, 1);
int worldLight = ContraptionRenderDispatcher.getContraptionLightAt(world, renderWorld, pos, lightPos); lightVec.transform(lightTransform);
lightPos = new BlockPos(lightVec.getX(), lightVec.getY(), lightVec.getZ());
} else {
lightPos = pos;
}
int worldLight = getCombinedLight(world, lightPos, renderWorld, pos);
renderer.render(tileEntity, pt, ms, buffer, worldLight, OverlayTexture.DEFAULT_UV); renderer.render(tileEntity, pt, ms, buffer, worldLight, OverlayTexture.DEFAULT_UV);
} catch (Exception e) { } catch (Exception e) {
@ -82,4 +87,16 @@ public class TileEntityRenderHelper {
} }
} }
public static int getCombinedLight(World world, BlockPos worldPos, @Nullable PlacementSimulationWorld renderWorld,
BlockPos renderWorldPos) {
int worldLight = WorldRenderer.getLightmapCoordinates(world, worldPos);
if (renderWorld != null) {
int renderWorldLight = WorldRenderer.getLightmapCoordinates(renderWorld, renderWorldPos);
return SuperByteBuffer.maxLight(worldLight, renderWorldLight);
}
return worldLight;
}
} }