Add lighting to non-Flywheel contraptions

- Pass contraption world to movement behavior rendering
- Add hybrid lighting option to SuperByteBuffer (takes max of world light and vertex light)
- Create ContraptionWorldHolder for caching contraption worlds for contraptions that are not rendered with Flywheel
- Refactor some parts of contraption rendering
This commit is contained in:
PepperBell 2021-05-15 00:21:20 -07:00
parent 8efe8ed01e
commit 67052fd00c
18 changed files with 266 additions and 268 deletions

View file

@ -8,6 +8,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Mov
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.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer;
@ -34,10 +35,10 @@ public class DrillMovementBehaviour extends BlockBreakingMovementBehaviour {
@Override @Override
@OnlyIn(value = Dist.CLIENT) @OnlyIn(value = Dist.CLIENT)
public void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, public void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld,
IRenderTypeBuffer buffer) { MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffer) {
if (!Backend.canUseInstancing()) if (!Backend.canUseInstancing())
DrillRenderer.renderInContraption(context, ms, msLocal, buffer); DrillRenderer.renderInContraption(context, renderWorld, ms, msLocal, buffer);
} }
@Override @Override

View file

@ -5,12 +5,14 @@ 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.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;
import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AngleHelper;
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.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer;
@ -29,8 +31,8 @@ public class DrillRenderer extends KineticTileEntityRenderer {
return PartialBufferer.getFacing(AllBlockPartials.DRILL_HEAD, te.getBlockState()); return PartialBufferer.getFacing(AllBlockPartials.DRILL_HEAD, te.getBlockState());
} }
public static void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, public static void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld,
IRenderTypeBuffer buffer) { MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffer) {
MatrixStack[] matrixStacks = new MatrixStack[]{ms, msLocal}; 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);
@ -51,8 +53,8 @@ public class DrillRenderer extends KineticTileEntityRenderer {
.unCentre(); .unCentre();
superBuffer superBuffer
.light(msLocal.peek() .light(msLocal.peek().getModel(),
.getModel()) ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld))
.renderInto(ms, buffer.getBuffer(RenderType.getSolid())); .renderInto(ms, buffer.getBuffer(RenderType.getSolid()));
} }

View file

@ -14,6 +14,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.ren
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer;
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 net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
@ -52,10 +53,10 @@ public class HarvesterMovementBehaviour extends MovementBehaviour {
} }
@Override @Override
public void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, public void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld,
IRenderTypeBuffer buffers) { MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffers) {
if (!Backend.canUseInstancing()) if (!Backend.canUseInstancing())
HarvesterRenderer.renderInContraption(context, ms, msLocal, buffers); HarvesterRenderer.renderInContraption(context, renderWorld, ms, msLocal, buffers);
} }
@Override @Override

View file

@ -12,6 +12,7 @@ import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer
import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer;
@ -39,8 +40,8 @@ public class HarvesterRenderer extends SafeTileEntityRenderer<HarvesterTileEntit
.renderInto(ms, buffer.getBuffer(RenderType.getCutoutMipped())); .renderInto(ms, buffer.getBuffer(RenderType.getCutoutMipped()));
} }
public static void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, public static void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld,
IRenderTypeBuffer buffers) { MatrixStack ms, MatrixStack msLocal, 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);
@ -52,8 +53,9 @@ public class HarvesterRenderer extends SafeTileEntityRenderer<HarvesterTileEntit
transform(context.world, facing, superBuffer, speed); transform(context.world, facing, superBuffer, speed);
superBuffer.light(msLocal.peek() superBuffer
.getModel(), ContraptionRenderDispatcher.getLightOnContraption(context)) .light(msLocal.peek().getModel(),
ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld))
.renderInto(ms, buffers.getBuffer(RenderType.getCutoutMipped())); .renderInto(ms, buffers.getBuffer(RenderType.getCutoutMipped()));
} }

View file

@ -6,6 +6,7 @@ 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.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer;
@ -31,9 +32,9 @@ public class PortableStorageInterfaceMovement extends MovementBehaviour {
@Override @Override
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, public void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld,
IRenderTypeBuffer buffer) { MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffer) {
PortableStorageInterfaceRenderer.renderInContraption(context, ms, msLocal, buffer); PortableStorageInterfaceRenderer.renderInContraption(context, renderWorld, ms, msLocal, buffer);
} }
@Override @Override

View file

@ -15,6 +15,7 @@ import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer
import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AngleHelper;
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 net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer;
@ -41,8 +42,8 @@ public class PortableStorageInterfaceRenderer extends SafeTileEntityRenderer<Por
.renderInto(ms, vb), ms); .renderInto(ms, vb), ms);
} }
public static void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, public static void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld,
IRenderTypeBuffer buffer) { MatrixStack ms, MatrixStack msLocal, 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,7 +57,7 @@ public class PortableStorageInterfaceRenderer extends SafeTileEntityRenderer<Por
} }
render(blockState, progress, lit, sbb -> sbb.light(msLocal.peek() render(blockState, progress, lit, sbb -> sbb.light(msLocal.peek()
.getModel(), ContraptionRenderDispatcher.getLightOnContraption(context)) .getModel(), ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld))
.renderInto(ms, vb), ms, msLocal); .renderInto(ms, vb), ms, msLocal);
} }

