insane amounts of refactoring

surprisingly it all still works the same, but better
maybe still some more cleanup to do
This commit is contained in:
JozsefA 2021-01-22 11:28:39 -08:00
parent 11f9c7459c
commit f6518d5c5d
28 changed files with 334 additions and 245 deletions

View file

@ -7,6 +7,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
@ -219,11 +220,11 @@ public class AllBlockPartials {
}
public <T extends KineticTileEntity> InstanceBuffer<RotatingData> renderOnRotating(InstanceContext<T> ctx, BlockState referenceState) {
return ctx.getKinetics().renderPartialRotating(this, referenceState);
return ctx.getRotating().getModel(this, referenceState);
}
public <T extends BeltTileEntity> InstanceBuffer<BeltData> renderOnBelt(InstanceContext<T> ctx, BlockState referenceState) {
return ctx.getKinetics().renderPartialBelt(this, referenceState);
return ctx.getBelts().getModel(this, referenceState);
}
public <T extends KineticTileEntity> InstanceBuffer<RotatingData> renderOnDirectionalSouthRotating(InstanceContext<T> ctx, BlockState referenceState) {
@ -232,14 +233,16 @@ public class AllBlockPartials {
}
public <T extends KineticTileEntity> InstanceBuffer<RotatingData> renderOnDirectionalSouthRotating(InstanceContext<T> ctx, BlockState referenceState, Direction facing) {
MatrixStack ms = new MatrixStack();
// TODO 1.15 find a way to cache this model matrix computation
MatrixStacker.of(ms)
.centre()
.rotateY(AngleHelper.horizontalAngle(facing))
.rotateX(AngleHelper.verticalAngle(facing))
.unCentre();
return ctx.getKinetics().renderDirectionalPartialInstanced(this, referenceState, facing, ms);
Supplier<MatrixStack> ms = () -> {
MatrixStack stack = new MatrixStack();
MatrixStacker.of(stack)
.centre()
.rotateY(AngleHelper.horizontalAngle(facing))
.rotateX(AngleHelper.verticalAngle(facing))
.unCentre();
return stack;
};
return ctx.getRotating().getModel(this, referenceState, facing, ms);
}
}

View file

@ -16,8 +16,7 @@ import com.simibubi.create.foundation.block.render.CustomBlockModels;
import com.simibubi.create.foundation.block.render.SpriteShifter;
import com.simibubi.create.foundation.item.CustomItemModels;
import com.simibubi.create.foundation.item.CustomRenderedItems;
import com.simibubi.create.foundation.render.ContraptionRenderDispatcher;
import com.simibubi.create.foundation.render.RenderedContraption;
import com.simibubi.create.foundation.render.contraption.ContraptionRenderDispatcher;
import com.simibubi.create.foundation.render.FastKineticRenderer;
import com.simibubi.create.foundation.render.SuperByteBufferCache;
import com.simibubi.create.foundation.utility.outliner.Outliner;

View file

@ -5,7 +5,7 @@ import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.KineticDebugger;
import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock;
import com.simibubi.create.foundation.render.SuperByteBuffer;
import com.simibubi.create.foundation.render.SuperByteBufferCache.Compartment;
import com.simibubi.create.foundation.render.Compartment;
import com.simibubi.create.foundation.render.instancing.IInstancedTileEntityRenderer;
import com.simibubi.create.foundation.render.instancing.InstanceBuffer;
import com.simibubi.create.foundation.render.instancing.InstanceContext;
@ -61,12 +61,12 @@ public class KineticTileEntityRenderer extends SafeTileEntityRenderer<KineticTil
}
public static <T extends KineticTileEntity> void renderRotatingKineticBlock(InstanceContext<T> ctx, BlockState renderedState) {
InstanceBuffer<RotatingData> instancedRenderer = ctx.getKinetics().renderBlockInstanced(KINETIC_TILE, renderedState);
InstanceBuffer<RotatingData> instancedRenderer = ctx.getRotating().getModel(KINETIC_TILE, renderedState);
renderRotatingBuffer(ctx, instancedRenderer);
}
public static <T extends KineticTileEntity> void markForRebuild(InstanceContext<T> ctx, BlockState renderedState) {
ctx.getKinetics().renderBlockInstanced(KINETIC_TILE, renderedState).clearInstanceData();
ctx.getRotating().getModel(KINETIC_TILE, renderedState).clearInstanceData();
}
public static <T extends KineticTileEntity> void renderRotatingBuffer(InstanceContext<T> ctx, InstanceBuffer<RotatingData> instancer) {
@ -151,7 +151,7 @@ public class KineticTileEntityRenderer extends SafeTileEntityRenderer<KineticTil
}
protected InstanceBuffer<RotatingData> getRotatedModel(InstanceContext<? extends KineticTileEntity> ctx) {
return ctx.getKinetics().renderBlockInstanced(KINETIC_TILE, getRenderedBlockState(ctx.te));
return ctx.getRotating().getModel(KINETIC_TILE, getRenderedBlockState(ctx.te));
}
}

