contraption actors take into account self lighting

This commit is contained in:
JozsefA 2021-02-13 13:10:14 -08:00
parent 0ad6db4bf7
commit 951a0c4769
12 changed files with 258 additions and 218 deletions

View file

@ -1,7 +1,6 @@
package com.simibubi.create; package com.simibubi.create;
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionRenderer;
import com.simibubi.create.content.contraptions.relays.encased.CasingConnectivity; import com.simibubi.create.content.contraptions.relays.encased.CasingConnectivity;
import com.simibubi.create.content.schematics.ClientSchematicLoader; import com.simibubi.create.content.schematics.ClientSchematicLoader;
import com.simibubi.create.content.schematics.client.SchematicAndQuillHandler; import com.simibubi.create.content.schematics.client.SchematicAndQuillHandler;
@ -74,7 +73,7 @@ public class CreateClient {
bufferCache = new SuperByteBufferCache(); bufferCache = new SuperByteBufferCache();
bufferCache.registerCompartment(KineticTileEntityRenderer.KINETIC_TILE); bufferCache.registerCompartment(KineticTileEntityRenderer.KINETIC_TILE);
bufferCache.registerCompartment(ContraptionRenderer.CONTRAPTION, 20); bufferCache.registerCompartment(ContraptionRenderDispatcher.CONTRAPTION, 20);
AllKeys.register(); AllKeys.register();
AllContainerTypes.registerScreenFactories(); AllContainerTypes.registerScreenFactories();

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.ContraptionRenderDispatcher;
import com.simibubi.create.content.contraptions.components.structureMovement.render.RenderedContraption; import com.simibubi.create.content.contraptions.components.structureMovement.render.RenderedContraption;
import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; import com.simibubi.create.foundation.render.backend.instancing.InstancedModel;
import com.simibubi.create.foundation.render.backend.instancing.RenderMaterial; import com.simibubi.create.foundation.render.backend.instancing.RenderMaterial;
@ -79,7 +80,7 @@ public class HarvesterRenderer extends SafeTileEntityRenderer<HarvesterTileEntit
.rotate(Direction.WEST, AngleHelper.rad(angle)) .rotate(Direction.WEST, AngleHelper.rad(angle))
.translate(-rotOffset.x, -rotOffset.y, -rotOffset.z) .translate(-rotOffset.x, -rotOffset.y, -rotOffset.z)
.light(msLocal.peek() .light(msLocal.peek()
.getModel()) .getModel(), ContraptionRenderDispatcher.getLightOnContraption(context))
.renderInto(ms, buffers.getBuffer(RenderType.getCutoutMipped())); .renderInto(ms, buffers.getBuffer(RenderType.getCutoutMipped()));
} }

View file

@ -5,6 +5,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.ContraptionRenderDispatcher;
import com.simibubi.create.foundation.render.SuperByteBuffer; import com.simibubi.create.foundation.render.SuperByteBuffer;
import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer;
import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AngleHelper;
@ -52,7 +53,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()) .getModel(), ContraptionRenderDispatcher.getLightOnContraption(context))
.renderInto(ms, vb), ms, msLocal); .renderInto(ms, vb), ms, msLocal);
} }

View file

@ -11,6 +11,7 @@ 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.deployer.DeployerTileEntity.State; import com.simibubi.create.content.contraptions.components.deployer.DeployerTileEntity.State;
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.backend.FastRenderDispatcher; import com.simibubi.create.foundation.render.backend.FastRenderDispatcher;
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringRenderer; import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringRenderer;
import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer;
@ -191,9 +192,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) pole.light(lighting, ContraptionRenderDispatcher.getLightOnContraption(context))
.renderInto(ms, builder); .renderInto(ms, builder);
hand.light(lighting) hand.light(lighting, ContraptionRenderDispatcher.getLightOnContraption(context))
.renderInto(ms, builder); .renderInto(ms, builder);
} }

View file