View file

@ -1,5 +1,6 @@
package com.simibubi.create.content.contraptions.components.actors; package com.simibubi.create.content.contraptions.components.actors;
import com.jozufozu.flywheel.backend.Backend;
import com.mojang.blaze3d.matrix.MatrixStack; 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;
@ -7,6 +8,7 @@ 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.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 net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer;
@ -75,9 +77,9 @@ public class SawMovementBehaviour extends BlockBreakingMovementBehaviour {
@Override @Override
@OnlyIn(value = Dist.CLIENT) @OnlyIn(value = Dist.CLIENT)
public void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, public void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld,
IRenderTypeBuffer buffer) { MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffer) {
SawRenderer.renderInContraption(context, ms, msLocal, buffer); SawRenderer.renderInContraption(context, renderWorld, ms, msLocal, buffer);
} }
@Override @Override

View file

@ -27,6 +27,7 @@ import com.simibubi.create.foundation.item.ItemHelper.ExtractionCountMode;
import com.simibubi.create.foundation.utility.BlockHelper; import com.simibubi.create.foundation.utility.BlockHelper;
import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.NBTHelper;
import com.simibubi.create.foundation.utility.NBTProcessors; import com.simibubi.create.foundation.utility.NBTProcessors;
import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer;
@ -254,10 +255,10 @@ public class DeployerMovementBehaviour extends MovementBehaviour {
} }
@Override @Override
public void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, public void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld,
IRenderTypeBuffer buffers) { MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffers) {
if (!Backend.canUseInstancing()) if (!Backend.canUseInstancing())
DeployerRenderer.renderInContraption(context, ms, msLocal, buffers); DeployerRenderer.renderInContraption(context, renderWorld, ms, msLocal, buffers);
} }
@Override @Override

View file

@ -21,6 +21,7 @@ import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.NBTHelper;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
@ -154,8 +155,8 @@ public class DeployerRenderer extends SafeTileEntityRenderer<DeployerTileEntity>
return buffer; return buffer;
} }
public static void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, public static void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld,
IRenderTypeBuffer buffer) { MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffer) {
MatrixStack[] matrixStacks = new MatrixStack[]{ms, msLocal}; 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;
@ -187,9 +188,9 @@ public class DeployerRenderer extends SafeTileEntityRenderer<DeployerTileEntity>
.getModel(); .getModel();
for (MatrixStack m : matrixStacks) for (MatrixStack m : matrixStacks)
m.translate(offset.x, offset.y, offset.z); m.translate(offset.x, offset.y, offset.z);
pole.light(lighting, ContraptionRenderDispatcher.getLightOnContraption(context)) pole.light(lighting, ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld))
.renderInto(ms, builder); .renderInto(ms, builder);
hand.light(lighting, ContraptionRenderDispatcher.getLightOnContraption(context)) hand.light(lighting, ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld))
.renderInto(ms, builder); .renderInto(ms, builder);
} }

View file

@ -18,6 +18,7 @@ import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer
import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.MatrixStacker; import com.simibubi.create.foundation.utility.MatrixStacker;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
@ -151,8 +152,8 @@ public class SawRenderer extends SafeTileEntityRenderer<SawTileEntity> {
return KineticTileEntityRenderer.shaft(KineticTileEntityRenderer.getRotationAxisOf(te)); return KineticTileEntityRenderer.shaft(KineticTileEntityRenderer.getRotationAxisOf(te));
} }
public static void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, public static void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld,
IRenderTypeBuffer buffer) { MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffer) {
MatrixStack[] matrixStacks = new MatrixStack[] { ms, msLocal }; MatrixStack[] matrixStacks = new MatrixStack[] { ms, msLocal };
BlockState state = context.state; BlockState state = context.state;
SuperByteBuffer superBuffer; SuperByteBuffer superBuffer;
@ -196,8 +197,8 @@ public class SawRenderer extends SafeTileEntityRenderer<SawTileEntity> {
} }
superBuffer superBuffer
.light(msLocal.peek() .light(msLocal.peek().getModel(),
.getModel(), ContraptionRenderDispatcher.getLightOnContraption(context)) ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld))
.renderInto(ms, buffer.getBuffer(RenderType.getCutoutMipped())); .renderInto(ms, buffer.getBuffer(RenderType.getCutoutMipped()));
} }

View file

@ -5,6 +5,7 @@ import javax.annotation.Nullable;
import com.mojang.blaze3d.matrix.MatrixStack; 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.foundation.utility.worldWrappers.PlacementSimulationWorld;
import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.entity.item.ItemEntity; import net.minecraft.entity.item.ItemEntity;
@ -60,8 +61,8 @@ public abstract class MovementBehaviour {
} }
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, public void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld,
IRenderTypeBuffer buffer) {} MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffer) {}
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
@Nullable @Nullable

View file