View file

@ -34,6 +34,11 @@ public class DrillMovementBehaviour extends BlockBreakingMovementBehaviour {
DrillRenderer.renderInContraption(context, ms, msLocal, buffer);
}
@Override
public void addInstance(MovementContext context) {
super.addInstance(context);
}
@Override
protected DamageSource getDamageSource() {
return DrillBlock.damageSourceDrill;

View file

@ -37,6 +37,10 @@ public class DrillRenderer extends KineticTileEntityRenderer {
return AllBlockPartials.DRILL_HEAD.renderOnDirectionalSouth(state);
}
public static void addInstanceForContraption(MovementContext context) {
//AllBlockPartials.DRILL_HEAD.
}
public static void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal,
IRenderTypeBuffer buffer) {
MatrixStack[] matrixStacks = new MatrixStack[] { ms, msLocal };

View file

@ -141,7 +141,7 @@ public class SawRenderer extends SafeTileEntityRenderer<SawTileEntity> implement
BlockState state = te.getBlockState();
if (state.get(FACING).getAxis().isHorizontal())
return AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(ctx, state.rotate(te.getWorld(), te.getPos(), Rotation.CLOCKWISE_180));
return ctx.getKinetics().renderBlockInstanced(KineticTileEntityRenderer.KINETIC_TILE,
return ctx.getRotating().getModel(KineticTileEntityRenderer.KINETIC_TILE,
getRenderedBlockState(te));
}

View file

@ -2,9 +2,7 @@ package com.simibubi.create.content.contraptions.components.structureMovement;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.render.ContraptionRenderDispatcher;
import com.simibubi.create.foundation.render.RenderedContraption;
import net.java.games.input.Controller;
import com.simibubi.create.foundation.render.contraption.ContraptionRenderDispatcher;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.culling.ClippingHelperImpl;

View file

@ -12,7 +12,7 @@ import com.simibubi.create.CreateClient;
import com.simibubi.create.foundation.utility.MatrixStacker;
import com.simibubi.create.foundation.render.SuperByteBuffer;
import com.simibubi.create.foundation.render.SuperByteBufferCache;
import com.simibubi.create.foundation.render.SuperByteBufferCache.Compartment;
import com.simibubi.create.foundation.render.Compartment;
import com.simibubi.create.foundation.render.TileEntityRenderHelper;
import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld;

View file

@ -55,6 +55,9 @@ public abstract class MovementBehaviour {
public void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal,
IRenderTypeBuffer buffer) {}
@OnlyIn(Dist.CLIENT)
public void addInstance(MovementContext context) {}
public void onSpeedChanged(MovementContext context, Vec3d oldMotion, Vec3d motion) {
}

View file

@ -34,7 +34,7 @@ public class SpeedControllerRenderer extends SmartTileEntityRenderer<SpeedContro
}
private InstanceBuffer<RotatingData> getRotatedModel(InstanceContext<SpeedControllerTileEntity> ctx) {
return ctx.getKinetics().renderBlockInstanced(KineticTileEntityRenderer.KINETIC_TILE,
return ctx.getRotating().getModel(KineticTileEntityRenderer.KINETIC_TILE,
KineticTileEntityRenderer.shaft(KineticTileEntityRenderer.getRotationAxisOf(ctx.te)));
}

View file

@ -30,6 +30,7 @@ import net.minecraft.util.math.Vec3i;
import net.minecraft.world.LightType;
import java.util.Random;
import java.util.function.Supplier;
public class BeltRenderer extends SafeTileEntityRenderer<BeltTileEntity> implements IInstancedTileEntityRenderer<BeltTileEntity> {
@ -82,8 +83,6 @@ public class BeltRenderer extends SafeTileEntityRenderer<BeltTileEntity> impleme
end = b;
}
FastKineticRenderer fastKineticRenderer = ctx.getKinetics();
for (boolean bottom : Iterate.trueAndFalse) {
AllBlockPartials beltPartial = diagonal
@ -128,23 +127,7 @@ public class BeltRenderer extends SafeTileEntityRenderer<BeltTileEntity> impleme
}
if (te.hasPulley()) {
// TODO 1.15 find a way to cache this model matrix computation
MatrixStack modelTransform = new MatrixStack();
Direction dir = blockState.get(BeltBlock.HORIZONTAL_FACING)
.rotateY();
if (sideways)
dir = Direction.UP;
MatrixStacker msr = MatrixStacker.of(modelTransform);
msr.centre();
if (dir.getAxis() == Axis.X)
msr.rotateY(90);
if (dir.getAxis() == Axis.Y)
msr.rotateX(90);
msr.rotateX(90);
msr.unCentre();
InstanceBuffer<RotatingData> rotatingBuffer = fastKineticRenderer
.renderDirectionalPartialInstanced(AllBlockPartials.BELT_PULLEY, blockState, dir, modelTransform);
InstanceBuffer<RotatingData> rotatingBuffer = getPulleyModel(ctx, blockState, sideways);
KineticTileEntityRenderer.renderRotatingBuffer(ctx, rotatingBuffer);
}
}
@ -152,7 +135,6 @@ public class BeltRenderer extends SafeTileEntityRenderer<BeltTileEntity> impleme
@Override
public void markForRebuild(InstanceContext<BeltTileEntity> ctx) {
BeltTileEntity te = ctx.te;
FastKineticRenderer fastKineticRenderer = ctx.getKinetics();
BlockState blockState = te.getBlockState();
if (!AllBlocks.BELT.has(blockState))
@ -197,25 +179,34 @@ public class BeltRenderer extends SafeTileEntityRenderer<BeltTileEntity> impleme
break;
}
// TODO 1.15 find a way to cache this model matrix computation
MatrixStack modelTransform = new MatrixStack();
InstanceBuffer<RotatingData> rotatingBuffer = getPulleyModel(ctx, blockState, sideways);
rotatingBuffer.clearInstanceData();
}
private InstanceBuffer<RotatingData> getPulleyModel(InstanceContext<BeltTileEntity> ctx, BlockState blockState, boolean sideways) {
Direction dir = blockState.get(BeltBlock.HORIZONTAL_FACING)
.rotateY();
if (sideways)
dir = Direction.UP;
MatrixStacker msr = MatrixStacker.of(modelTransform);
msr.centre();
if (dir.getAxis() == Axis.X)
msr.rotateY(90);
if (dir.getAxis() == Axis.Y)
Axis axis = dir.getAxis();
Supplier<MatrixStack> ms = () -> {
MatrixStack modelTransform = new MatrixStack();
MatrixStacker msr = MatrixStacker.of(modelTransform);
msr.centre();
if (axis == Axis.X)
msr.rotateY(90);
if (axis == Axis.Y)
msr.rotateX(90);
msr.rotateX(90);
msr.rotateX(90);
msr.unCentre();
msr.unCentre();
InstanceBuffer<RotatingData> rotatingBuffer = fastKineticRenderer
.renderDirectionalPartialInstanced(AllBlockPartials.BELT_PULLEY, blockState, dir, modelTransform);
return modelTransform;
};
rotatingBuffer.clearInstanceData();
return ctx.getRotating().getModel(AllBlockPartials.BELT_PULLEY, blockState, dir, ms);
}
protected void renderItems(BeltTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer,

View file

@ -0,0 +1,12 @@
package com.simibubi.create.foundation.render;
import com.simibubi.create.AllBlockPartials;
import net.minecraft.block.BlockState;
import net.minecraft.util.Direction;
import org.apache.commons.lang3.tuple.Pair;
public class Compartment<T> {
public static final Compartment<BlockState> GENERIC_TILE = new Compartment<>();
public static final Compartment<AllBlockPartials> PARTIAL = new Compartment<>();
public static final Compartment<Pair<Direction, AllBlockPartials>> DIRECTIONAL_PARTIAL = new Compartment<>();
}

View file

@ -1,56 +1,42 @@
package com.simibubi.create.foundation.render;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.AllBlockPartials;
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.foundation.render.contraption.RenderedContraption;
import com.simibubi.create.foundation.render.instancing.*;
import com.simibubi.create.foundation.render.shader.Shader;
import com.simibubi.create.foundation.render.shader.ShaderCallback;
import com.simibubi.create.foundation.render.shader.ShaderHelper;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.*;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.texture.Texture;
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
import net.minecraft.inventory.container.PlayerContainer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.world.World;
import org.apache.commons.lang3.tuple.Pair;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL13;
import org.lwjgl.opengl.GL40;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.function.Consumer;
import java.util.function.Supplier;
import static com.simibubi.create.foundation.render.SuperByteBufferCache.PARTIAL;
public class FastKineticRenderer {
Map<SuperByteBufferCache.Compartment<?>, Cache<Object, InstanceBuffer<RotatingData>>> rotating;
Map<SuperByteBufferCache.Compartment<?>, Cache<Object, InstanceBuffer<BeltData>>> belts;
protected Map<MaterialType<?>, RenderMaterial<?>> materials = new HashMap<>();
public boolean dirty = false;
public FastKineticRenderer() {
rotating = new HashMap<>();
belts = new HashMap<>();
registerCompartment(SuperByteBufferCache.PARTIAL);
registerCompartment(SuperByteBufferCache.DIRECTIONAL_PARTIAL);
registerCompartment(KineticTileEntityRenderer.KINETIC_TILE);
registerMaterials();
}
public void buildTileEntityBuffers(World world) {
public void registerMaterials() {
materials.put(KineticRenderMaterials.BELTS, new RenderMaterial<>(Shader.BELT, BeltBuffer::new));
materials.put(KineticRenderMaterials.ROTATING, new RenderMaterial<>(Shader.ROTATING, RotatingBuffer::new));
}
@SuppressWarnings("unchecked")
public <M extends InstanceBuffer<?>> RenderMaterial<M> get(MaterialType<M> materialType) {
return (RenderMaterial<M>) materials.get(materialType);
}
@SuppressWarnings("unchecked")
public void buildTileEntityBuffers(World world) {
List<TileEntity> tileEntities = world.loadedTileEntityList;
if (!tileEntities.isEmpty()) {
@ -66,11 +52,11 @@ public class FastKineticRenderer {
}
}
<T extends TileEntity> void addInstancedData(T te, IInstancedTileEntityRenderer<T> renderer) {
public <T extends TileEntity> void addInstancedData(T te, IInstancedTileEntityRenderer<T> renderer) {
renderer.addInstanceData(new InstanceContext.World<>(te));
}
<T extends TileEntity> void addInstancedData(RenderedContraption c, T te, IInstancedTileEntityRenderer<T> renderer) {
public <T extends TileEntity> void addInstancedData(RenderedContraption c, T te, IInstancedTileEntityRenderer<T> renderer) {
renderer.addInstanceData(new InstanceContext.Contraption<>(te, c));
}
@ -80,141 +66,45 @@ public class FastKineticRenderer {
* guaranteed to be no race conditions with the render thread, i.e. when constructing a FastContraptionRenderer.
*/
public void markAllDirty() {
runOnAll(InstanceBuffer::markDirty);
for (RenderMaterial<?> material : materials.values()) {
material.runOnAll(InstanceBuffer::markDirty);
}
}
public void invalidate() {
runOnAll(InstanceBuffer::delete);
belts.values().forEach(Cache::invalidateAll);
rotating.values().forEach(Cache::invalidateAll);
for (RenderMaterial<?> material : materials.values()) {
material.runOnAll(InstanceBuffer::delete);
}
dirty = true;
}
private void runOnAll(Consumer<InstanceBuffer<?>> f) {
for (Cache<Object, InstanceBuffer<RotatingData>> cache : rotating.values()) {
for (InstanceBuffer<RotatingData> renderer : cache.asMap().values()) {
f.accept(renderer);
}
}
for (Cache<Object, InstanceBuffer<BeltData>> cache : belts.values()) {
for (InstanceBuffer<BeltData> renderer : cache.asMap().values()) {
f.accept(renderer);
}
}
public void render(RenderType layer, Matrix4f projection, Matrix4f view) {
render(layer, projection, view, null);
}
void renderBelts() {
for (Cache<Object, InstanceBuffer<BeltData>> cache : belts.values()) {
for (InstanceBuffer<BeltData> type : cache.asMap().values()) {
if (!type.isEmpty()) {
type.render();
}
}
}
}
void renderRotating() {
for (Cache<Object, InstanceBuffer<RotatingData>> cache : rotating.values()) {
for (InstanceBuffer<RotatingData> rotatingDataInstanceBuffer : cache.asMap().values()) {
if (!rotatingDataInstanceBuffer.isEmpty()) {
rotatingDataInstanceBuffer.render();
}
}
}
}
public void renderInstancesAsWorld(RenderType layer, Matrix4f projection, Matrix4f view) {
protected void prepareFrame() {
if (dirty) {
buildTileEntityBuffers(Minecraft.getInstance().world);
markAllDirty();
dirty = false;
}
}
public void render(RenderType layer, Matrix4f projection, Matrix4f view, ShaderCallback callback) {
prepareFrame();
layer.startDrawing();
ShaderCallback callback = ShaderHelper.getViewProjectionCallback(projection, view);
ShaderHelper.useShader(Shader.ROTATING, callback);
renderRotating();
ShaderHelper.useShader(Shader.BELT, callback);
renderBelts();
for (RenderMaterial<?> material : materials.values()) {
material.render(projection, view, callback);
}
ShaderHelper.releaseShader();
layer.endDrawing();
}
public void registerCompartment(SuperByteBufferCache.Compartment<?> instance) {
rotating.put(instance, CacheBuilder.newBuilder().build());
belts.put(instance, CacheBuilder.newBuilder().build());
}
public InstanceBuffer<RotatingData> renderPartialRotating(AllBlockPartials partial, BlockState referenceState) {
return getRotating(PARTIAL, partial, () -> rotatingInstancedRenderer(partial.get(), referenceState));
}
public InstanceBuffer<BeltData> renderPartialBelt(AllBlockPartials partial, BlockState referenceState) {
return getBelt(PARTIAL, partial, () -> beltInstancedRenderer(partial.get(), referenceState));
}
public InstanceBuffer<RotatingData> renderDirectionalPartialInstanced(AllBlockPartials partial, BlockState referenceState, Direction dir,
MatrixStack modelTransform) {
return getRotating(SuperByteBufferCache.DIRECTIONAL_PARTIAL, Pair.of(dir, partial),
() -> rotatingInstancedRenderer(partial.get(), referenceState, modelTransform));
}
public InstanceBuffer<RotatingData> renderBlockInstanced(SuperByteBufferCache.Compartment<BlockState> compartment, BlockState toRender) {
return getRotating(compartment, toRender, () -> rotatingInstancedRenderer(toRender));
}
public <T> InstanceBuffer<RotatingData> getRotating(SuperByteBufferCache.Compartment<T> compartment, T key, Supplier<InstanceBuffer<RotatingData>> supplier) {
Cache<Object, InstanceBuffer<RotatingData>> compartmentCache = this.rotating.get(compartment);
try {
return compartmentCache.get(key, supplier::get);
} catch (ExecutionException e) {
e.printStackTrace();
return null;
}
}
public <T> InstanceBuffer<BeltData> getBelt(SuperByteBufferCache.Compartment<T> compartment, T key, Supplier<InstanceBuffer<BeltData>> supplier) {
Cache<Object, InstanceBuffer<BeltData>> compartmentCache = this.belts.get(compartment);
try {
return compartmentCache.get(key, supplier::get);
} catch (ExecutionException e) {
e.printStackTrace();
return null;
}
}
private InstanceBuffer<RotatingData> rotatingInstancedRenderer(BlockState renderedState) {
BlockRendererDispatcher dispatcher = Minecraft.getInstance().getBlockRendererDispatcher();
return rotatingInstancedRenderer(dispatcher.getModelForState(renderedState), renderedState);
}
private InstanceBuffer<RotatingData> rotatingInstancedRenderer(IBakedModel model, BlockState renderedState) {
return rotatingInstancedRenderer(model, renderedState, new MatrixStack());
}
private InstanceBuffer<BeltData> beltInstancedRenderer(IBakedModel model, BlockState renderedState) {
return beltInstancedRenderer(model, renderedState, new MatrixStack());
}
private InstanceBuffer<RotatingData> rotatingInstancedRenderer(IBakedModel model, BlockState referenceState, MatrixStack ms) {
BufferBuilder builder = SuperByteBufferCache.getBufferBuilder(model, referenceState, ms);
return new RotatingBuffer(builder);
}
private InstanceBuffer<BeltData> beltInstancedRenderer(IBakedModel model, BlockState referenceState, MatrixStack ms) {
BufferBuilder builder = SuperByteBufferCache.getBufferBuilder(model, referenceState, ms);
return new BeltBuffer(builder);
}
public static RenderType getKineticRenderLayer() {
return RenderType.getCutoutMipped();
}

View file

@ -3,6 +3,7 @@ package com.simibubi.create.foundation.render;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.CreateClient;
import com.simibubi.create.foundation.render.contraption.ContraptionRenderDispatcher;
import com.simibubi.create.foundation.render.instancing.IInstanceRendered;
import com.simibubi.create.foundation.render.instancing.IInstancedTileEntityRenderer;
import com.simibubi.create.foundation.render.instancing.InstanceContext;
@ -24,7 +25,6 @@ import net.minecraft.world.ILightReader;
import net.minecraft.world.LightType;
import net.minecraft.world.chunk.Chunk;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL30;
import java.util.Map;
@ -46,7 +46,7 @@ public class FastRenderDispatcher {
RenderSystem.enableDepthTest();
RenderSystem.enableCull();
GL11.glCullFace(GL11.GL_BACK);
CreateClient.kineticRenderer.renderInstancesAsWorld(type, projection, view);
CreateClient.kineticRenderer.render(type, projection, view);
RenderSystem.disableCull();
//RenderSystem.disableDepthTest();
}

View file

@ -27,20 +27,13 @@ import net.minecraft.util.math.BlockPos;
public class SuperByteBufferCache {
public static class Compartment<T> {
}
public static final Compartment<BlockState> GENERIC_TILE = new Compartment<>();
public static final Compartment<AllBlockPartials> PARTIAL = new Compartment<>();
public static final Compartment<Pair<Direction, AllBlockPartials>> DIRECTIONAL_PARTIAL = new Compartment<>();
Map<Compartment<?>, Cache<Object, SuperByteBuffer>> cache;
public SuperByteBufferCache() {
cache = new HashMap<>();
registerCompartment(GENERIC_TILE);
registerCompartment(PARTIAL);
registerCompartment(DIRECTIONAL_PARTIAL);
registerCompartment(Compartment.GENERIC_TILE);
registerCompartment(Compartment.PARTIAL);
registerCompartment(Compartment.DIRECTIONAL_PARTIAL);
}
public SuperByteBuffer renderBlock(BlockState toRender) {
@ -48,23 +41,23 @@ public class SuperByteBufferCache {
}
public SuperByteBuffer renderPartial(AllBlockPartials partial, BlockState referenceState) {
return get(PARTIAL, partial, () -> standardModelRender(partial.get(), referenceState));
return get(Compartment.PARTIAL, partial, () -> standardModelRender(partial.get(), referenceState));
}
public SuperByteBuffer renderPartial(AllBlockPartials partial, BlockState referenceState,
MatrixStack modelTransform) {
return get(PARTIAL, partial, () -> standardModelRender(partial.get(), referenceState, modelTransform));
return get(Compartment.PARTIAL, partial, () -> standardModelRender(partial.get(), referenceState, modelTransform));
}
public SuperByteBuffer renderDirectionalPartial(AllBlockPartials partial, BlockState referenceState,
Direction dir) {
return get(DIRECTIONAL_PARTIAL, Pair.of(dir, partial),
() -> standardModelRender(partial.get(), referenceState));
return get(Compartment.DIRECTIONAL_PARTIAL, Pair.of(dir, partial),
() -> standardModelRender(partial.get(), referenceState));
}
public SuperByteBuffer renderDirectionalPartial(AllBlockPartials partial, BlockState referenceState, Direction dir,
MatrixStack modelTransform) {
return get(DIRECTIONAL_PARTIAL, Pair.of(dir, partial),
() -> standardModelRender(partial.get(), referenceState, modelTransform));
return get(Compartment.DIRECTIONAL_PARTIAL, Pair.of(dir, partial),
() -> standardModelRender(partial.get(), referenceState, modelTransform));
}
public SuperByteBuffer renderBlockIn(Compartment<BlockState> compartment, BlockState toRender) {
@ -72,7 +65,7 @@ public class SuperByteBufferCache {
}
SuperByteBuffer getGeneric(BlockState key, Supplier<SuperByteBuffer> supplier) {
return get(GENERIC_TILE, key, supplier);
return get(Compartment.GENERIC_TILE, key, supplier);
}
public <T> SuperByteBuffer get(Compartment<T> compartment, T key, Supplier<SuperByteBuffer> supplier) {

View file

@ -1,6 +1,7 @@
package com.simibubi.create.foundation.render;
package com.simibubi.create.foundation.render.contraption;
import com.mojang.blaze3d.platform.GlStateManager;
import com.simibubi.create.foundation.render.GPUBuffer;
import com.simibubi.create.foundation.render.instancing.InstanceBuffer;
import com.simibubi.create.foundation.render.instancing.VertexFormat;
import net.minecraft.client.renderer.BufferBuilder;

View file

@ -0,0 +1,25 @@
package com.simibubi.create.foundation.render.contraption;
import com.simibubi.create.foundation.render.FastKineticRenderer;
import com.simibubi.create.foundation.render.instancing.BeltBuffer;
import com.simibubi.create.foundation.render.instancing.KineticRenderMaterials;
import com.simibubi.create.foundation.render.instancing.RenderMaterial;
import com.simibubi.create.foundation.render.instancing.RotatingBuffer;
import com.simibubi.create.foundation.render.shader.Shader;
import com.simibubi.create.foundation.render.shader.ShaderCallback;
import com.simibubi.create.foundation.render.shader.ShaderHelper;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.Matrix4f;
import net.minecraft.client.renderer.RenderType;
public class ContraptionKineticRenderer extends FastKineticRenderer {
@Override
public void registerMaterials() {
materials.put(KineticRenderMaterials.BELTS, new RenderMaterial<>(Shader.CONTRAPTION_BELT, BeltBuffer::new));
materials.put(KineticRenderMaterials.ROTATING, new RenderMaterial<>(Shader.CONTRAPTION_ROTATING, RotatingBuffer::new));
}
@Override
protected void prepareFrame() {}
}

View file

@ -1,17 +1,13 @@
package com.simibubi.create.foundation.render;
package com.simibubi.create.foundation.render.contraption;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
import com.simibubi.create.foundation.render.light.LightVolume;
import com.simibubi.create.foundation.render.FastKineticRenderer;
import com.simibubi.create.foundation.render.shader.Shader;
import com.simibubi.create.foundation.render.shader.ShaderCallback;
import com.simibubi.create.foundation.render.shader.ShaderHelper;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.Matrix4f;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.SectionPos;
import net.minecraft.world.ILightReader;
import net.minecraft.world.LightType;
@ -64,17 +60,8 @@ public class ContraptionRenderDispatcher {
}
if (renderType == FastKineticRenderer.getKineticRenderLayer()) {
int rotatingShader = ShaderHelper.useShader(Shader.CONTRAPTION_ROTATING, callback);
for (RenderedContraption renderer : renderers.values()) {
renderer.setup(rotatingShader);
renderer.kinetics.renderRotating();
renderer.teardown();
}
int beltShader = ShaderHelper.useShader(Shader.CONTRAPTION_BELT, callback);
for (RenderedContraption renderer : renderers.values()) {
renderer.setup(beltShader);
renderer.kinetics.renderBelts();
renderer.kinetics.render(renderType, projectionMat, viewMat, renderer::setup);
renderer.teardown();
}
}

View file

@ -1,12 +1,15 @@
package com.simibubi.create.foundation.render;
package com.simibubi.create.foundation.render.contraption;
import com.mojang.blaze3d.platform.GlStateManager;
import com.simibubi.create.AllMovementBehaviours;
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionRenderer;
import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour;
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
import com.simibubi.create.foundation.render.FastKineticRenderer;
import com.simibubi.create.foundation.render.instancing.IInstanceRendered;
import com.simibubi.create.foundation.render.instancing.IInstancedTileEntityRenderer;
import com.simibubi.create.foundation.render.light.ContraptionLighter;
import com.simibubi.create.foundation.render.light.LightVolume;
import com.simibubi.create.foundation.render.shader.ShaderHelper;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.Matrix4f;
@ -14,15 +17,11 @@ import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.SectionPos;
import net.minecraft.world.ILightReader;
import net.minecraft.world.LightType;
import net.minecraft.world.World;
import org.lwjgl.opengl.GL20;
import net.minecraft.world.gen.feature.template.Template;
import org.apache.commons.lang3.tuple.MutablePair;
import java.nio.FloatBuffer;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
@ -31,7 +30,7 @@ public class RenderedContraption {
private final ContraptionLighter<?> lighter;
public final FastKineticRenderer kinetics;
public final ContraptionKineticRenderer kinetics;
private Contraption contraption;
@ -40,7 +39,7 @@ public class RenderedContraption {
public RenderedContraption(World world, Contraption contraption) {
this.contraption = contraption;
this.lighter = contraption.makeLighter();
this.kinetics = new FastKineticRenderer();
this.kinetics = new ContraptionKineticRenderer();
buildLayers(contraption);
buildInstancedTiles(contraption);
@ -98,6 +97,21 @@ public class RenderedContraption {
kinetics.markAllDirty();
}
private void buildActors(Contraption c) {
List<MutablePair<Template.BlockInfo, MovementContext>> actors = c.getActors();
for (MutablePair<Template.BlockInfo, MovementContext> actor : actors) {
Template.BlockInfo blockInfo = actor.left;
MovementContext context = actor.right;
MovementBehaviour movementBehaviour = AllMovementBehaviours.of(blockInfo.state);
if (movementBehaviour != null) {
movementBehaviour.addInstance(context);
}
}
}
void setRenderSettings(Matrix4f model) {
this.model = model;
}

View file

@ -27,4 +27,11 @@ public abstract class DynamicInstanceBuffer<S extends InstanceData, D extends In
protected int getTotalShaderAttributeCount() {
return super.getTotalShaderAttributeCount() + getDynamicFormat().getShaderAttributeCount();
}
@Override
protected void preDrawTask() {
super.preDrawTask();
}
}

View file

@ -1,7 +1,7 @@
package com.simibubi.create.foundation.render.instancing;
import com.simibubi.create.CreateClient;
import com.simibubi.create.foundation.render.RenderedContraption;
import com.simibubi.create.foundation.render.contraption.RenderedContraption;
import com.simibubi.create.foundation.render.FastKineticRenderer;
import net.minecraft.tileentity.TileEntity;
@ -13,6 +13,14 @@ public abstract class InstanceContext<T extends TileEntity> {
this.te = te;
}
public RenderMaterial<InstanceBuffer<RotatingData>> getRotating() {
return getKinetics().get(KineticRenderMaterials.ROTATING);
}
public RenderMaterial<InstanceBuffer<BeltData>> getBelts() {
return getKinetics().get(KineticRenderMaterials.BELTS);
}
public abstract FastKineticRenderer getKinetics();
public abstract boolean checkWorldLight();

View file

@ -0,0 +1,6 @@
package com.simibubi.create.foundation.render.instancing;
public class KineticRenderMaterials {
public static final MaterialType<InstanceBuffer<RotatingData>> ROTATING = new MaterialType<>();
public static final MaterialType<InstanceBuffer<BeltData>> BELTS = new MaterialType<>();
}

View file

@ -0,0 +1,3 @@
package com.simibubi.create.foundation.render.instancing;
public class MaterialType<M> { }

View file

@ -0,0 +1,8 @@
package com.simibubi.create.foundation.render.instancing;
import net.minecraft.client.renderer.BufferBuilder;
@FunctionalInterface
public interface ModelFactory<B extends InstanceBuffer<?>> {
B convert(BufferBuilder buf);
}

View file

@ -0,0 +1,131 @@
package com.simibubi.create.foundation.render.instancing;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.AllBlockPartials;
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.foundation.render.Compartment;
import com.simibubi.create.foundation.render.SuperByteBufferCache;
import com.simibubi.create.foundation.render.shader.Shader;
import com.simibubi.create.foundation.render.shader.ShaderCallback;
import com.simibubi.create.foundation.render.shader.ShaderHelper;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BlockRendererDispatcher;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.Matrix4f;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.util.Direction;
import org.apache.commons.lang3.tuple.Pair;
import org.lwjgl.opengl.GL40;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.function.Consumer;
import java.util.function.Supplier;
import static com.simibubi.create.foundation.render.Compartment.PARTIAL;
public class RenderMaterial<MODEL extends InstanceBuffer<?>> {
protected final Map<Compartment<?>, Cache<Object, MODEL>> models;
protected final ModelFactory<MODEL> factory;
protected final Shader shader;
public RenderMaterial(Shader shader, ModelFactory<MODEL> factory) {
this.models = new HashMap<>();
this.factory = factory;
this.shader = shader;
registerCompartment(Compartment.PARTIAL);
registerCompartment(Compartment.DIRECTIONAL_PARTIAL);
registerCompartment(KineticTileEntityRenderer.KINETIC_TILE);
}
public void render(Matrix4f projection, Matrix4f view) {
render(projection, view, null);
}
public void render(Matrix4f projection, Matrix4f view, ShaderCallback setup) {
int handle = setupShader(projection, view);
if (setup != null) setup.call(handle);
makeRenderCalls();
teardown();
}
protected int setupShader(Matrix4f projection, Matrix4f view) {
ShaderCallback callback = ShaderHelper.getViewProjectionCallback(projection, view);
return ShaderHelper.useShader(shader, callback);
}
public void teardown() {}
public void delete() {
runOnAll(InstanceBuffer::delete);
models.values().forEach(Cache::invalidateAll);
}
protected void makeRenderCalls() {
for (Cache<Object, MODEL> cache : models.values()) {
for (MODEL model : cache.asMap().values()) {
if (!model.isEmpty()) {
model.render();
}
}
}
}
public void runOnAll(Consumer<MODEL> f) {
for (Cache<Object, MODEL> cache : models.values()) {
for (MODEL model : cache.asMap().values()) {
f.accept(model);
}
}
}
public void registerCompartment(Compartment<?> instance) {
models.put(instance, CacheBuilder.newBuilder().build());
}
public MODEL getModel(AllBlockPartials partial, BlockState referenceState) {
return get(PARTIAL, partial, () -> buildModel(partial.get(), referenceState));
}
public MODEL getModel(AllBlockPartials partial, BlockState referenceState, Direction dir, Supplier<MatrixStack> modelTransform) {
return get(Compartment.DIRECTIONAL_PARTIAL, Pair.of(dir, partial),
() -> buildModel(partial.get(), referenceState, modelTransform.get()));
}
public MODEL getModel(Compartment<BlockState> compartment, BlockState toRender) {
return get(compartment, toRender, () -> buildModel(toRender));
}
public <T> MODEL get(Compartment<T> compartment, T key, Supplier<MODEL> supplier) {
Cache<Object, MODEL> compartmentCache = models.get(compartment);
try {
return compartmentCache.get(key, supplier::get);
} catch (ExecutionException e) {
e.printStackTrace();
return null;
}
}
private MODEL buildModel(BlockState renderedState) {
BlockRendererDispatcher dispatcher = Minecraft.getInstance().getBlockRendererDispatcher();
return buildModel(dispatcher.getModelForState(renderedState), renderedState);
}
private MODEL buildModel(IBakedModel model, BlockState renderedState) {
return buildModel(model, renderedState, new MatrixStack());
}
private MODEL buildModel(IBakedModel model, BlockState referenceState, MatrixStack ms) {
BufferBuilder builder = SuperByteBufferCache.getBufferBuilder(model, referenceState, ms);
return factory.convert(builder);
}
}

View file

@ -159,6 +159,7 @@ public class LightVolume {
// just in case something goes wrong or we accidentally call this before this volume is properly disposed of.
if (glTexture == 0 || lightData == null) return;
GL13.glActiveTexture(GL40.GL_TEXTURE4);
GL12.glBindTexture(GL12.GL_TEXTURE_3D, glTexture);
GL11.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_MIN_FILTER, GL13.GL_LINEAR);
GL11.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_MAG_FILTER, GL13.GL_LINEAR);

View file

@ -1,7 +1,7 @@
package com.simibubi.create.foundation.render.light;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.render.ContraptionRenderDispatcher;
import com.simibubi.create.foundation.render.contraption.ContraptionRenderDispatcher;
import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer;
import com.simibubi.create.foundation.utility.Pair;
import com.simibubi.create.foundation.utility.outliner.AABBOutline;

View file

@ -31,7 +31,7 @@ public class ShaderHelper {
public static final Logger log = LogManager.getLogger("shader");
public static final FloatBuffer FLOAT_BUFFER = MemoryUtil.memAllocFloat(1);
public static final FloatBuffer FLOAT_BUFFER = MemoryUtil.memAllocFloat(1); // TODO: these leak 80 bytes of memory per program launch
public static final FloatBuffer VEC3_BUFFER = MemoryUtil.memAllocFloat(3);
public static final FloatBuffer MATRIX_BUFFER = MemoryUtil.memAllocFloat(16);