@ -8,6 +8,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.ContraptionRenderDispatcher;
import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import com.simibubi.create.foundation.render.backend.FastRenderDispatcher;
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringRenderer; import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringRenderer;
import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer;
@ -183,7 +184,7 @@ public class SawRenderer extends SafeTileEntityRenderer<SawTileEntity> {
superBuffer superBuffer
.light(msLocal.peek() .light(msLocal.peek()
.getModel()) .getModel(), ContraptionRenderDispatcher.getLightOnContraption(context))
.renderInto(ms, buffer.getBuffer(RenderType.getCutoutMipped())); .renderInto(ms, buffer.getBuffer(RenderType.getCutoutMipped()));
} }

View file

@ -1,8 +1,7 @@
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.foundation.render.backend.Backend; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher;
import com.simibubi.create.foundation.render.backend.FastRenderDispatcher;
import com.simibubi.create.foundation.utility.AnimationTickHolder; 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.ClippingHelperImpl; import net.minecraft.client.renderer.culling.ClippingHelperImpl;
@ -57,12 +56,7 @@ public abstract class AbstractContraptionEntityRenderer<C extends AbstractContra
transform(entity, partialTicks, matrixStacks); transform(entity, partialTicks, matrixStacks);
Contraption contraption = entity.getContraption(); Contraption contraption = entity.getContraption();
if (contraption != null) { if (contraption != null) {
if (Backend.canUseVBOs()) { ContraptionRenderDispatcher.render(entity, ms, buffers, msLocal, contraption);
ContraptionRenderer.renderDynamic(entity.world, contraption, ms, msLocal, buffers);
}
else {
ContraptionRenderer.render(entity.world, contraption, ms, msLocal, buffers);
}
} }
ms.pop(); ms.pop();

View file