@ -17,6 +17,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.ren
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;
import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld;
import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderType;
@ -31,8 +32,8 @@ public class StabilizedBearingMovementBehaviour extends MovementBehaviour {
@Override @Override
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, public void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld,
IRenderTypeBuffer buffer) { MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffer) {
if (Backend.canUseInstancing()) return; if (Backend.canUseInstancing()) return;
Direction facing = context.state.get(BlockStateProperties.FACING); Direction facing = context.state.get(BlockStateProperties.FACING);
@ -55,9 +56,10 @@ public class StabilizedBearingMovementBehaviour extends MovementBehaviour {
superBuffer.rotateCentered(orientation); superBuffer.rotateCentered(orientation);
// render // render
superBuffer.light(msLocal.peek() superBuffer
.getModel(), ContraptionRenderDispatcher.getLightOnContraption(context)); .light(msLocal.peek().getModel(),
superBuffer.renderInto(ms, buffer.getBuffer(RenderType.getSolid())); ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld))
.renderInto(ms, buffer.getBuffer(RenderType.getSolid()));
} }
@Override @Override

View file

@ -1,17 +1,17 @@
package com.simibubi.create.content.contraptions.components.structureMovement.render; package com.simibubi.create.content.contraptions.components.structureMovement.render;
import static org.lwjgl.opengl.GL13.GL_QUADS; import static org.lwjgl.opengl.GL11.glDisable;
import static org.lwjgl.opengl.GL11.glEnable;
import static org.lwjgl.opengl.GL12.GL_TEXTURE_3D;
import static org.lwjgl.opengl.GL13.GL_TEXTURE0; import static org.lwjgl.opengl.GL13.GL_TEXTURE0;
import static org.lwjgl.opengl.GL13.GL_TEXTURE4; import static org.lwjgl.opengl.GL13.GL_TEXTURE4;
import static org.lwjgl.opengl.GL13.GL_TEXTURE_3D;
import static org.lwjgl.opengl.GL13.glActiveTexture; import static org.lwjgl.opengl.GL13.glActiveTexture;
import static org.lwjgl.opengl.GL13.glDisable;
import static org.lwjgl.opengl.GL13.glEnable;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import org.lwjgl.opengl.GL11;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
@ -36,7 +36,7 @@ import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.ActiveRenderInfo; import net.minecraft.client.renderer.ActiveRenderInfo;
import net.minecraft.client.renderer.BlockModelRenderer; import net.minecraft.client.renderer.BlockModelRenderer;
import net.minecraft.client.renderer.BlockRendererDispatcher; import net.minecraft.client.renderer.BlockModelShapes;
import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer;
@ -44,7 +44,6 @@ import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.RenderTypeLookup; import net.minecraft.client.renderer.RenderTypeLookup;
import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.world.ClientWorld; import net.minecraft.client.world.ClientWorld;
@ -57,25 +56,34 @@ import net.minecraftforge.client.ForgeHooksClient;
import net.minecraftforge.client.model.data.EmptyModelData; import net.minecraftforge.client.model.data.EmptyModelData;
public class ContraptionRenderDispatcher { public class ContraptionRenderDispatcher {
public static final Int2ObjectMap<RenderedContraption> renderers = new Int2ObjectOpenHashMap<>(); private static final BlockModelRenderer MODEL_RENDERER = new BlockModelRenderer(Minecraft.getInstance().getBlockColors());
private static final BlockModelShapes BLOCK_MODELS = Minecraft.getInstance().getModelManager().getBlockModelShapes();
private static int ticksUntilHolderRefresh;
public static final Int2ObjectMap<RenderedContraption> RENDERERS = new Int2ObjectOpenHashMap<>();
public static final Int2ObjectMap<ContraptionWorldHolder> WORLD_HOLDERS = new Int2ObjectOpenHashMap<>();
public static final Compartment<Pair<Contraption, Integer>> CONTRAPTION = new Compartment<>(); public static final Compartment<Pair<Contraption, Integer>> CONTRAPTION = new Compartment<>();
protected static PlacementSimulationWorld renderWorld;
public static void tick() { public static void tick() {
if (Minecraft.getInstance().isGamePaused()) return; if (Minecraft.getInstance().isGamePaused()) return;
for (RenderedContraption contraption : renderers.values()) { for (RenderedContraption contraption : RENDERERS.values()) {
contraption.getLighter().tick(contraption); contraption.getLighter().tick(contraption);
contraption.kinetics.tick(); contraption.kinetics.tick();
} }
if (ticksUntilHolderRefresh <= 0) {
removeDeadHolders();
ticksUntilHolderRefresh = 20;
}
} }
public static void beginFrame(ClientWorld world, MatrixStack stack, ActiveRenderInfo info, GameRenderer gameRenderer, LightTexture lightTexture) { public static void beginFrame(ClientWorld world, MatrixStack stack, ActiveRenderInfo info, GameRenderer gameRenderer, LightTexture lightTexture) {
double camX = info.getProjectedView().x; double camX = info.getProjectedView().x;
double camY = info.getProjectedView().y; double camY = info.getProjectedView().y;
double camZ = info.getProjectedView().z; double camZ = info.getProjectedView().z;
for (RenderedContraption renderer : renderers.values()) { for (RenderedContraption renderer : RENDERERS.values()) {
renderer.beginFrame(info, camX, camY, camZ); renderer.beginFrame(info, camX, camY, camZ);
} }
} }
@ -83,7 +91,7 @@ public class ContraptionRenderDispatcher {
public static void renderLayer(ClientWorld world, RenderType layer, Matrix4f viewProjection, double camX, double camY, double camZ) { public static void renderLayer(ClientWorld world, RenderType layer, Matrix4f viewProjection, double camX, double camY, double camZ) {
removeDeadContraptions(); removeDeadContraptions();
if (renderers.isEmpty()) return; if (RENDERERS.isEmpty()) return;
layer.startDrawing(); layer.startDrawing();
glEnable(GL_TEXTURE_3D); glEnable(GL_TEXTURE_3D);
@ -96,13 +104,13 @@ public class ContraptionRenderDispatcher {
structureShader.uploadViewProjection(viewProjection); structureShader.uploadViewProjection(viewProjection);
structureShader.uploadCameraPos(camX, camY, camZ); structureShader.uploadCameraPos(camX, camY, camZ);
for (RenderedContraption renderer : renderers.values()) { for (RenderedContraption renderer : RENDERERS.values()) {
renderer.doRenderLayer(layer, structureShader); renderer.doRenderLayer(layer, structureShader);
} }
} }
if (Backend.canUseInstancing()) { if (Backend.canUseInstancing()) {
for (RenderedContraption renderer : renderers.values()) { for (RenderedContraption renderer : RENDERERS.values()) {
renderer.kinetics.render(layer, viewProjection, camX, camY, camZ, renderer::setup); renderer.kinetics.render(layer, viewProjection, camX, camY, camZ, renderer::setup);
renderer.teardown(); renderer.teardown();
} }
@ -113,70 +121,81 @@ public class ContraptionRenderDispatcher {
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
} }
public static void render(AbstractContraptionEntity entity, MatrixStack ms, IRenderTypeBuffer buffers,
MatrixStack msLocal, Contraption contraption) {
World world = entity.world;
if (Backend.canUseVBOs() && Backend.isFlywheelWorld(world)) {
RenderedContraption renderer = getRenderer(world, contraption);
PlacementSimulationWorld renderWorld = renderer.renderWorld;
ContraptionRenderDispatcher.renderDynamic(world, renderWorld, contraption, ms, msLocal, buffers);
} else {
ContraptionWorldHolder holder = getWorldHolder(world, contraption);
PlacementSimulationWorld renderWorld = holder.renderWorld;
ContraptionRenderDispatcher.renderDynamic(world, renderWorld, contraption, ms, msLocal, buffers);
ContraptionRenderDispatcher.renderStructure(world, renderWorld, contraption, ms, msLocal, buffers);
}
}
private static RenderedContraption getRenderer(World world, Contraption c) { private static RenderedContraption getRenderer(World world, Contraption c) {
int entityId = c.entity.getEntityId(); int entityId = c.entity.getEntityId();
RenderedContraption contraption = renderers.get(entityId); RenderedContraption contraption = RENDERERS.get(entityId);
if (contraption == null) { if (contraption == null) {
contraption = new RenderedContraption(world, c); PlacementSimulationWorld renderWorld = setupRenderWorld(world, c);
renderers.put(entityId, contraption); contraption = new RenderedContraption(world, renderWorld, c);
RENDERERS.put(entityId, contraption);
} }
return contraption; return contraption;
} }
public static void render(AbstractContraptionEntity entity, MatrixStack ms, IRenderTypeBuffer buffers, private static ContraptionWorldHolder getWorldHolder(World world, Contraption c) {
MatrixStack msLocal, Contraption contraption) { int entityId = c.entity.getEntityId();
if (Backend.canUseVBOs() && Backend.isFlywheelWorld(entity.world)) { ContraptionWorldHolder holder = WORLD_HOLDERS.get(entityId);
ContraptionRenderDispatcher.renderDynamic(entity.world, contraption, ms, msLocal, buffers);
} else { if (holder == null) {
ContraptionRenderDispatcher.renderDynamic(entity.world, contraption, ms, msLocal, buffers); PlacementSimulationWorld renderWorld = setupRenderWorld(world, c);
ContraptionRenderDispatcher.renderStructure(entity.world, contraption, ms, msLocal, buffers); holder = new ContraptionWorldHolder(c, renderWorld);
WORLD_HOLDERS.put(entityId, holder);
} }
return holder;
} }
public static void renderStructure(World world, Contraption c, MatrixStack ms, MatrixStack msLocal, public static PlacementSimulationWorld setupRenderWorld(World world, Contraption c) {
IRenderTypeBuffer buffer) { PlacementSimulationWorld renderWorld = new PlacementSimulationWorld(world);
SuperByteBufferCache bufferCache = CreateClient.bufferCache;
List<RenderType> blockLayers = RenderType.getBlockLayers();
buffer.getBuffer(RenderType.getSolid()); renderWorld.setTileEntities(c.presentTileEntities.values());
for (int i = 0; i < blockLayers.size(); i++) {
RenderType layer = blockLayers.get(i); for (Template.BlockInfo info : c.getBlocks()
Pair<Contraption, Integer> key = Pair.of(c, i); .values())
SuperByteBuffer contraptionBuffer = bufferCache.get(CONTRAPTION, key, () -> buildStructureBuffer(c, layer)); // Skip individual lighting updates to prevent lag with large contraptions
if (contraptionBuffer.isEmpty()) renderWorld.setBlockState(info.pos, info.state, 128);
continue;
Matrix4f model = msLocal.peek() renderWorld.updateLightSources();
.getModel(); renderWorld.lighter.tick(Integer.MAX_VALUE, false, false);
contraptionBuffer.light(model)
.renderInto(ms, buffer.getBuffer(layer)); return renderWorld;
}
} }
public static void renderDynamic(World world, Contraption c, MatrixStack ms, MatrixStack msLocal, public static void renderDynamic(World world, PlacementSimulationWorld renderWorld, Contraption c,
IRenderTypeBuffer buffer) { MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffer) {
renderTileEntities(world, c, ms, msLocal, buffer); renderTileEntities(world, renderWorld, c, ms, msLocal, buffer);
if (buffer instanceof IRenderTypeBuffer.Impl) if (buffer instanceof IRenderTypeBuffer.Impl)
((IRenderTypeBuffer.Impl) buffer).draw(); ((IRenderTypeBuffer.Impl) buffer).draw();
renderActors(world, c, ms, msLocal, buffer); renderActors(world, renderWorld, c, ms, msLocal, buffer);
} }
public static void renderTileEntities(World world, Contraption c, MatrixStack ms, MatrixStack msLocal, public static void renderTileEntities(World world, PlacementSimulationWorld renderWorld, Contraption c,
IRenderTypeBuffer buffer) { MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffer) {
PlacementSimulationWorld renderWorld = null;
if (Backend.canUseVBOs() && Backend.isFlywheelWorld(world)) {
RenderedContraption renderer = getRenderer(world, c);
renderWorld = renderer.renderWorld;
}
TileEntityRenderHelper.renderTileEntities(world, renderWorld, c.specialRenderedTileEntities, ms, msLocal, buffer); TileEntityRenderHelper.renderTileEntities(world, renderWorld, c.specialRenderedTileEntities, ms, msLocal, buffer);
} }
protected static void renderActors(World world, Contraption c, MatrixStack ms, MatrixStack msLocal, protected static void renderActors(World world, PlacementSimulationWorld renderWorld, Contraption c,
IRenderTypeBuffer buffer) { MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffer) {
MatrixStack[] matrixStacks = new MatrixStack[]{ms, msLocal}; 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)
@ -192,115 +211,112 @@ public class ContraptionRenderDispatcher {
MovementBehaviour movementBehaviour = AllMovementBehaviours.of(blockInfo.state); MovementBehaviour movementBehaviour = AllMovementBehaviours.of(blockInfo.state);
if (movementBehaviour != null) if (movementBehaviour != null)
movementBehaviour.renderInContraption(context, ms, msLocal, buffer); movementBehaviour.renderInContraption(context, renderWorld, ms, msLocal, buffer);
for (MatrixStack m : matrixStacks) for (MatrixStack m : matrixStacks)
m.pop(); m.pop();
} }
} }
private static SuperByteBuffer buildStructureBuffer(Contraption c, RenderType layer) { public static void renderStructure(World world, PlacementSimulationWorld renderWorld, Contraption c,
BufferBuilder builder = buildStructure(c, layer); MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffer) {
SuperByteBufferCache bufferCache = CreateClient.bufferCache;
List<RenderType> blockLayers = RenderType.getBlockLayers();
buffer.getBuffer(RenderType.getSolid());
for (int i = 0; i < blockLayers.size(); i++) {
RenderType layer = blockLayers.get(i);
Pair<Contraption, Integer> key = Pair.of(c, i);
SuperByteBuffer contraptionBuffer = bufferCache.get(CONTRAPTION, key, () -> buildStructureBuffer(renderWorld, c, layer));
if (contraptionBuffer.isEmpty())
continue;
Matrix4f model = msLocal.peek()
.getModel();
contraptionBuffer.light(model)
.hybridLight()
.renderInto(ms, buffer.getBuffer(layer));
}
}
private static SuperByteBuffer buildStructureBuffer(PlacementSimulationWorld renderWorld, Contraption c, RenderType layer) {
BufferBuilder builder = buildStructure(renderWorld, c, layer);
return new SuperByteBuffer(builder); return new SuperByteBuffer(builder);
} }
public static BufferBuilder buildStructure(Contraption c, RenderType layer) { public static BufferBuilder buildStructure(PlacementSimulationWorld renderWorld, Contraption c, RenderType layer) {
if (renderWorld == null || renderWorld.getWorld() != Minecraft.getInstance().world)
renderWorld = new PlacementSimulationWorld(Minecraft.getInstance().world);
ForgeHooksClient.setRenderLayer(layer);
MatrixStack ms = new MatrixStack(); MatrixStack ms = new MatrixStack();
BlockRendererDispatcher dispatcher = Minecraft.getInstance()
.getBlockRendererDispatcher();
BlockModelRenderer blockRenderer = dispatcher.getBlockModelRenderer();
Random random = new Random(); Random random = new Random();
BufferBuilder builder = new BufferBuilder(DefaultVertexFormats.BLOCK.getIntegerSize()); BufferBuilder builder = new BufferBuilder(DefaultVertexFormats.BLOCK.getIntegerSize());
builder.begin(GL_QUADS, DefaultVertexFormats.BLOCK); builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK);
renderWorld.setTileEntities(c.presentTileEntities.values());
ForgeHooksClient.setRenderLayer(layer);
BlockModelRenderer.enableCache();
for (Template.BlockInfo info : c.getBlocks() for (Template.BlockInfo info : c.getBlocks()
.values()) .values()) {
renderWorld.setBlockState(info.pos, info.state);
for (Template.BlockInfo info : c.getBlocks()
.values()) {
BlockState state = info.state; BlockState state = info.state;
if (state.getRenderType() == BlockRenderType.ENTITYBLOCK_ANIMATED) if (state.getRenderType() != BlockRenderType.MODEL)
continue; continue;
if (!RenderTypeLookup.canRenderInLayer(state, layer)) if (!RenderTypeLookup.canRenderInLayer(state, layer))
continue; continue;
IBakedModel originalModel = dispatcher.getModelForState(state); BlockPos pos = info.pos;
ms.push();
ms.translate(info.pos.getX(), info.pos.getY(), info.pos.getZ());
blockRenderer.renderModel(renderWorld, originalModel, state, info.pos, ms, builder, true, random, 42,
OverlayTexture.DEFAULT_UV, EmptyModelData.INSTANCE);
ms.pop();
}
builder.finishDrawing(); ms.push();
renderWorld.clear(); ms.translate(pos.getX(), pos.getY(), pos.getZ());
renderWorld = null; MODEL_RENDERER.renderModel(renderWorld, BLOCK_MODELS.getModel(state), state, pos, ms, builder, true,
return builder; random, 42, OverlayTexture.DEFAULT_UV, EmptyModelData.INSTANCE);
} ms.pop();
public static int getLight(World world, float lx, float ly, float lz) {
BlockPos.Mutable pos = new BlockPos.Mutable();
float sky = 0, block = 0;
float offset = 1 / 8f;
for (float zOffset = offset; zOffset >= -offset; zOffset -= 2 * offset)
for (float yOffset = offset; yOffset >= -offset; yOffset -= 2 * offset)
for (float xOffset = offset; xOffset >= -offset; xOffset -= 2 * offset) {
pos.setPos(lx + xOffset, ly + yOffset, lz + zOffset);
sky += world.getLightLevel(LightType.SKY, pos) / 8f;
block += world.getLightLevel(LightType.BLOCK, pos) / 8f;
}
return ((int) sky) << 20 | ((int) block) << 4;
}
public static int getLightOnContraption(World world, PlacementSimulationWorld renderWorld, BlockPos pos, BlockPos lightPos) {
int worldLight = WorldRenderer.getLightmapCoordinates(world, lightPos);
if (renderWorld != null)
return getMaxBlockLight(worldLight, renderWorld.getLightLevel(LightType.BLOCK, pos));
return worldLight;
}
public static int getMaxBlockLight(int packedLight, int blockLightValue) {
int unpackedBlockLight = LightTexture.getBlockLightCoordinates(packedLight);
if (blockLightValue > unpackedBlockLight) {
packedLight = (packedLight & 0xFFFF0000) | (blockLightValue << 4);
}
return packedLight;
}
public static int getLightOnContraption(MovementContext context) {
int entityId = context.contraption.entity.getEntityId();
RenderedContraption renderedContraption = renderers.get(entityId);
if (renderedContraption != null) {
return renderedContraption.renderWorld.getLightLevel(LightType.BLOCK, context.localPos);
} else {
return -1;
} }
BlockModelRenderer.disableCache();
ForgeHooksClient.setRenderLayer(null);
builder.finishDrawing();
return builder;
}
public static int getLight(World world, float lx, float ly, float lz) {
BlockPos.Mutable pos = new BlockPos.Mutable();
float sky = 0, block = 0;
float offset = 1 / 8f;
for (float zOffset = offset; zOffset >= -offset; zOffset -= 2 * offset)
for (float yOffset = offset; yOffset >= -offset; yOffset -= 2 * offset)
for (float xOffset = offset; xOffset >= -offset; xOffset -= 2 * offset) {
pos.setPos(lx + xOffset, ly + yOffset, lz + zOffset);
sky += world.getLightLevel(LightType.SKY, pos) / 8f;
block += world.getLightLevel(LightType.BLOCK, pos) / 8f;
}
return ((int) sky) << 20 | ((int) block) << 4;
}
public static int 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) {
return WorldRenderer.getLightmapCoordinates(renderWorld, context.localPos);
} }
public static void invalidateAll() { public static void invalidateAll() {
for (RenderedContraption renderer : renderers.values()) { for (RenderedContraption renderer : RENDERERS.values()) {
renderer.invalidate(); renderer.invalidate();
} }
renderers.clear(); RENDERERS.clear();
WORLD_HOLDERS.clear();
} }
public static void removeDeadContraptions() { public static void removeDeadContraptions() {
renderers.values().removeIf(renderer -> { RENDERERS.values().removeIf(renderer -> {
if (renderer.isDead()) { if (renderer.isDead()) {
renderer.invalidate(); renderer.invalidate();
return true; return true;
@ -308,4 +324,8 @@ public class ContraptionRenderDispatcher {
return false; return false;
}); });
} }
public static void removeDeadHolders() {
WORLD_HOLDERS.values().removeIf(ContraptionWorldHolder::isDead);
}
} }

View file

@ -0,0 +1,22 @@
package com.simibubi.create.content.contraptions.components.structureMovement.render;
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld;
public class ContraptionWorldHolder {
public final Contraption contraption;
public final PlacementSimulationWorld renderWorld;
public ContraptionWorldHolder(Contraption contraption, PlacementSimulationWorld renderWorld) {
this.contraption = contraption;
this.renderWorld = renderWorld;
}
public int getEntityId() {
return contraption.entity.getEntityId();
}
public boolean isDead() {
return !contraption.entity.isAlive();
}
}

View file

@ -11,7 +11,7 @@ import com.simibubi.create.foundation.utility.outliner.AABBOutline;
public class LightVolumeDebugger { public class LightVolumeDebugger {
public static void render(MatrixStack ms, SuperRenderTypeBuffer buffer) { public static void render(MatrixStack ms, SuperRenderTypeBuffer buffer) {
ContraptionRenderDispatcher.renderers.values() ContraptionRenderDispatcher.RENDERERS.values()
.stream() .stream()
.flatMap(r -> { .flatMap(r -> {
GridAlignedBB texture = r.getLighter().lightVolume.getTextureVolume(); GridAlignedBB texture = r.getLighter().lightVolume.getTextureVolume();

View file

@ -4,9 +4,6 @@ import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Random;
import org.lwjgl.opengl.GL11;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.instancing.IInstanceRendered; import com.jozufozu.flywheel.backend.instancing.IInstanceRendered;
@ -18,46 +15,29 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Con
import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld;
import net.minecraft.block.BlockRenderType;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.ActiveRenderInfo; import net.minecraft.client.renderer.ActiveRenderInfo;
import net.minecraft.client.renderer.BlockModelRenderer;
import net.minecraft.client.renderer.BlockModelShapes;
import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.RenderTypeLookup;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.AxisAlignedBB;
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.Matrix4f;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.gen.feature.template.Template;
import net.minecraftforge.client.ForgeHooksClient;
import net.minecraftforge.client.model.data.EmptyModelData;
public class RenderedContraption { public class RenderedContraption extends ContraptionWorldHolder {
private static final BlockModelRenderer MODEL_RENDERER = new BlockModelRenderer(Minecraft.getInstance().getBlockColors());
private static final BlockModelShapes BLOCK_MODELS = Minecraft.getInstance().getModelManager().getBlockModelShapes();
public Contraption contraption;
private final ContraptionLighter<?> lighter; private final ContraptionLighter<?> lighter;
public final ContraptionKineticRenderer kinetics; public final ContraptionKineticRenderer kinetics;
public final PlacementSimulationWorld renderWorld;
private final Map<RenderType, ContraptionModel> renderLayers = new HashMap<>(); private final Map<RenderType, ContraptionModel> renderLayers = new HashMap<>();
private Matrix4f model; private Matrix4f model;
private AxisAlignedBB lightBox; private AxisAlignedBB lightBox;
public RenderedContraption(World world, Contraption contraption) { public RenderedContraption(World world, PlacementSimulationWorld renderWorld, Contraption contraption) {
this.contraption = contraption; super(contraption, renderWorld);
this.lighter = contraption.makeLighter(); this.lighter = contraption.makeLighter();
this.kinetics = new ContraptionKineticRenderer(this); this.kinetics = new ContraptionKineticRenderer(this);
this.renderWorld = setupRenderWorld(world, contraption);
buildLayers(); buildLayers();
if (Backend.canUseInstancing()) { if (Backend.canUseInstancing()) {
@ -66,14 +46,6 @@ public class RenderedContraption {
} }
} }
public int getEntityId() {
return contraption.entity.getEntityId();
}
public boolean isDead() {
return !contraption.entity.isAlive();
}
public ContraptionLighter<?> getLighter() { public ContraptionLighter<?> getLighter() {
return lighter; return lighter;
} }
@ -164,55 +136,7 @@ public class RenderedContraption {
} }
private static ContraptionModel buildStructureModel(PlacementSimulationWorld renderWorld, Contraption c, RenderType layer) { private static ContraptionModel buildStructureModel(PlacementSimulationWorld renderWorld, Contraption c, RenderType layer) {
BufferBuilder builder = buildStructure(renderWorld, c, layer); BufferBuilder builder = ContraptionRenderDispatcher.buildStructure(renderWorld, c, layer);
return new ContraptionModel(builder); return new ContraptionModel(builder);
} }
private static PlacementSimulationWorld setupRenderWorld(World world, Contraption c) {
PlacementSimulationWorld renderWorld = new PlacementSimulationWorld(world);
renderWorld.setTileEntities(c.presentTileEntities.values());
for (Template.BlockInfo info : c.getBlocks()
.values())
// Skip individual lighting updates to prevent lag with large contraptions
renderWorld.setBlockState(info.pos, info.state, 128);
renderWorld.updateLightSources();
renderWorld.lighter.tick(Integer.MAX_VALUE, false, false);
return renderWorld;
}
private static BufferBuilder buildStructure(PlacementSimulationWorld renderWorld, Contraption c, RenderType layer) {
MatrixStack ms = new MatrixStack();
Random random = new Random();
BufferBuilder builder = new BufferBuilder(DefaultVertexFormats.BLOCK.getIntegerSize());
builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK);
ForgeHooksClient.setRenderLayer(layer);
BlockModelRenderer.enableCache();
for (Template.BlockInfo info : c.getBlocks()
.values()) {
BlockState state = info.state;
if (state.getRenderType() != BlockRenderType.MODEL)
continue;
if (!RenderTypeLookup.canRenderInLayer(state, layer))
continue;
BlockPos pos = info.pos;
ms.push();
ms.translate(pos.getX(), pos.getY(), pos.getZ());
MODEL_RENDERER.renderModel(renderWorld, BLOCK_MODELS.getModel(state), state, pos, ms, builder, true,
random, 42, OverlayTexture.DEFAULT_UV, EmptyModelData.INSTANCE);
ms.pop();
}
BlockModelRenderer.disableCache();
ForgeHooksClient.setRenderLayer(null);
builder.finishDrawing();
return builder;
}
} }

View file

@ -5,7 +5,6 @@ import java.nio.ByteBuffer;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.vertex.IVertexBuilder; import com.mojang.blaze3d.vertex.IVertexBuilder;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher;
import com.simibubi.create.foundation.block.render.SpriteShiftEntry; import com.simibubi.create.foundation.block.render.SpriteShiftEntry;
import com.simibubi.create.foundation.utility.MatrixStacker; import com.simibubi.create.foundation.utility.MatrixStacker;
@ -13,6 +12,7 @@ import it.unimi.dsi.fastutil.longs.Long2DoubleMap;
import it.unimi.dsi.fastutil.longs.Long2DoubleOpenHashMap; import it.unimi.dsi.fastutil.longs.Long2DoubleOpenHashMap;
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.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;
@ -40,8 +40,8 @@ public class SuperByteBuffer extends TemplateBuffer {
// Vertex Lighting // Vertex Lighting
private boolean shouldLight; private boolean shouldLight;
private boolean hybridLight;
private int packedLightCoords; private int packedLightCoords;
private int otherBlockLight;
private Matrix4f lightTransform; private Matrix4f lightTransform;
// Vertex Coloring // Vertex Coloring
@ -149,12 +149,15 @@ public class SuperByteBuffer extends TemplateBuffer {
lightPos.transform(localTransforms); lightPos.transform(localTransforms);
lightPos.transform(lightTransform); lightPos.transform(lightTransform);
light = getLight(Minecraft.getInstance().world, lightPos); int worldLight = getLight(Minecraft.getInstance().world, lightPos);
if (otherBlockLight >= 0) { if (light >= 0) {
light = ContraptionRenderDispatcher.getMaxBlockLight(light, otherBlockLight); light = maxLight(worldLight, light);
} }
} }
builder.light(light); if (hybridLight)
builder.light(maxLight(light, getLight(buffer, i)));
else
builder.light(light);
} else } else
builder.light(getLight(buffer, i)); builder.light(getLight(buffer, i));
@ -167,7 +170,7 @@ public class SuperByteBuffer extends TemplateBuffer {
spriteShiftFunc = null; spriteShiftFunc = null;
shouldColor = false; shouldColor = false;
shouldLight = false; shouldLight = false;
otherBlockLight = -1; hybridLight = false;
} }
public MatrixStacker matrixStacker() { public MatrixStacker matrixStacker() {
@ -271,10 +274,15 @@ public class SuperByteBuffer extends TemplateBuffer {
return this; return this;
} }
public SuperByteBuffer light(Matrix4f lightTransform, int otherBlockLight) { public SuperByteBuffer light(Matrix4f lightTransform, int packedLightCoords) {
shouldLight = true; shouldLight = true;
this.lightTransform = lightTransform; this.lightTransform = lightTransform;
this.otherBlockLight = otherBlockLight; this.packedLightCoords = packedLightCoords;
return this;
}
public SuperByteBuffer hybridLight() {
hybridLight = true;
return this; return this;
} }
@ -287,6 +295,14 @@ public class SuperByteBuffer extends TemplateBuffer {
return this; return this;
} }
public static int maxLight(int packedLight1, int packedLight2) {
int blockLight1 = LightTexture.getBlockLightCoordinates(packedLight1);
int skyLight1 = LightTexture.getSkyLightCoordinates(packedLight1);
int blockLight2 = LightTexture.getBlockLightCoordinates(packedLight2);
int skyLight2 = LightTexture.getSkyLightCoordinates(packedLight2);
return LightTexture.pack(Math.max(blockLight1, blockLight2), Math.max(skyLight1, skyLight2));
}
private static int getLight(World world, Vector4f lightPos) { private static int getLight(World world, Vector4f lightPos) {
BlockPos.Mutable pos = new BlockPos.Mutable(); BlockPos.Mutable pos = new BlockPos.Mutable();
double sky = 0, block = 0; double sky = 0, block = 0;

View file

@ -63,7 +63,7 @@ public class TileEntityRenderHelper {
Vector4f vec = new Vector4f(pos.getX() + .5f, pos.getY() + .5f, pos.getZ() + .5f, 1); Vector4f vec = new Vector4f(pos.getX() + .5f, pos.getY() + .5f, pos.getZ() + .5f, 1);
vec.transform(matrix); vec.transform(matrix);
BlockPos lightPos = new BlockPos(vec.getX(), vec.getY(), vec.getZ()); BlockPos lightPos = new BlockPos(vec.getX(), vec.getY(), vec.getZ());
int worldLight = ContraptionRenderDispatcher.getLightOnContraption(world, renderWorld, pos, lightPos); int worldLight = ContraptionRenderDispatcher.getContraptionLightAt(world, renderWorld, pos, lightPos);
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) {