merge experimental rendering from 1.16 to 1.15 part II
This commit is contained in:
parent
7d43bb056a
commit
102e392ab4
23 changed files with 506 additions and 270 deletions
|
@ -13,7 +13,8 @@ import com.simibubi.create.content.contraptions.fluids.FluidTransportBehaviour.A
|
|||
import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.HeatLevel;
|
||||
import com.simibubi.create.foundation.utility.*;
|
||||
|
||||
import com.simibubi.create.foundation.utility.render.InstancedBuffer;
|
||||
import com.simibubi.create.foundation.utility.render.BeltBuffer;
|
||||
import com.simibubi.create.foundation.utility.render.RotatingBuffer;
|
||||
import com.simibubi.create.foundation.utility.render.SuperByteBuffer;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.renderer.model.IBakedModel;
|
||||
|
@ -216,15 +217,19 @@ public class AllBlockPartials {
|
|||
return CreateClient.bufferCache.renderDirectionalPartial(this, referenceState, facing, ms);
|
||||
}
|
||||
|
||||
public InstancedBuffer renderOnInstanced(BlockState referenceState) {
|
||||
return CreateClient.kineticRenderer.renderPartialInstanced(this, referenceState);
|
||||
public RotatingBuffer renderOnRotating(BlockState referenceState) {
|
||||
return CreateClient.kineticRenderer.renderPartialRotating(this, referenceState);
|
||||
}
|
||||
|
||||
public InstancedBuffer renderOnDirectionalSouthInstanced(BlockState referenceState) {
|
||||
Direction facing = referenceState.get(FACING);
|
||||
return renderOnDirectionalSouthInstanced(referenceState, facing);
|
||||
public BeltBuffer renderOnBelt(BlockState referenceState) {
|
||||
return CreateClient.kineticRenderer.renderPartialBelt(this, referenceState);
|
||||
}
|
||||
public InstancedBuffer renderOnDirectionalSouthInstanced(BlockState referenceState, Direction facing) {
|
||||
|
||||
public RotatingBuffer renderOnDirectionalSouthRotating(BlockState referenceState) {
|
||||
Direction facing = referenceState.get(FACING);
|
||||
return renderOnDirectionalSouthRotating(referenceState, facing);
|
||||
}
|
||||
public RotatingBuffer renderOnDirectionalSouthRotating(BlockState referenceState, Direction facing) {
|
||||
MatrixStack ms = new MatrixStack();
|
||||
// TODO 1.15 find a way to cache this model matrix computation
|
||||
MatrixStacker.of(ms)
|
||||
|
|
|
@ -9,6 +9,7 @@ import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer
|
|||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||
import com.simibubi.create.foundation.utility.ColorHelper;
|
||||
import com.simibubi.create.foundation.utility.render.InstancedBuffer;
|
||||
import com.simibubi.create.foundation.utility.render.RotatingBuffer;
|
||||
import com.simibubi.create.foundation.utility.render.SuperByteBuffer;
|
||||
import com.simibubi.create.foundation.utility.render.SuperByteBufferCache.Compartment;
|
||||
|
||||
|
@ -49,11 +50,11 @@ public class KineticTileEntityRenderer extends SafeTileEntityRenderer<KineticTil
|
|||
}
|
||||
|
||||
public static void renderRotatingKineticBlock(KineticTileEntity te, BlockState renderedState, int light) {
|
||||
InstancedBuffer instancedRenderer = CreateClient.kineticRenderer.renderBlockInstanced(KINETIC_TILE, renderedState);
|
||||
RotatingBuffer instancedRenderer = CreateClient.kineticRenderer.renderBlockInstanced(KINETIC_TILE, renderedState);
|
||||
renderRotatingBuffer(te, instancedRenderer, light);
|
||||
}
|
||||
|
||||
public static void renderRotatingBuffer(KineticTileEntity te, InstancedBuffer instancer, int light) {
|
||||
public static void renderRotatingBuffer(KineticTileEntity te, RotatingBuffer instancer, int light) {
|
||||
instancer.setupInstance(data -> {
|
||||
final BlockPos pos = te.getPos();
|
||||
Axis axis = ((IRotate) te.getBlockState()
|
||||
|
@ -129,7 +130,7 @@ public class KineticTileEntityRenderer extends SafeTileEntityRenderer<KineticTil
|
|||
return te.getBlockState();
|
||||
}
|
||||
|
||||
protected InstancedBuffer getRotatedModel(KineticTileEntity te) {
|
||||
protected RotatingBuffer getRotatedModel(KineticTileEntity te) {
|
||||
return CreateClient.kineticRenderer.renderBlockInstanced(KINETIC_TILE, getRenderedBlockState(te));
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import com.simibubi.create.foundation.utility.AngleHelper;
|
|||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||
import com.simibubi.create.foundation.utility.MatrixStacker;
|
||||
import com.simibubi.create.foundation.utility.render.InstancedBuffer;
|
||||
import com.simibubi.create.foundation.utility.render.RotatingBuffer;
|
||||
import com.simibubi.create.foundation.utility.render.SuperByteBuffer;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
||||
|
@ -27,8 +28,8 @@ public class DrillRenderer extends KineticTileEntityRenderer {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected InstancedBuffer getRotatedModel(KineticTileEntity te) {
|
||||
return AllBlockPartials.DRILL_HEAD.renderOnDirectionalSouthInstanced(te.getBlockState());
|
||||
protected RotatingBuffer getRotatedModel(KineticTileEntity te) {
|
||||
return AllBlockPartials.DRILL_HEAD.renderOnDirectionalSouthRotating(te.getBlockState());
|
||||
}
|
||||
|
||||
protected static SuperByteBuffer getRotatingModel(BlockState state) {
|
||||
|
|
|
@ -8,6 +8,7 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
|
|||
import com.simibubi.create.content.contraptions.components.clock.CuckooClockTileEntity.Animation;
|
||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||
import com.simibubi.create.foundation.utility.render.InstancedBuffer;
|
||||
import com.simibubi.create.foundation.utility.render.RotatingBuffer;
|
||||
import com.simibubi.create.foundation.utility.render.SuperByteBuffer;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
|
@ -91,14 +92,14 @@ public class CuckooClockRenderer extends KineticTileEntityRenderer {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected InstancedBuffer getRotatedModel(KineticTileEntity te) {
|
||||
protected RotatingBuffer getRotatedModel(KineticTileEntity te) {
|
||||
return transform(AllBlockPartials.SHAFT_HALF, te);
|
||||
}
|
||||
|
||||
private InstancedBuffer transform(AllBlockPartials partial, KineticTileEntity te) {
|
||||
return partial.renderOnDirectionalSouthInstanced(te.getBlockState(), te.getBlockState()
|
||||
.get(CuckooClockBlock.HORIZONTAL_FACING)
|
||||
.getOpposite());
|
||||
private RotatingBuffer transform(AllBlockPartials partial, KineticTileEntity te) {
|
||||
return partial.renderOnDirectionalSouthRotating(te.getBlockState(), te.getBlockState()
|
||||
.get(CuckooClockBlock.HORIZONTAL_FACING)
|
||||
.getOpposite());
|
||||
}
|
||||
|
||||
private SuperByteBuffer rotateHand(SuperByteBuffer buffer, float angle, Direction facing) {
|
||||
|
|
|
@ -9,6 +9,7 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
|||
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
|
||||
import com.simibubi.create.foundation.utility.render.InstancedBuffer;
|
||||
|
||||
import com.simibubi.create.foundation.utility.render.RotatingBuffer;
|
||||
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||
import net.minecraft.client.renderer.WorldRenderer;
|
||||
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
|
||||
|
@ -31,10 +32,10 @@ public class EncasedFanRenderer extends KineticTileEntityRenderer {
|
|||
int lightBehind = WorldRenderer.getLightmapCoordinates(te.getWorld(), te.getPos().offset(direction.getOpposite()));
|
||||
int lightInFront = WorldRenderer.getLightmapCoordinates(te.getWorld(), te.getPos().offset(direction));
|
||||
|
||||
InstancedBuffer shaftHalf =
|
||||
AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthInstanced(te.getBlockState(), direction.getOpposite());
|
||||
InstancedBuffer fanInner =
|
||||
AllBlockPartials.ENCASED_FAN_INNER.renderOnDirectionalSouthInstanced(te.getBlockState(), direction.getOpposite());
|
||||
RotatingBuffer shaftHalf =
|
||||
AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(te.getBlockState(), direction.getOpposite());
|
||||
RotatingBuffer fanInner =
|
||||
AllBlockPartials.ENCASED_FAN_INNER.renderOnDirectionalSouthRotating(te.getBlockState(), direction.getOpposite());
|
||||
|
||||
renderRotatingBuffer(te, shaftHalf, lightBehind);
|
||||
fanInner.setupInstance(data -> {
|
||||
|
|
|
@ -10,6 +10,7 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
|
|||
import com.simibubi.create.content.contraptions.components.flywheel.FlywheelBlock.ConnectionState;
|
||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||
import com.simibubi.create.foundation.utility.render.InstancedBuffer;
|
||||
import com.simibubi.create.foundation.utility.render.RotatingBuffer;
|
||||
import com.simibubi.create.foundation.utility.render.SuperByteBuffer;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
|
@ -75,10 +76,10 @@ public class FlywheelRenderer extends KineticTileEntityRenderer {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected InstancedBuffer getRotatedModel(KineticTileEntity te) {
|
||||
return AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthInstanced(te.getBlockState(), te.getBlockState()
|
||||
.get(HORIZONTAL_FACING)
|
||||
.getOpposite());
|
||||
protected RotatingBuffer getRotatedModel(KineticTileEntity te) {
|
||||
return AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(te.getBlockState(), te.getBlockState()
|
||||
.get(HORIZONTAL_FACING)
|
||||
.getOpposite());
|
||||
}
|
||||
|
||||
protected SuperByteBuffer transformConnector(SuperByteBuffer buffer, boolean upper, boolean rotating, float angle,
|
||||
|
|
|
@ -6,6 +6,7 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
|||
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
|
||||
import com.simibubi.create.foundation.utility.render.InstancedBuffer;
|
||||
|
||||
import com.simibubi.create.foundation.utility.render.RotatingBuffer;
|
||||
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
|
||||
|
||||
public class MillstoneRenderer extends KineticTileEntityRenderer {
|
||||
|
@ -15,8 +16,8 @@ public class MillstoneRenderer extends KineticTileEntityRenderer {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected InstancedBuffer getRotatedModel(KineticTileEntity te) {
|
||||
return CreateClient.kineticRenderer.renderPartialInstanced(AllBlockPartials.MILLSTONE_COG, te.getBlockState());
|
||||
protected RotatingBuffer getRotatedModel(KineticTileEntity te) {
|
||||
return CreateClient.kineticRenderer.renderPartialRotating(AllBlockPartials.MILLSTONE_COG, te.getBlockState());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
|||
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
|
||||
import com.simibubi.create.foundation.utility.render.InstancedBuffer;
|
||||
|
||||
import com.simibubi.create.foundation.utility.render.RotatingBuffer;
|
||||
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
|
||||
|
||||
public class CreativeMotorRenderer extends KineticTileEntityRenderer {
|
||||
|
@ -14,8 +15,8 @@ public class CreativeMotorRenderer extends KineticTileEntityRenderer {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected InstancedBuffer getRotatedModel(KineticTileEntity te) {
|
||||
return AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthInstanced(te.getBlockState());
|
||||
protected RotatingBuffer getRotatedModel(KineticTileEntity te) {
|
||||
return AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(te.getBlockState());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer
|
|||
import com.simibubi.create.foundation.utility.*;
|
||||
|
||||
import com.simibubi.create.foundation.utility.render.InstancedBuffer;
|
||||
import com.simibubi.create.foundation.utility.render.RotatingBuffer;
|
||||
import com.simibubi.create.foundation.utility.render.SuperByteBuffer;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
@ -123,10 +124,10 @@ public class SawRenderer extends SafeTileEntityRenderer<SawTileEntity> {
|
|||
}
|
||||
}
|
||||
|
||||
protected InstancedBuffer getRotatedModel(KineticTileEntity te) {
|
||||
protected RotatingBuffer getRotatedModel(KineticTileEntity te) {
|
||||
BlockState state = te.getBlockState();
|
||||
if (state.get(FACING).getAxis().isHorizontal())
|
||||
return AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthInstanced(state.rotate(te.getWorld(), te.getPos(), Rotation.CLOCKWISE_180));
|
||||
return AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(state.rotate(te.getWorld(), te.getPos(), Rotation.CLOCKWISE_180));
|
||||
return CreateClient.kineticRenderer.renderBlockInstanced(KineticTileEntityRenderer.KINETIC_TILE,
|
||||
getRenderedBlockState(te));
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
|||
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
|
||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||
import com.simibubi.create.foundation.utility.render.InstancedBuffer;
|
||||
import com.simibubi.create.foundation.utility.render.RotatingBuffer;
|
||||
import com.simibubi.create.foundation.utility.render.SuperByteBuffer;
|
||||
|
||||
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||
|
@ -44,10 +45,10 @@ public class BearingRenderer extends KineticTileEntityRenderer {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected InstancedBuffer getRotatedModel(KineticTileEntity te) {
|
||||
return AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthInstanced(te.getBlockState(), te.getBlockState()
|
||||
.get(BearingBlock.FACING)
|
||||
.getOpposite());
|
||||
protected RotatingBuffer getRotatedModel(KineticTileEntity te) {
|
||||
return AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(te.getBlockState(), te.getBlockState()
|
||||
.get(BearingBlock.FACING)
|
||||
.getOpposite());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
|
|||
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||
import com.simibubi.create.foundation.utility.MatrixStacker;
|
||||
import com.simibubi.create.foundation.utility.render.InstancedBuffer;
|
||||
import com.simibubi.create.foundation.utility.render.RotatingBuffer;
|
||||
import com.simibubi.create.foundation.utility.render.SuperByteBuffer;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
|
@ -52,8 +53,8 @@ public class PumpRenderer extends KineticTileEntityRenderer {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected InstancedBuffer getRotatedModel(KineticTileEntity te) {
|
||||
return AllBlockPartials.MECHANICAL_PUMP_COG.renderOnDirectionalSouthInstanced(te.getBlockState());
|
||||
protected RotatingBuffer getRotatedModel(KineticTileEntity te) {
|
||||
return AllBlockPartials.MECHANICAL_PUMP_COG.renderOnDirectionalSouthRotating(te.getBlockState());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
|
|||
import com.simibubi.create.foundation.tileEntity.renderer.SmartTileEntityRenderer;
|
||||
import com.simibubi.create.foundation.utility.render.InstancedBuffer;
|
||||
|
||||
import com.simibubi.create.foundation.utility.render.RotatingBuffer;
|
||||
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
|
||||
|
||||
|
@ -23,7 +24,7 @@ public class SpeedControllerRenderer extends SmartTileEntityRenderer<SpeedContro
|
|||
KineticTileEntityRenderer.renderRotatingBuffer(tileEntityIn, getRotatedModel(tileEntityIn), light);
|
||||
}
|
||||
|
||||
private InstancedBuffer getRotatedModel(SpeedControllerTileEntity te) {
|
||||
private RotatingBuffer getRotatedModel(SpeedControllerTileEntity te) {
|
||||
return CreateClient.kineticRenderer.renderBlockInstanced(KineticTileEntityRenderer.KINETIC_TILE,
|
||||
KineticTileEntityRenderer.shaft(KineticTileEntityRenderer.getRotationAxisOf(te)));
|
||||
}
|
||||
|
|
|
@ -16,16 +16,14 @@ import com.simibubi.create.foundation.utility.AngleHelper;
|
|||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import com.simibubi.create.foundation.utility.MatrixStacker;
|
||||
import com.simibubi.create.foundation.utility.render.BeltBuffer;
|
||||
import com.simibubi.create.foundation.utility.render.InstancedBuffer;
|
||||
import com.simibubi.create.foundation.utility.render.RotatingBuffer;
|
||||
import com.simibubi.create.foundation.utility.render.ShadowRenderHelper;
|
||||
|
||||
import com.simibubi.create.foundation.utility.render.SuperByteBuffer;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||
import net.minecraft.client.renderer.ItemRenderer;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.Vector3f;
|
||||
import net.minecraft.client.renderer.*;
|
||||
import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType;
|
||||
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
|
||||
import net.minecraft.entity.Entity;
|
||||
|
@ -96,7 +94,10 @@ public class BeltRenderer extends SafeTileEntityRenderer<BeltTileEntity> {
|
|||
: start ? AllBlockPartials.BELT_START
|
||||
: end ? AllBlockPartials.BELT_END : AllBlockPartials.BELT_MIDDLE;
|
||||
|
||||
InstancedBuffer beltBuffer = beltPartial.renderOnInstanced(blockState);
|
||||
BeltBuffer beltBuffer = beltPartial.renderOnBelt(blockState);
|
||||
SpriteShiftEntry spriteShift =
|
||||
diagonal ? AllSpriteShifts.BELT_DIAGONAL : bottom ? AllSpriteShifts.BELT_OFFSET : AllSpriteShifts.BELT;
|
||||
|
||||
int cycleLength = diagonal ? 12 : 16;
|
||||
int cycleOffset = bottom ? 8 : 0;
|
||||
|
||||
|
@ -108,12 +109,16 @@ public class BeltRenderer extends SafeTileEntityRenderer<BeltTileEntity> {
|
|||
|| sideways && axisDirection == AxisDirection.NEGATIVE)
|
||||
speed = -speed;
|
||||
|
||||
data.setPackedLight(light)
|
||||
.setPosition(te.getPos())
|
||||
.setRotationalSpeed(speed)
|
||||
.setRotationAxis(0, 0, 0)
|
||||
.setCycleLength(cycleLength)
|
||||
.setCycleOffset(cycleOffset);
|
||||
Matrix4f m = new Matrix4f();
|
||||
m.loadIdentity();
|
||||
m.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(AngleHelper.horizontalAngle(facing) + (upward ? 180 : 0) + (sideways ? 270 : 0)));
|
||||
m.multiply(Vector3f.POSITIVE_Z.getDegreesQuaternion(sideways ? 90 : 0));
|
||||
m.multiply(Vector3f.POSITIVE_X.getDegreesQuaternion(!diagonal && beltSlope != BeltSlope.HORIZONTAL ? 90 : 0));
|
||||
|
||||
data.setPosition(te.getPos())
|
||||
.setModel(m)
|
||||
.setPackedLight(light)
|
||||
.setRotationalSpeed(speed);
|
||||
});
|
||||
|
||||
// Diagonal belt do not have a separate bottom model
|
||||
|
@ -138,7 +143,7 @@ public class BeltRenderer extends SafeTileEntityRenderer<BeltTileEntity> {
|
|||
msr.rotateX(90);
|
||||
msr.unCentre();
|
||||
|
||||
InstancedBuffer superBuffer = CreateClient.kineticRenderer
|
||||
RotatingBuffer superBuffer = CreateClient.kineticRenderer
|
||||
.renderDirectionalPartialInstanced(AllBlockPartials.BELT_PULLEY, blockState, dir, modelTransform);
|
||||
KineticTileEntityRenderer.renderRotatingBuffer(te, superBuffer, light);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
|
|||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import com.simibubi.create.foundation.utility.render.InstancedBuffer;
|
||||
|
||||
import com.simibubi.create.foundation.utility.render.RotatingBuffer;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
|
||||
|
@ -34,7 +35,7 @@ public class SplitShaftRenderer extends KineticTileEntityRenderer {
|
|||
continue;
|
||||
|
||||
|
||||
InstancedBuffer shaft = AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthInstanced(te.getBlockState(), direction);
|
||||
RotatingBuffer shaft = AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(te.getBlockState(), direction);
|
||||
|
||||
shaft.setupInstance(data -> {
|
||||
float speed = te.getSpeed();
|
||||
|
|
|
@ -7,6 +7,7 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
|
|||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import com.simibubi.create.foundation.utility.render.InstancedBuffer;
|
||||
|
||||
import com.simibubi.create.foundation.utility.render.RotatingBuffer;
|
||||
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
|
||||
import net.minecraft.state.properties.BlockStateProperties;
|
||||
|
@ -31,7 +32,7 @@ public class GearboxRenderer extends KineticTileEntityRenderer {
|
|||
if (boxAxis == axis)
|
||||
continue;
|
||||
|
||||
InstancedBuffer shaft = AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthInstanced(te.getBlockState(), direction);
|
||||
RotatingBuffer shaft = AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(te.getBlockState(), direction);
|
||||
|
||||
shaft.setupInstance(data -> {
|
||||
float speed = te.getSpeed();
|
||||
|
|
|
@ -9,6 +9,7 @@ import com.simibubi.create.content.logistics.block.mechanicalArm.ArmTileEntity.P
|
|||
import com.simibubi.create.foundation.utility.*;
|
||||
|
||||
import com.simibubi.create.foundation.utility.render.InstancedBuffer;
|
||||
import com.simibubi.create.foundation.utility.render.RotatingBuffer;
|
||||
import com.simibubi.create.foundation.utility.render.SuperByteBuffer;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
@ -116,8 +117,8 @@ public class ArmRenderer extends KineticTileEntityRenderer {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected InstancedBuffer getRotatedModel(KineticTileEntity te) {
|
||||
return AllBlockPartials.ARM_COG.renderOnInstanced(te.getBlockState());
|
||||
protected RotatingBuffer getRotatedModel(KineticTileEntity te) {
|
||||
return AllBlockPartials.ARM_COG.renderOnRotating(te.getBlockState());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
package com.simibubi.create.foundation.utility.render;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.GLAllocation;
|
||||
import net.minecraft.client.renderer.LightTexture;
|
||||
import net.minecraft.client.renderer.Matrix4f;
|
||||
import net.minecraft.client.renderer.vertex.VertexFormatElement;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
import org.lwjgl.opengl.GL40;
|
||||
|
||||
import java.nio.Buffer;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class BeltBuffer extends InstancedBuffer<BeltBuffer.BeltData> {
|
||||
public BeltBuffer(BufferBuilder buf) {
|
||||
super(buf);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BeltData newInstance() {
|
||||
return new BeltData();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int numAttributes() {
|
||||
return 9;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finishBufferingInternal() {
|
||||
int floatSize = VertexFormatElement.Type.FLOAT.getSize();
|
||||
int intSize = VertexFormatElement.Type.INT.getSize();
|
||||
int stride = floatSize * 22;
|
||||
|
||||
int instanceSize = instanceCount * stride;
|
||||
|
||||
ByteBuffer buffer = GLAllocation.createDirectByteBuffer(instanceSize);
|
||||
buffer.order(template.order());
|
||||
((Buffer) buffer).limit(instanceSize);
|
||||
|
||||
data.forEach(instanceData -> instanceData.buffer(buffer));
|
||||
buffer.rewind();
|
||||
|
||||
GlStateManager.bindBuffers(GL15.GL_ARRAY_BUFFER, instanceVBO);
|
||||
GlStateManager.bufferData(GL15.GL_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
|
||||
|
||||
// render position
|
||||
GL20.glVertexAttribPointer(3, 3, GL11.GL_FLOAT, false, stride, 0);
|
||||
|
||||
// model matrix
|
||||
for (int i = 0; i < 4; i++) {
|
||||
GL20.glVertexAttribPointer(4 + i, 4, GL11.GL_FLOAT, false, stride, floatSize * (4 * i + 3));
|
||||
}
|
||||
|
||||
// light map
|
||||
GL20.glVertexAttribPointer(8, 2, GL11.GL_FLOAT, false, stride, floatSize * 16L);
|
||||
|
||||
// rotational speed and offset
|
||||
GL20.glVertexAttribPointer(9, 1, GL11.GL_FLOAT, false, stride, floatSize * 18L);
|
||||
|
||||
for (int i = 3; i <= numAttributes(); i++) {
|
||||
GL40.glVertexAttribDivisor(i, 1);
|
||||
}
|
||||
|
||||
// Deselect (bind to 0) the VBO
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
public static class BeltData {
|
||||
private float x;
|
||||
private float y;
|
||||
private float z;
|
||||
private Matrix4f model;
|
||||
private int packedLight;
|
||||
private float rotationalSpeed;
|
||||
|
||||
public BeltData setPosition(BlockPos pos) {
|
||||
this.x = pos.getX();
|
||||
this.y = pos.getY();
|
||||
this.z = pos.getZ();
|
||||
return this;
|
||||
}
|
||||
|
||||
public BeltData setModel(Matrix4f model) {
|
||||
this.model = model;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BeltData setPackedLight(int packedLight) {
|
||||
this.packedLight = packedLight;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BeltData setRotationalSpeed(float rotationalSpeed) {
|
||||
this.rotationalSpeed = rotationalSpeed;
|
||||
return this;
|
||||
}
|
||||
|
||||
void buffer(ByteBuffer buf) {
|
||||
float blockLightCoordinates = LightTexture.getBlockLightCoordinates(packedLight) / (float) 0xF;
|
||||
float skyLightCoordinates = LightTexture.getSkyLightCoordinates(packedLight) / (float) 0xF;
|
||||
|
||||
buf.putFloat(x);
|
||||
buf.putFloat(y);
|
||||
buf.putFloat(z);
|
||||
|
||||
InstancedBuffer.MATRIX_BUF.rewind();
|
||||
model.write(InstancedBuffer.MATRIX_BUF.asFloatBuffer());
|
||||
InstancedBuffer.MATRIX_BUF.rewind();
|
||||
|
||||
buf.put(InstancedBuffer.MATRIX_BUF);
|
||||
buf.putFloat(blockLightCoordinates);
|
||||
buf.putFloat(skyLightCoordinates);
|
||||
buf.putFloat(rotationalSpeed);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ import com.mojang.blaze3d.systems.RenderSystem;
|
|||
import com.simibubi.create.AllBlockPartials;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.foundation.utility.render.shader.Shader;
|
||||
import com.simibubi.create.foundation.utility.render.shader.ShaderCallback;
|
||||
import com.simibubi.create.foundation.utility.render.shader.ShaderHelper;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
@ -36,12 +37,14 @@ import static com.simibubi.create.foundation.utility.render.SuperByteBufferCache
|
|||
|
||||
@Mod.EventBusSubscriber(modid = Create.ID, value = Dist.CLIENT)
|
||||
public class FastKineticRenderer {
|
||||
Map<SuperByteBufferCache.Compartment<?>, Cache<Object, InstancedBuffer>> cache;
|
||||
Map<SuperByteBufferCache.Compartment<?>, Cache<Object, RotatingBuffer>> rotating;
|
||||
Map<SuperByteBufferCache.Compartment<?>, Cache<Object, BeltBuffer>> belts;
|
||||
|
||||
Queue<Runnable> runs;
|
||||
|
||||
public FastKineticRenderer() {
|
||||
cache = new HashMap<>();
|
||||
rotating = new HashMap<>();
|
||||
belts = new HashMap<>();
|
||||
runs = new ConcurrentLinkedQueue<>();
|
||||
registerCompartment(SuperByteBufferCache.GENERIC_TILE);
|
||||
registerCompartment(SuperByteBufferCache.PARTIAL);
|
||||
|
@ -49,8 +52,14 @@ public class FastKineticRenderer {
|
|||
}
|
||||
|
||||
public void tick() {
|
||||
for (Cache<Object, InstancedBuffer> cache : cache.values()) {
|
||||
for (InstancedBuffer renderer : cache.asMap().values()) {
|
||||
for (Cache<Object, RotatingBuffer> cache : rotating.values()) {
|
||||
for (RotatingBuffer renderer : cache.asMap().values()) {
|
||||
renderer.clearInstanceData();
|
||||
}
|
||||
}
|
||||
|
||||
for (Cache<Object, BeltBuffer> cache : belts.values()) {
|
||||
for (BeltBuffer renderer : cache.asMap().values()) {
|
||||
renderer.clearInstanceData();
|
||||
}
|
||||
}
|
||||
|
@ -69,7 +78,22 @@ public class FastKineticRenderer {
|
|||
GameRenderer gameRenderer = Minecraft.getInstance().gameRenderer;
|
||||
LightTexture lightManager = gameRenderer.getLightmapTextureManager();
|
||||
|
||||
ShaderHelper.useShader(Shader.ROTATING_INSTANCED, shader -> {
|
||||
Texture blockAtlasTexture = Minecraft.getInstance().textureManager.getTexture(PlayerContainer.BLOCK_ATLAS_TEXTURE);
|
||||
Texture lightTexture = Minecraft.getInstance().textureManager.getTexture(lightManager.resourceLocation);
|
||||
|
||||
GL40.glActiveTexture(GL40.GL_TEXTURE0);
|
||||
GL40.glBindTexture(GL11.GL_TEXTURE_2D, blockAtlasTexture.getGlTextureId());
|
||||
|
||||
GL40.glActiveTexture(GL40.GL_TEXTURE0 + 1);
|
||||
GL40.glBindTexture(GL11.GL_TEXTURE_2D, lightTexture.getGlTextureId());
|
||||
RenderSystem.texParameter(3553, 10241, 9729);
|
||||
RenderSystem.texParameter(3553, 10240, 9729);
|
||||
RenderSystem.texParameter(3553, 10242, 10496);
|
||||
RenderSystem.texParameter(3553, 10243, 10496);
|
||||
RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
RenderSystem.enableTexture();
|
||||
|
||||
ShaderCallback callback = shader -> {
|
||||
ShaderHelper.MATRIX_BUFFER.position(0);
|
||||
event.getProjectionMatrix().write(ShaderHelper.MATRIX_BUFFER);
|
||||
|
||||
|
@ -85,32 +109,22 @@ public class FastKineticRenderer {
|
|||
translate.write(ShaderHelper.MATRIX_BUFFER);
|
||||
int view = GlStateManager.getUniformLocation(shader, "view");
|
||||
GlStateManager.uniformMatrix4(view, false, ShaderHelper.MATRIX_BUFFER);
|
||||
};
|
||||
ShaderHelper.useShader(Shader.ROTATING_INSTANCED, callback);
|
||||
|
||||
Texture blockAtlasTexture = Minecraft.getInstance().textureManager.getTexture(PlayerContainer.BLOCK_ATLAS_TEXTURE);
|
||||
Texture lightTexture = Minecraft.getInstance().textureManager.getTexture(lightManager.resourceLocation);
|
||||
rotating.values()
|
||||
.stream()
|
||||
.flatMap(cache -> cache.asMap().values().stream())
|
||||
.filter(type -> !type.isEmpty())
|
||||
.forEach(InstancedBuffer::render);
|
||||
|
||||
GL40.glActiveTexture(GL40.GL_TEXTURE0);
|
||||
GL40.glBindTexture(GL11.GL_TEXTURE_2D, blockAtlasTexture.getGlTextureId());
|
||||
ShaderHelper.useShader(Shader.BELT_INSTANCED, callback);
|
||||
|
||||
GL40.glActiveTexture(GL40.GL_TEXTURE0 + 1);
|
||||
GL40.glBindTexture(GL11.GL_TEXTURE_2D, lightTexture.getGlTextureId());
|
||||
RenderSystem.texParameter(3553, 10241, 9729);
|
||||
RenderSystem.texParameter(3553, 10240, 9729);
|
||||
RenderSystem.texParameter(3553, 10242, 10496);
|
||||
RenderSystem.texParameter(3553, 10243, 10496);
|
||||
RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
RenderSystem.enableTexture();
|
||||
});
|
||||
|
||||
cache.values()
|
||||
.stream()
|
||||
.flatMap(cache -> {
|
||||
ConcurrentMap<Object, InstancedBuffer> map = cache.asMap();
|
||||
|
||||
return map.values().stream();
|
||||
})
|
||||
.filter(type -> !type.isEmpty())
|
||||
.forEach(InstancedBuffer::render);
|
||||
belts.values()
|
||||
.stream()
|
||||
.flatMap(cache -> cache.asMap().values().stream())
|
||||
.filter(type -> !type.isEmpty())
|
||||
.forEach(InstancedBuffer::render);
|
||||
|
||||
ShaderHelper.releaseShader();
|
||||
|
||||
|
@ -129,29 +143,45 @@ public class FastKineticRenderer {
|
|||
}
|
||||
|
||||
public void registerCompartment(SuperByteBufferCache.Compartment<?> instance) {
|
||||
cache.put(instance, CacheBuilder.newBuilder().build());
|
||||
rotating.put(instance, CacheBuilder.newBuilder().build());
|
||||
belts.put(instance, CacheBuilder.newBuilder().build());
|
||||
}
|
||||
|
||||
public void registerCompartment(SuperByteBufferCache.Compartment<?> instance, long ticksUntilExpired) {
|
||||
cache.put(instance, CacheBuilder.newBuilder().expireAfterAccess(ticksUntilExpired * 50, TimeUnit.MILLISECONDS).build());
|
||||
rotating.put(instance, CacheBuilder.newBuilder().expireAfterAccess(ticksUntilExpired * 50, TimeUnit.MILLISECONDS).build());
|
||||
belts.put(instance, CacheBuilder.newBuilder().expireAfterAccess(ticksUntilExpired * 50, TimeUnit.MILLISECONDS).build());
|
||||
}
|
||||
|
||||
public InstancedBuffer renderPartialInstanced(AllBlockPartials partial, BlockState referenceState) {
|
||||
return getInstanced(PARTIAL, partial, () -> rotatingInstancedRenderer(partial.get(), referenceState));
|
||||
public RotatingBuffer renderPartialRotating(AllBlockPartials partial, BlockState referenceState) {
|
||||
return getRotating(PARTIAL, partial, () -> rotatingInstancedRenderer(partial.get(), referenceState));
|
||||
}
|
||||
|
||||
public InstancedBuffer renderDirectionalPartialInstanced(AllBlockPartials partial, BlockState referenceState, Direction dir,
|
||||
public BeltBuffer renderPartialBelt(AllBlockPartials partial, BlockState referenceState) {
|
||||
return getBelt(PARTIAL, partial, () -> beltInstancedRenderer(partial.get(), referenceState));
|
||||
}
|
||||
|
||||
public RotatingBuffer renderDirectionalPartialInstanced(AllBlockPartials partial, BlockState referenceState, Direction dir,
|
||||
MatrixStack modelTransform) {
|
||||
return getInstanced(SuperByteBufferCache.DIRECTIONAL_PARTIAL, Pair.of(dir, partial),
|
||||
() -> rotatingInstancedRenderer(partial.get(), referenceState, modelTransform));
|
||||
return getRotating(SuperByteBufferCache.DIRECTIONAL_PARTIAL, Pair.of(dir, partial),
|
||||
() -> rotatingInstancedRenderer(partial.get(), referenceState, modelTransform));
|
||||
}
|
||||
|
||||
public InstancedBuffer renderBlockInstanced(SuperByteBufferCache.Compartment<BlockState> compartment, BlockState toRender) {
|
||||
return getInstanced(compartment, toRender, () -> rotatingInstancedRenderer(toRender));
|
||||
public RotatingBuffer renderBlockInstanced(SuperByteBufferCache.Compartment<BlockState> compartment, BlockState toRender) {
|
||||
return getRotating(compartment, toRender, () -> rotatingInstancedRenderer(toRender));
|
||||
}
|
||||
|
||||
public <T> InstancedBuffer getInstanced(SuperByteBufferCache.Compartment<T> compartment, T key, Supplier<InstancedBuffer> supplier) {
|
||||
Cache<Object, InstancedBuffer> compartmentCache = this.cache.get(compartment);
|
||||
public <T> RotatingBuffer getRotating(SuperByteBufferCache.Compartment<T> compartment, T key, Supplier<RotatingBuffer> supplier) {
|
||||
Cache<Object, RotatingBuffer> compartmentCache = this.rotating.get(compartment);
|
||||
try {
|
||||
return compartmentCache.get(key, supplier::get);
|
||||
} catch (ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public <T> BeltBuffer getBelt(SuperByteBufferCache.Compartment<T> compartment, T key, Supplier<BeltBuffer> supplier) {
|
||||
Cache<Object, BeltBuffer> compartmentCache = this.belts.get(compartment);
|
||||
try {
|
||||
return compartmentCache.get(key, supplier::get);
|
||||
} catch (ExecutionException e) {
|
||||
|
@ -161,23 +191,33 @@ public class FastKineticRenderer {
|
|||
}
|
||||
|
||||
|
||||
private InstancedBuffer rotatingInstancedRenderer(BlockState renderedState) {
|
||||
private RotatingBuffer rotatingInstancedRenderer(BlockState renderedState) {
|
||||
BlockRendererDispatcher dispatcher = Minecraft.getInstance().getBlockRendererDispatcher();
|
||||
return rotatingInstancedRenderer(dispatcher.getModelForState(renderedState), renderedState);
|
||||
}
|
||||
|
||||
private InstancedBuffer rotatingInstancedRenderer(IBakedModel model, BlockState renderedState) {
|
||||
private RotatingBuffer rotatingInstancedRenderer(IBakedModel model, BlockState renderedState) {
|
||||
return rotatingInstancedRenderer(model, renderedState, new MatrixStack());
|
||||
}
|
||||
|
||||
private InstancedBuffer rotatingInstancedRenderer(IBakedModel model, BlockState referenceState, MatrixStack ms) {
|
||||
private BeltBuffer beltInstancedRenderer(IBakedModel model, BlockState renderedState) {
|
||||
return beltInstancedRenderer(model, renderedState, new MatrixStack());
|
||||
}
|
||||
|
||||
private RotatingBuffer rotatingInstancedRenderer(IBakedModel model, BlockState referenceState, MatrixStack ms) {
|
||||
BufferBuilder builder = SuperByteBufferCache.getBufferBuilder(model, referenceState, ms);
|
||||
|
||||
return new InstancedBuffer(builder);
|
||||
return new RotatingBuffer(builder);
|
||||
}
|
||||
|
||||
private BeltBuffer beltInstancedRenderer(IBakedModel model, BlockState referenceState, MatrixStack ms) {
|
||||
BufferBuilder builder = SuperByteBufferCache.getBufferBuilder(model, referenceState, ms);
|
||||
|
||||
return new BeltBuffer(builder);
|
||||
}
|
||||
|
||||
public void invalidate() {
|
||||
cache.values().forEach(cache -> {
|
||||
rotating.values().forEach(cache -> {
|
||||
cache.asMap().values().forEach(InstancedBuffer::invalidate);
|
||||
cache.invalidateAll();
|
||||
});
|
||||
|
|
|
@ -5,10 +5,7 @@ import com.mojang.blaze3d.platform.GlStateManager;
|
|||
import com.simibubi.create.CreateClient;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.GLAllocation;
|
||||
import net.minecraft.client.renderer.LightTexture;
|
||||
import net.minecraft.client.renderer.Vector3f;
|
||||
import net.minecraft.client.renderer.vertex.VertexFormatElement;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import org.lwjgl.opengl.*;
|
||||
|
||||
import java.nio.Buffer;
|
||||
|
@ -16,12 +13,14 @@ import java.nio.ByteBuffer;
|
|||
import java.util.ArrayList;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class InstancedBuffer extends TemplateBuffer {
|
||||
public abstract class InstancedBuffer<T> extends TemplateBuffer {
|
||||
|
||||
public int vao, ebo, invariantVBO, instanceVBO, instanceCount;
|
||||
protected static ByteBuffer MATRIX_BUF = GLAllocation.createDirectByteBuffer(16 << 2);
|
||||
|
||||
private final ArrayList<InstanceData> data = new ArrayList<>();
|
||||
private boolean shouldBuild = true;
|
||||
protected int vao, ebo, invariantVBO, instanceVBO, instanceCount;
|
||||
|
||||
protected final ArrayList<T> data = new ArrayList<>();
|
||||
protected boolean shouldBuild = true;
|
||||
|
||||
public InstancedBuffer(BufferBuilder buf) {
|
||||
super(buf);
|
||||
|
@ -113,166 +112,52 @@ public class InstancedBuffer extends TemplateBuffer {
|
|||
});
|
||||
}
|
||||
|
||||
public void setupInstance(Consumer<InstanceData> setup) {
|
||||
protected void addData(T instance) {
|
||||
data.add(instance);
|
||||
instanceCount++;
|
||||
}
|
||||
|
||||
protected abstract T newInstance();
|
||||
|
||||
protected abstract int numAttributes();
|
||||
|
||||
public void setupInstance(Consumer<T> setup) {
|
||||
if (!shouldBuild) return;
|
||||
|
||||
InstanceData instanceData = new InstanceData();
|
||||
T instanceData = newInstance();
|
||||
setup.accept(instanceData);
|
||||
|
||||
data.add(instanceData);
|
||||
instanceCount++;
|
||||
addData(instanceData);
|
||||
}
|
||||
|
||||
public void render() {
|
||||
|
||||
GL30.glBindVertexArray(vao);
|
||||
if (finishBuffering()) {
|
||||
finishBuffering();
|
||||
|
||||
for (int i = 0; i <= 8; i++) {
|
||||
GL40.glEnableVertexAttribArray(i);
|
||||
}
|
||||
|
||||
GlStateManager.bindBuffers(GL15.GL_ELEMENT_ARRAY_BUFFER, ebo);
|
||||
|
||||
GL40.glDrawElementsInstanced(GL11.GL_QUADS, count, GL11.GL_UNSIGNED_SHORT, 0, instanceCount);
|
||||
|
||||
for (int i = 0; i <= 8; i++) {
|
||||
GL40.glDisableVertexAttribArray(i);
|
||||
}
|
||||
for (int i = 0; i <= 10; i++) {
|
||||
GL40.glEnableVertexAttribArray(i);
|
||||
}
|
||||
|
||||
GlStateManager.bindBuffers(GL15.GL_ELEMENT_ARRAY_BUFFER, ebo);
|
||||
|
||||
GL40.glDrawElementsInstanced(GL11.GL_QUADS, count, GL11.GL_UNSIGNED_SHORT, 0, instanceCount);
|
||||
|
||||
for (int i = 0; i <= 10; i++) {
|
||||
GL40.glDisableVertexAttribArray(i);
|
||||
}
|
||||
|
||||
GL30.glBindVertexArray(0);
|
||||
}
|
||||
|
||||
private boolean finishBuffering() {
|
||||
if (!shouldBuild) return true;
|
||||
private void finishBuffering() {
|
||||
if (!shouldBuild) return;
|
||||
|
||||
int floatSize = VertexFormatElement.Type.FLOAT.getSize();
|
||||
int intSize = VertexFormatElement.Type.INT.getSize();
|
||||
int stride = floatSize * 10 + intSize * 2;
|
||||
|
||||
int instanceSize = data.size() * stride;
|
||||
|
||||
if (instanceSize == 0) return false;
|
||||
|
||||
ByteBuffer buffer = GLAllocation.createDirectByteBuffer(instanceSize);
|
||||
buffer.order(template.order());
|
||||
((Buffer) buffer).limit(instanceSize);
|
||||
|
||||
data.forEach(instanceData -> instanceData.buffer(buffer));
|
||||
buffer.rewind();
|
||||
|
||||
GlStateManager.bindBuffers(GL15.GL_ARRAY_BUFFER, instanceVBO);
|
||||
GlStateManager.bufferData(GL15.GL_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
|
||||
|
||||
// the render position
|
||||
GL20.glVertexAttribPointer(3, 3, GL11.GL_FLOAT, false, stride, 0);
|
||||
|
||||
// vertex lighting
|
||||
GL20.glVertexAttribPointer(4, 2, GL11.GL_FLOAT, false, stride, floatSize * 3L);
|
||||
|
||||
// rotational speed and offset
|
||||
GL20.glVertexAttribPointer(5, 1, GL11.GL_FLOAT, false, stride, floatSize * 5L);
|
||||
GL20.glVertexAttribPointer(6, 1, GL11.GL_FLOAT, false, stride, floatSize * 6L);
|
||||
// rotation axis
|
||||
GL20.glVertexAttribPointer(7, 3, GL11.GL_FLOAT, false, stride, floatSize * 7L);
|
||||
// uv scrolling
|
||||
GL20.glVertexAttribPointer(8, 2, GL11.GL_INT, false, stride, floatSize * 10L);
|
||||
|
||||
for (int i = 3; i <= 8; i++) {
|
||||
GL40.glVertexAttribDivisor(i, 1);
|
||||
}
|
||||
|
||||
// Deselect (bind to 0) the VBO
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
finishBufferingInternal();
|
||||
|
||||
shouldBuild = false;
|
||||
data.clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static class InstanceData {
|
||||
private float x;
|
||||
private float y;
|
||||
private float z;
|
||||
private int packedLight = 0;
|
||||
private float rotationalSpeed;
|
||||
private float rotationOffset;
|
||||
private float rotationAxisX;
|
||||
private float rotationAxisY;
|
||||
private float rotationAxisZ;
|
||||
private int cycleLength;
|
||||
private int cycleOffset;
|
||||
|
||||
public InstanceData setPackedLight(int packedLight) {
|
||||
this.packedLight = packedLight;
|
||||
return this;
|
||||
}
|
||||
|
||||
public InstanceData setRotationalSpeed(float rotationalSpeed) {
|
||||
this.rotationalSpeed = rotationalSpeed;
|
||||
return this;
|
||||
}
|
||||
|
||||
public InstanceData setRotationOffset(float rotationOffset) {
|
||||
this.rotationOffset = rotationOffset;
|
||||
return this;
|
||||
}
|
||||
|
||||
public InstanceData setPosition(Vector3f pos) {
|
||||
this.x = pos.getX();
|
||||
this.y = pos.getY();
|
||||
this.z = pos.getZ();
|
||||
return this;
|
||||
}
|
||||
|
||||
public InstanceData setPosition(BlockPos pos) {
|
||||
this.x = pos.getX();
|
||||
this.y = pos.getY();
|
||||
this.z = pos.getZ();
|
||||
return this;
|
||||
}
|
||||
|
||||
public InstanceData setRotationAxis(Vector3f axis) {
|
||||
this.rotationAxisX = axis.getX();
|
||||
this.rotationAxisY = axis.getY();
|
||||
this.rotationAxisZ = axis.getZ();
|
||||
return this;
|
||||
}
|
||||
|
||||
public InstanceData setRotationAxis(float rotationAxisX, float rotationAxisY, float rotationAxisZ) {
|
||||
this.rotationAxisX = rotationAxisX;
|
||||
this.rotationAxisY = rotationAxisY;
|
||||
this.rotationAxisZ = rotationAxisZ;
|
||||
return this;
|
||||
}
|
||||
|
||||
public InstanceData setCycleLength(int cycleLength) {
|
||||
this.cycleLength = cycleLength;
|
||||
return this;
|
||||
}
|
||||
|
||||
public InstanceData setCycleOffset(int cycleOffset) {
|
||||
this.cycleOffset = cycleOffset;
|
||||
return this;
|
||||
}
|
||||
|
||||
void buffer(ByteBuffer buf) {
|
||||
float blockLightCoordinates = LightTexture.getBlockLightCoordinates(packedLight) / (float) 0xF;
|
||||
float skyLightCoordinates = LightTexture.getSkyLightCoordinates(packedLight) / (float) 0xF;
|
||||
|
||||
buf.putFloat(x);
|
||||
buf.putFloat(y);
|
||||
buf.putFloat(z);
|
||||
buf.putFloat(blockLightCoordinates);
|
||||
buf.putFloat(skyLightCoordinates);
|
||||
buf.putFloat(rotationalSpeed);
|
||||
buf.putFloat(rotationOffset);
|
||||
buf.putFloat(rotationAxisX);
|
||||
buf.putFloat(rotationAxisY);
|
||||
buf.putFloat(rotationAxisZ);
|
||||
buf.putInt(cycleLength);
|
||||
buf.putInt(cycleOffset);
|
||||
}
|
||||
}
|
||||
protected abstract void finishBufferingInternal();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
package com.simibubi.create.foundation.utility.render;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.simibubi.create.foundation.block.render.SpriteShiftEntry;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.GLAllocation;
|
||||
import net.minecraft.client.renderer.LightTexture;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.renderer.vertex.VertexFormatElement;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.vector.Vector3f;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
import org.lwjgl.opengl.GL40;
|
||||
|
||||
import java.nio.Buffer;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class RotatingBuffer extends InstancedBuffer<RotatingBuffer.InstanceData> {
|
||||
public RotatingBuffer(BufferBuilder buf) {
|
||||
super(buf);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InstanceData newInstance() {
|
||||
return new InstanceData();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int numAttributes() {
|
||||
return 7;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finishBufferingInternal() {
|
||||
int floatSize = VertexFormatElement.Type.FLOAT.getSize();
|
||||
int stride = floatSize * 10;
|
||||
|
||||
int instanceSize = instanceCount * stride;
|
||||
|
||||
ByteBuffer buffer = GLAllocation.createDirectByteBuffer(instanceSize);
|
||||
buffer.order(template.order());
|
||||
((Buffer) buffer).limit(instanceSize);
|
||||
|
||||
data.forEach(instanceData -> instanceData.buffer(buffer));
|
||||
buffer.rewind();
|
||||
|
||||
GlStateManager.bindBuffers(GL15.GL_ARRAY_BUFFER, instanceVBO);
|
||||
GlStateManager.bufferData(GL15.GL_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
|
||||
|
||||
// the render position
|
||||
GL20.glVertexAttribPointer(3, 3, GL11.GL_FLOAT, false, stride, 0);
|
||||
|
||||
// vertex lighting
|
||||
GL20.glVertexAttribPointer(4, 2, GL11.GL_FLOAT, false, stride, floatSize * 3L);
|
||||
|
||||
// rotational speed and offset
|
||||
GL20.glVertexAttribPointer(5, 1, GL11.GL_FLOAT, false, stride, floatSize * 5L);
|
||||
GL20.glVertexAttribPointer(6, 1, GL11.GL_FLOAT, false, stride, floatSize * 6L);
|
||||
// rotation axis
|
||||
GL20.glVertexAttribPointer(7, 3, GL11.GL_FLOAT, false, stride, floatSize * 7L);
|
||||
|
||||
for (int i = 3; i <= numAttributes(); i++) {
|
||||
GL40.glVertexAttribDivisor(i, 1);
|
||||
}
|
||||
|
||||
// Deselect (bind to 0) the VBO
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
public static class InstanceData {
|
||||
private float x;
|
||||
private float y;
|
||||
private float z;
|
||||
private int packedLight;
|
||||
private float rotationalSpeed;
|
||||
private float rotationOffset;
|
||||
private float rotationAxisX;
|
||||
private float rotationAxisY;
|
||||
private float rotationAxisZ;
|
||||
|
||||
public InstanceData setPackedLight(int packedLight) {
|
||||
this.packedLight = packedLight;
|
||||
return this;
|
||||
}
|
||||
|
||||
public InstanceData setRotationalSpeed(float rotationalSpeed) {
|
||||
this.rotationalSpeed = rotationalSpeed;
|
||||
return this;
|
||||
}
|
||||
|
||||
public InstanceData setRotationOffset(float rotationOffset) {
|
||||
this.rotationOffset = rotationOffset;
|
||||
return this;
|
||||
}
|
||||
|
||||
public InstanceData setPosition(Vector3f pos) {
|
||||
this.x = pos.getX();
|
||||
this.y = pos.getY();
|
||||
this.z = pos.getZ();
|
||||
return this;
|
||||
}
|
||||
|
||||
public InstanceData setPosition(BlockPos pos) {
|
||||
this.x = pos.getX();
|
||||
this.y = pos.getY();
|
||||
this.z = pos.getZ();
|
||||
return this;
|
||||
}
|
||||
|
||||
public InstanceData setRotationAxis(Vector3f axis) {
|
||||
this.rotationAxisX = axis.getX();
|
||||
this.rotationAxisY = axis.getY();
|
||||
this.rotationAxisZ = axis.getZ();
|
||||
return this;
|
||||
}
|
||||
|
||||
public InstanceData setRotationAxis(float rotationAxisX, float rotationAxisY, float rotationAxisZ) {
|
||||
this.rotationAxisX = rotationAxisX;
|
||||
this.rotationAxisY = rotationAxisY;
|
||||
this.rotationAxisZ = rotationAxisZ;
|
||||
return this;
|
||||
}
|
||||
|
||||
void buffer(ByteBuffer buf) {
|
||||
float blockLightCoordinates = LightTexture.getBlockLightCoordinates(packedLight) / (float) 0xF;
|
||||
float skyLightCoordinates = LightTexture.getSkyLightCoordinates(packedLight) / (float) 0xF;
|
||||
|
||||
buf.putFloat(x);
|
||||
buf.putFloat(y);
|
||||
buf.putFloat(z);
|
||||
buf.putFloat(blockLightCoordinates);
|
||||
buf.putFloat(skyLightCoordinates);
|
||||
buf.putFloat(rotationalSpeed);
|
||||
buf.putFloat(rotationOffset);
|
||||
buf.putFloat(rotationAxisX);
|
||||
buf.putFloat(rotationAxisY);
|
||||
buf.putFloat(rotationAxisZ);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,8 @@
|
|||
package com.simibubi.create.foundation.utility.render.shader;
|
||||
|
||||
public enum Shader {
|
||||
ROTATING_INSTANCED("shader/instanced.vert", "shader/instanced.frag");
|
||||
ROTATING_INSTANCED("shader/rotating.vert", "shader/instanced.frag"),
|
||||
BELT_INSTANCED("shader/belt.vert", "shader/instanced.frag"),;
|
||||
|
||||
public final String vert;
|
||||
public final String frag;
|
||||
|
|
35
src/main/resources/assets/create/shader/belt.vert
Normal file
35
src/main/resources/assets/create/shader/belt.vert
Normal file
|
@ -0,0 +1,35 @@
|
|||
#version 330 core
|
||||
#define PI 3.1415926538
|
||||
|
||||
layout (location = 0) in vec3 aPos;
|
||||
layout (location = 1) in vec3 aNormal;
|
||||
layout (location = 2) in vec2 aTexCoords;
|
||||
|
||||
layout (location = 3) in vec3 instancePos;
|
||||
layout (location = 4) in mat4 model;
|
||||
layout (location = 8) in vec2 light;
|
||||
layout (location = 9) in float speed;
|
||||
|
||||
out vec2 TexCoords;
|
||||
out vec2 Light;
|
||||
|
||||
uniform float time;
|
||||
uniform int ticks;
|
||||
uniform mat4 projection;
|
||||
uniform mat4 view;
|
||||
|
||||
|
||||
void main() {
|
||||
// float textureIndex = fract((speed * time / 36 + cycle[1]) / cycle[0]) * cycle[0];
|
||||
// if (textureIndex < 0) {
|
||||
// textureIndex += cycle[0];
|
||||
// }
|
||||
//
|
||||
// vec2 scrollPos = vec2(fract(textureIndex / 4), floor(textureIndex / 16));
|
||||
|
||||
vec4 renderPos = model * vec4(aPos - vec3(0.5), 1f);
|
||||
renderPos += vec4(instancePos + vec3(0.5), 0);
|
||||
|
||||
TexCoords = aTexCoords;
|
||||
gl_Position = projection * view * renderPos;
|
||||
}
|
|
@ -9,7 +9,6 @@ layout (location = 4) in vec2 light;
|
|||
layout (location = 5) in float speed;
|
||||
layout (location = 6) in float rotationOffset;
|
||||
layout (location = 7) in vec3 rotationAxis;
|
||||
layout (location = 8) in int[2] uvScroll; // uvScroll[0] <- cycleLength, uvScroll[1] <- cycleOffset
|
||||
|
||||
out vec2 TexCoords;
|
||||
out vec2 Light;
|
||||
|
@ -19,9 +18,12 @@ uniform int ticks;
|
|||
uniform mat4 projection;
|
||||
uniform mat4 view;
|
||||
|
||||
mat4 rotationMatrix(vec3 axis, float angle)
|
||||
mat4 kineticRotation()
|
||||
{
|
||||
axis = normalize(axis);
|
||||
float degrees = rotationOffset + time * speed * -3./10.;
|
||||
float angle = fract(degrees / 360.) * PI * 2.;
|
||||
|
||||
vec3 axis = normalize(rotationAxis);
|
||||
float s = sin(angle);
|
||||
float c = cos(angle);
|
||||
float oc = 1.0 - c;
|
||||
|
@ -34,26 +36,11 @@ mat4 rotationMatrix(vec3 axis, float angle)
|
|||
|
||||
void main()
|
||||
{
|
||||
vec4 renderPos;
|
||||
int textureIndex = 0;
|
||||
if (abs(rotationAxis.x) + abs(rotationAxis.y) + abs(rotationAxis.z) < 0.2) {
|
||||
renderPos = vec4(aPos + instancePos, 1f);
|
||||
vec4 renderPos = kineticRotation() * vec4(aPos - vec3(0.5), 1);
|
||||
|
||||
textureIndex = int((speed * time / 36) + uvScroll[1]) % uvScroll[0];
|
||||
if (textureIndex < 0) {
|
||||
textureIndex += uvScroll[0];
|
||||
}
|
||||
renderPos += vec4(instancePos + vec3(0.5), 0);
|
||||
|
||||
} else {
|
||||
float degrees = rotationOffset + time * speed * 3./10.;
|
||||
float angle = fract(-degrees / 360.) * PI * 2.;
|
||||
|
||||
renderPos = rotationMatrix(rotationAxis, angle) * vec4(aPos - vec3(0.5), 1f);
|
||||
|
||||
renderPos += vec4(instancePos + vec3(0.5), 0);
|
||||
}
|
||||
|
||||
TexCoords = aTexCoords + vec2(float(textureIndex % 4) / 4f, float(textureIndex / 4) / 4f);
|
||||
TexCoords = aTexCoords;
|
||||
|
||||
gl_Position = projection * view * renderPos;
|
||||
Light = light;
|
Loading…
Reference in a new issue