@ -1,173 +0,0 @@
package com.simibubi.create.content.contraptions.components.structureMovement;
import java.util.List;
import java.util.Random;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher;
import com.simibubi.create.foundation.render.*;
import com.simibubi.create.foundation.render.backend.Backend;
import com.simibubi.create.foundation.render.backend.FastRenderDispatcher;
import org.apache.commons.lang3.tuple.Pair;
import org.lwjgl.opengl.GL11;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.AllMovementBehaviours;
import com.simibubi.create.CreateClient;
import com.simibubi.create.foundation.utility.MatrixStacker;
import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld;
import net.minecraft.block.BlockRenderType;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BlockModelRenderer;
import net.minecraft.client.renderer.BlockRendererDispatcher;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.Matrix4f;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.RenderTypeLookup;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.LightType;
import net.minecraft.world.World;
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
import net.minecraftforge.client.ForgeHooksClient;
import net.minecraftforge.client.model.data.EmptyModelData;
public class ContraptionRenderer {
public static final Compartment<Pair<Contraption, Integer>> CONTRAPTION = new Compartment<>();
protected static PlacementSimulationWorld renderWorld;
public static void render(World world, Contraption c, MatrixStack ms, MatrixStack msLocal,
IRenderTypeBuffer buffer) {
renderDynamic(world, c, ms, msLocal, buffer);
renderStructure(world, c, ms, msLocal, buffer);
}
public static void renderDynamic(World world, Contraption c, MatrixStack ms, MatrixStack msLocal,
IRenderTypeBuffer buffer) {
renderTileEntities(world, c, ms, msLocal, buffer);
if (buffer instanceof IRenderTypeBuffer.Impl)
((IRenderTypeBuffer.Impl) buffer).draw();
renderActors(world, c, ms, msLocal, buffer);
}
protected static void renderStructure(World world, Contraption c, 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(c, layer));
if (contraptionBuffer.isEmpty())
continue;
Matrix4f model = msLocal.peek()
.getModel();
contraptionBuffer.light(model)
.renderInto(ms, buffer.getBuffer(layer));
}
}
protected static void renderTileEntities(World world, Contraption c, MatrixStack ms, MatrixStack msLocal,
IRenderTypeBuffer buffer) {
if (Backend.canUseVBOs()) {
ContraptionRenderDispatcher.renderTileEntities(world, c, ms, msLocal, buffer);
} else {
TileEntityRenderHelper.renderTileEntities(world, c.maybeInstancedTileEntities, ms, msLocal, buffer);
}
}
private static SuperByteBuffer buildStructureBuffer(Contraption c, RenderType layer) {
BufferBuilder builder = buildStructure(c, layer);
return new SuperByteBuffer(builder);
}
public static BufferBuilder buildStructure(Contraption c, RenderType layer) {
if (renderWorld == null || renderWorld.getWorld() != Minecraft.getInstance().world)
renderWorld = new PlacementSimulationWorld(Minecraft.getInstance().world);
ForgeHooksClient.setRenderLayer(layer);
MatrixStack ms = new MatrixStack();
BlockRendererDispatcher dispatcher = Minecraft.getInstance()
.getBlockRendererDispatcher();
BlockModelRenderer blockRenderer = dispatcher.getBlockModelRenderer();
Random random = new Random();
BufferBuilder builder = new BufferBuilder(DefaultVertexFormats.BLOCK.getIntegerSize());
builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK);
renderWorld.setTileEntities(c.presentTileEntities.values());
for (BlockInfo info : c.getBlocks()
.values())
renderWorld.setBlockState(info.pos, info.state);
for (BlockInfo info : c.getBlocks()
.values()) {
BlockState state = info.state;
if (state.getRenderType() == BlockRenderType.ENTITYBLOCK_ANIMATED)
continue;
if (!RenderTypeLookup.canRenderInLayer(state, layer))
continue;
IBakedModel originalModel = dispatcher.getModelForState(state);
ms.push();
ms.translate(info.pos.getX(), info.pos.getY(), info.pos.getZ());
blockRenderer.renderModel(renderWorld, originalModel, state, info.pos, ms, builder, true, random, 42,
OverlayTexture.DEFAULT_UV, EmptyModelData.INSTANCE);
ms.pop();
}
builder.finishDrawing();
renderWorld.clear();
renderWorld = null;
return builder;
}
protected static void renderActors(World world, Contraption c, MatrixStack ms, MatrixStack msLocal,
IRenderTypeBuffer buffer) {
MatrixStack[] matrixStacks = new MatrixStack[] { ms, msLocal };
for (Pair<BlockInfo, MovementContext> actor : c.getActors()) {
MovementContext context = actor.getRight();
if (context == null)
continue;
if (context.world == null)
context.world = world;
BlockInfo blockInfo = actor.getLeft();
for (MatrixStack m : matrixStacks) {
m.push();
MatrixStacker.of(m)
.translate(blockInfo.pos);
}
MovementBehaviour movementBehaviour = AllMovementBehaviours.of(blockInfo.state);
if (movementBehaviour != null)
movementBehaviour.renderInContraption(context, ms, msLocal, buffer);
for (MatrixStack m : matrixStacks)
m.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;
}
}

View file

@ -3,6 +3,7 @@ package com.simibubi.create.content.contraptions.components.structureMovement.be
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.*; import com.simibubi.create.content.contraptions.components.structureMovement.*;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher;
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;
@ -57,7 +58,7 @@ public class StabilizedBearingMovementBehaviour extends MovementBehaviour {
// render // render
superBuffer.light(msLocal.peek() superBuffer.light(msLocal.peek()
.getModel()); .getModel(), ContraptionRenderDispatcher.getLightOnContraption(context));
superBuffer.renderInto(ms, buffer.getBuffer(RenderType.getSolid())); superBuffer.renderInto(ms, buffer.getBuffer(RenderType.getSolid()));
} }

View file

@ -1,45 +1,51 @@
package com.simibubi.create.content.contraptions.components.structureMovement.render; package com.simibubi.create.content.contraptions.components.structureMovement.render;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; import com.simibubi.create.AllMovementBehaviours;
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntityRenderer; import com.simibubi.create.CreateClient;
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; import com.simibubi.create.content.contraptions.components.structureMovement.*;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionHandler; import com.simibubi.create.foundation.render.*;
import com.simibubi.create.foundation.render.AllProgramSpecs;
import com.simibubi.create.foundation.render.TileEntityRenderHelper;
import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import com.simibubi.create.foundation.render.backend.FastRenderDispatcher;
import com.simibubi.create.foundation.render.backend.Backend; import com.simibubi.create.foundation.render.backend.Backend;
import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.Pair; import com.simibubi.create.foundation.utility.MatrixStacker;
import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import net.minecraft.block.BlockRenderType;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.*;
import net.minecraft.client.renderer.Matrix4f;
import net.minecraft.client.renderer.RenderType;
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.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.world.ClientWorld; import net.minecraft.client.world.ClientWorld;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.SectionPos; import net.minecraft.util.math.SectionPos;
import net.minecraft.world.ILightReader; import net.minecraft.world.ILightReader;
import net.minecraft.world.LightType; import net.minecraft.world.LightType;
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;
import net.minecraftforge.event.TickEvent; import net.minecraftforge.event.TickEvent;
import org.apache.commons.lang3.tuple.Pair;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL13; import org.lwjgl.opengl.GL13;
import org.lwjgl.opengl.GL40; import org.lwjgl.opengl.GL40;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.ArrayList; import java.util.*;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinPool;
public class ContraptionRenderDispatcher { public class ContraptionRenderDispatcher {
public static final Int2ObjectMap<RenderedContraption> renderers = new Int2ObjectOpenHashMap<>(); public static final Int2ObjectMap<RenderedContraption> renderers = new Int2ObjectOpenHashMap<>();
public static final Compartment<Pair<Contraption, Integer>> CONTRAPTION = new Compartment<>();
protected static PlacementSimulationWorld renderWorld;
public static void notifyLightUpdate(ILightReader world, LightType type, SectionPos pos) { public static void notifyLightUpdate(ILightReader world, LightType type, SectionPos pos) {
for (RenderedContraption renderer : renderers.values()) { for (RenderedContraption renderer : renderers.values()) {
@ -48,6 +54,8 @@ public class ContraptionRenderDispatcher {
} }
public static void renderTick(TickEvent.RenderTickEvent event) { public static void renderTick(TickEvent.RenderTickEvent event) {
if (!Backend.canUseVBOs()) return;
ClientWorld world = Minecraft.getInstance().world; ClientWorld world = Minecraft.getInstance().world;
if (event.phase == TickEvent.Phase.START && world != null) { if (event.phase == TickEvent.Phase.START && world != null) {
Map<Integer, WeakReference<AbstractContraptionEntity>> map = ContraptionHandler.loadedContraptions.get(world); Map<Integer, WeakReference<AbstractContraptionEntity>> map = ContraptionHandler.loadedContraptions.get(world);
@ -70,9 +78,13 @@ public class ContraptionRenderDispatcher {
public static void renderTileEntities(World world, Contraption c, MatrixStack ms, MatrixStack msLocal, public static void renderTileEntities(World world, Contraption c, MatrixStack ms, MatrixStack msLocal,
IRenderTypeBuffer buffer) { IRenderTypeBuffer buffer) {
if (Backend.canUseInstancing()) {
RenderedContraption renderer = getRenderer(world, c); RenderedContraption renderer = getRenderer(world, c);
TileEntityRenderHelper.renderTileEntities(world, renderer.renderWorld, c.specialRenderedTileEntities, ms, msLocal, buffer); TileEntityRenderHelper.renderTileEntities(world, renderer.renderWorld, c.specialRenderedTileEntities, ms, msLocal, buffer);
} else {
TileEntityRenderHelper.renderTileEntities(world, c.specialRenderedTileEntities, ms, msLocal, buffer);
}
} }
private static <C extends AbstractContraptionEntity> void updateTransform(C c, AbstractContraptionEntityRenderer<C> entityRenderer) { private static <C extends AbstractContraptionEntity> void updateTransform(C c, AbstractContraptionEntityRenderer<C> entityRenderer) {
@ -152,4 +164,158 @@ public class ContraptionRenderDispatcher {
renderers.clear(); renderers.clear();
} }
public static void render(AbstractContraptionEntity entity, MatrixStack ms, IRenderTypeBuffer buffers,
MatrixStack msLocal, Contraption contraption) {
if (Backend.canUseVBOs()) {
ContraptionRenderDispatcher.renderDynamic(entity.world, contraption, ms, msLocal, buffers);
} else {
ContraptionRenderDispatcher.renderDynamic(entity.world, contraption, ms, msLocal, buffers);
ContraptionRenderDispatcher.renderStructure(entity.world, contraption, ms, msLocal, buffers);
}
}
public static void renderDynamic(World world, Contraption c, MatrixStack ms, MatrixStack msLocal,
IRenderTypeBuffer buffer) {
renderTileEntities(world, c, ms, msLocal, buffer);
if (buffer instanceof IRenderTypeBuffer.Impl)
((IRenderTypeBuffer.Impl) buffer).draw();
renderActors(world, c, ms, msLocal, buffer);
}
public static void renderStructure(World world, Contraption c, 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(c, layer));
if (contraptionBuffer.isEmpty())
continue;
Matrix4f model = msLocal.peek()
.getModel();
contraptionBuffer.light(model)
.renderInto(ms, buffer.getBuffer(layer));
}
}
private static SuperByteBuffer buildStructureBuffer(Contraption c, RenderType layer) {
BufferBuilder builder = buildStructure(c, layer);
return new SuperByteBuffer(builder);
}
public static BufferBuilder buildStructure(Contraption c, RenderType layer) {
if (renderWorld == null || renderWorld.getWorld() != Minecraft.getInstance().world)
renderWorld = new PlacementSimulationWorld(Minecraft.getInstance().world);
ForgeHooksClient.setRenderLayer(layer);
MatrixStack ms = new MatrixStack();
BlockRendererDispatcher dispatcher = Minecraft.getInstance()
.getBlockRendererDispatcher();
BlockModelRenderer blockRenderer = dispatcher.getBlockModelRenderer();
Random random = new Random();
BufferBuilder builder = new BufferBuilder(DefaultVertexFormats.BLOCK.getIntegerSize());
builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK);
renderWorld.setTileEntities(c.presentTileEntities.values());
for (Template.BlockInfo info : c.getBlocks()
.values())
renderWorld.setBlockState(info.pos, info.state);
for (Template.BlockInfo info : c.getBlocks()
.values()) {
BlockState state = info.state;
if (state.getRenderType() == BlockRenderType.ENTITYBLOCK_ANIMATED)
continue;
if (!RenderTypeLookup.canRenderInLayer(state, layer))
continue;
IBakedModel originalModel = dispatcher.getModelForState(state);
ms.push();
ms.translate(info.pos.getX(), info.pos.getY(), info.pos.getZ());
blockRenderer.renderModel(renderWorld, originalModel, state, info.pos, ms, builder, true, random, 42,
OverlayTexture.DEFAULT_UV, EmptyModelData.INSTANCE);
ms.pop();
}
builder.finishDrawing();
renderWorld.clear();
renderWorld = null;
return builder;
}
protected static void renderActors(World world, Contraption c, MatrixStack ms, MatrixStack msLocal,
IRenderTypeBuffer buffer) {
MatrixStack[] matrixStacks = new MatrixStack[] { ms, msLocal };
for (Pair<Template.BlockInfo, MovementContext> actor : c.getActors()) {
MovementContext context = actor.getRight();
if (context == null)
continue;
if (context.world == null)
context.world = world;
Template.BlockInfo blockInfo = actor.getLeft();
for (MatrixStack m : matrixStacks) {
m.push();
MatrixStacker.of(m)
.translate(blockInfo.pos);
}
MovementBehaviour movementBehaviour = AllMovementBehaviours.of(blockInfo.state);
if (movementBehaviour != null)
movementBehaviour.renderInContraption(context, ms, msLocal, buffer);
for (MatrixStack m : matrixStacks)
m.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;
}
}
} }

View file

@ -0,0 +1,46 @@
package com.simibubi.create.content.contraptions.components.structureMovement.render;
import java.util.List;
import java.util.Random;
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour;
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher;
import com.simibubi.create.foundation.render.*;
import com.simibubi.create.foundation.render.backend.Backend;
import com.simibubi.create.foundation.render.backend.FastRenderDispatcher;
import org.apache.commons.lang3.tuple.Pair;
import org.lwjgl.opengl.GL11;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.AllMovementBehaviours;
import com.simibubi.create.CreateClient;
import com.simibubi.create.foundation.utility.MatrixStacker;
import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld;
import net.minecraft.block.BlockRenderType;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BlockModelRenderer;
import net.minecraft.client.renderer.BlockRendererDispatcher;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.Matrix4f;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.RenderTypeLookup;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.LightType;
import net.minecraft.world.World;
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
import net.minecraftforge.client.ForgeHooksClient;
import net.minecraftforge.client.model.data.EmptyModelData;
public class ContraptionRenderer {
}

View file

@ -2,6 +2,7 @@ package com.simibubi.create.foundation.render;
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 it.unimi.dsi.fastutil.longs.Long2DoubleMap; import it.unimi.dsi.fastutil.longs.Long2DoubleMap;
import it.unimi.dsi.fastutil.longs.Long2DoubleOpenHashMap; import it.unimi.dsi.fastutil.longs.Long2DoubleOpenHashMap;
@ -32,6 +33,7 @@ public class SuperByteBuffer extends TemplateBuffer {
// Vertex Lighting // Vertex Lighting
private boolean shouldLight; private boolean shouldLight;
private int packedLightCoords; private int packedLightCoords;
private int otherBlockLight;
private Matrix4f lightTransform; private Matrix4f lightTransform;
// Vertex Coloring // Vertex Coloring
@ -136,7 +138,11 @@ public class SuperByteBuffer extends TemplateBuffer {
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);
lightPos.transform(lightTransform); lightPos.transform(lightTransform);
light = getLight(Minecraft.getInstance().world, lightPos); light = getLight(Minecraft.getInstance().world, lightPos);
if (otherBlockLight >= 0) {
light = ContraptionRenderDispatcher.getMaxBlockLight(light, otherBlockLight);
}
} }
builder.light(light); builder.light(light);
} else } else
@ -150,6 +156,7 @@ public class SuperByteBuffer extends TemplateBuffer {
spriteShiftFunc = null; spriteShiftFunc = null;
shouldColor = false; shouldColor = false;
shouldLight = false; shouldLight = false;
otherBlockLight = -1;
} }
public SuperByteBuffer translate(double x, double y, double z) { public SuperByteBuffer translate(double x, double y, double z) {
@ -214,6 +221,13 @@ public class SuperByteBuffer extends TemplateBuffer {
return this; return this;
} }
public SuperByteBuffer light(Matrix4f lightTransform, int otherBlockLight) {
shouldLight = true;
this.lightTransform = lightTransform;
this.otherBlockLight = otherBlockLight;
return this;
}
public SuperByteBuffer color(int color) { public SuperByteBuffer color(int color) {
shouldColor = true; shouldColor = true;
r = ((color >> 16) & 0xFF); r = ((color >> 16) & 0xFF);

View file

@ -2,6 +2,7 @@ package com.simibubi.create.foundation.render;
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;
@ -12,9 +13,7 @@ import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.LightType;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.client.model.pipeline.LightUtil;
import java.util.Iterator; import java.util.Iterator;
@ -51,17 +50,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 = WorldRenderer.getLightmapCoordinates(world, lightPos); int worldLight = ContraptionRenderDispatcher.getLightOnContraption(world, renderWorld, pos, lightPos);
if (renderWorld != null) {
int contraptionBlockLight = renderWorld.getLightLevel(LightType.BLOCK, pos);
int worldBlockLight = LightTexture.getBlockLightCoordinates(worldLight);
if (contraptionBlockLight > worldBlockLight) {
worldLight = (worldLight & 0xFFFF0000) | (contraptionBlockLight << 4);
}
}
renderer.render(tileEntity, pt, ms, buffer, worldLight, renderer.render(tileEntity, pt, ms, buffer, worldLight,
OverlayTexture.DEFAULT_UV); OverlayTexture.DEFAULT_UV);