mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-11-14 06:24:12 +01:00
hot swappable rendering
kind of detects optifine still some kinks to work out
This commit is contained in:
parent
3e6ef34993
commit
c9ff31b099
@ -12,9 +12,10 @@ 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.KineticRenderer;
|
||||
import com.simibubi.create.foundation.render.OptifineHandler;
|
||||
import com.simibubi.create.foundation.render.SuperByteBufferCache;
|
||||
import com.simibubi.create.foundation.render.contraption.ContraptionRenderDispatcher;
|
||||
import com.simibubi.create.foundation.render.gl.shader.ShaderHelper;
|
||||
import com.simibubi.create.foundation.render.gl.backend.Backend;
|
||||
import com.simibubi.create.foundation.utility.outliner.Outliner;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.Minecraft;
|
||||
@ -31,8 +32,6 @@ import net.minecraftforge.client.event.ModelRegistryEvent;
|
||||
import net.minecraftforge.client.event.TextureStitchEvent;
|
||||
import net.minecraftforge.client.model.ModelLoader;
|
||||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
import net.minecraftforge.fml.ModList;
|
||||
import net.minecraftforge.fml.ModLoader;
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -62,10 +61,13 @@ public class CreateClient {
|
||||
modEventBus.addListener(CreateClient::onTextureStitch);
|
||||
modEventBus.addListener(AllParticleTypes::registerFactories);
|
||||
|
||||
ShaderHelper.initShaders();
|
||||
Backend.init();
|
||||
OptifineHandler.init();
|
||||
}
|
||||
|
||||
public static void clientInit(FMLClientSetupEvent event) {
|
||||
kineticRenderer = new KineticRenderer();
|
||||
|
||||
schematicSender = new ClientSchematicLoader();
|
||||
schematicHandler = new SchematicHandler();
|
||||
schematicAndQuillHandler = new SchematicAndQuillHandler();
|
||||
@ -74,8 +76,6 @@ public class CreateClient {
|
||||
bufferCache.registerCompartment(KineticTileEntityRenderer.KINETIC_TILE);
|
||||
bufferCache.registerCompartment(ContraptionRenderer.CONTRAPTION, 20);
|
||||
|
||||
kineticRenderer = new KineticRenderer();
|
||||
|
||||
AllKeys.register();
|
||||
AllContainerTypes.registerScreenFactories();
|
||||
//AllTileEntities.registerRenderers();
|
||||
|
@ -30,6 +30,8 @@ import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.text.TextFormatting;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.fml.DistExecutor;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
@ -475,13 +477,13 @@ public abstract class KineticTileEntity extends SmartTileEntity
|
||||
public void onLoad() {
|
||||
super.onLoad();
|
||||
if (world != null && world.isRemote)
|
||||
CreateClient.kineticRenderer.add(this);
|
||||
DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> CreateClient.kineticRenderer.add(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkUnloaded() {
|
||||
if (world != null && world.isRemote)
|
||||
CreateClient.kineticRenderer.remove(this);
|
||||
DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> CreateClient.kineticRenderer.remove(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -6,6 +6,9 @@ import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.CreateClient;
|
||||
import com.simibubi.create.content.contraptions.KineticDebugger;
|
||||
import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock;
|
||||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
import com.simibubi.create.foundation.config.ConfigBase;
|
||||
import com.simibubi.create.foundation.render.FastRenderDispatcher;
|
||||
import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer;
|
||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||
import com.simibubi.create.foundation.utility.ColorHelper;
|
||||
@ -38,6 +41,8 @@ public class KineticTileEntityRenderer extends SafeTileEntityRenderer<KineticTil
|
||||
@Override
|
||||
protected void renderSafe(KineticTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer,
|
||||
int light, int overlay) {
|
||||
if (FastRenderDispatcher.available()) return;
|
||||
|
||||
for (RenderType type : RenderType.getBlockLayers())
|
||||
if (RenderTypeLookup.canRenderInLayer(te.getBlockState(), type))
|
||||
renderRotatingBuffer(te, getRotatedModel(te), ms, buffer.getBuffer(type), light);
|
||||
|
@ -6,6 +6,8 @@ import com.simibubi.create.AllBlockPartials;
|
||||
import com.simibubi.create.AllSpriteShifts;
|
||||
import com.simibubi.create.content.contraptions.components.crafter.MechanicalCrafterTileEntity.Phase;
|
||||
import com.simibubi.create.content.contraptions.components.crafter.RecipeGridHandler.GroupedItems;
|
||||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
import com.simibubi.create.foundation.render.FastRenderDispatcher;
|
||||
import com.simibubi.create.foundation.render.SuperByteBuffer;
|
||||
import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer;
|
||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||
@ -152,12 +154,13 @@ public class MechanicalCrafterRenderer extends SafeTileEntityRenderer<Mechanical
|
||||
BlockState blockState = te.getBlockState();
|
||||
IVertexBuilder vb = buffer.getBuffer(RenderType.getSolid());
|
||||
|
||||
SuperByteBuffer superBuffer = AllBlockPartials.SHAFTLESS_COGWHEEL.renderOn(blockState);
|
||||
standardKineticRotationTransform(superBuffer, te, light);
|
||||
superBuffer.rotateCentered(Direction.UP, (float) (blockState.get(HORIZONTAL_FACING)
|
||||
.getAxis() != Direction.Axis.X ? 0 : Math.PI / 2));
|
||||
superBuffer.rotateCentered(Direction.EAST, (float) (Math.PI / 2));
|
||||
superBuffer.renderInto(ms, vb);
|
||||
if (!FastRenderDispatcher.available()) {
|
||||
SuperByteBuffer superBuffer = AllBlockPartials.SHAFTLESS_COGWHEEL.renderOn(blockState);
|
||||
standardKineticRotationTransform(superBuffer, te, light);
|
||||
superBuffer.rotateCentered(Direction.UP, (float) (blockState.get(HORIZONTAL_FACING).getAxis() != Direction.Axis.X ? 0 : Math.PI / 2));
|
||||
superBuffer.rotateCentered(Direction.EAST, (float) (Math.PI / 2));
|
||||
superBuffer.renderInto(ms, vb);
|
||||
}
|
||||
|
||||
Direction targetDirection = MechanicalCrafterBlock.getTargetDirection(blockState);
|
||||
BlockPos pos = te.getPos();
|
||||
|
@ -11,6 +11,8 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
|
||||
import com.simibubi.create.content.contraptions.components.deployer.DeployerTileEntity.Mode;
|
||||
import com.simibubi.create.content.contraptions.components.deployer.DeployerTileEntity.State;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
||||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
import com.simibubi.create.foundation.render.FastRenderDispatcher;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringRenderer;
|
||||
import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer;
|
||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||
@ -102,7 +104,9 @@ public class DeployerRenderer extends SafeTileEntityRenderer<DeployerTileEntity>
|
||||
protected void renderComponents(DeployerTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer,
|
||||
int light, int overlay) {
|
||||
IVertexBuilder vb = buffer.getBuffer(RenderType.getSolid());
|
||||
KineticTileEntityRenderer.renderRotatingKineticBlock(te, getRenderedBlockState(te), ms, vb, light);
|
||||
if (!FastRenderDispatcher.available()) {
|
||||
KineticTileEntityRenderer.renderRotatingKineticBlock(te, getRenderedBlockState(te), ms, vb, light);
|
||||
}
|
||||
|
||||
BlockState blockState = te.getBlockState();
|
||||
BlockPos pos = te.getPos();
|
||||
|
@ -376,4 +376,9 @@ public class DeployerTileEntity extends KineticTileEntity {
|
||||
TooltipHelper.addHint(tooltip, "hint.full_deployer");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldRenderAsTE() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,8 @@ import com.mojang.blaze3d.vertex.IVertexBuilder;
|
||||
import com.simibubi.create.AllBlockPartials;
|
||||
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
||||
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
|
||||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
import com.simibubi.create.foundation.render.FastRenderDispatcher;
|
||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||
import com.simibubi.create.foundation.render.SuperByteBuffer;
|
||||
|
||||
@ -26,6 +28,8 @@ public class EncasedFanRenderer extends KineticTileEntityRenderer {
|
||||
@Override
|
||||
protected void renderSafe(KineticTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer,
|
||||
int light, int overlay) {
|
||||
if (FastRenderDispatcher.available()) return;
|
||||
|
||||
Direction direction = te.getBlockState()
|
||||
.get(FACING);
|
||||
IVertexBuilder vb = buffer.getBuffer(RenderType.getCutoutMipped());
|
||||
|
@ -5,6 +5,8 @@ import com.mojang.blaze3d.vertex.IVertexBuilder;
|
||||
import com.simibubi.create.AllBlockPartials;
|
||||
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
||||
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
|
||||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
import com.simibubi.create.foundation.render.FastRenderDispatcher;
|
||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||
import com.simibubi.create.foundation.render.SuperByteBuffer;
|
||||
|
||||
@ -31,8 +33,10 @@ public class MechanicalMixerRenderer extends KineticTileEntityRenderer {
|
||||
|
||||
IVertexBuilder vb = buffer.getBuffer(RenderType.getSolid());
|
||||
|
||||
SuperByteBuffer superBuffer = AllBlockPartials.SHAFTLESS_COGWHEEL.renderOn(blockState);
|
||||
standardKineticRotationTransform(superBuffer, te, light).renderInto(ms, vb);
|
||||
if (!FastRenderDispatcher.available()) {
|
||||
SuperByteBuffer superBuffer = AllBlockPartials.SHAFTLESS_COGWHEEL.renderOn(blockState);
|
||||
standardKineticRotationTransform(superBuffer, te, light).renderInto(ms, vb);
|
||||
}
|
||||
|
||||
int packedLightmapCoords = WorldRenderer.getLightmapCoordinates(te.getWorld(), blockState, pos);
|
||||
float renderedHeadOffset = mixer.getRenderedHeadOffset(partialTicks);
|
||||
|
@ -8,6 +8,8 @@ import com.simibubi.create.CreateClient;
|
||||
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
||||
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
||||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
import com.simibubi.create.foundation.render.FastRenderDispatcher;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringRenderer;
|
||||
import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer;
|
||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||
@ -42,6 +44,9 @@ public class SawRenderer extends SafeTileEntityRenderer<SawTileEntity> {
|
||||
renderBlade(te, ms, buffer, light);
|
||||
renderItems(te, partialTicks, ms, buffer, light, overlay);
|
||||
FilteringRenderer.renderOnTileEntity(te, partialTicks, ms, buffer, light, overlay);
|
||||
|
||||
if (FastRenderDispatcher.available()) return;
|
||||
|
||||
renderShaft(te, ms, buffer, light, overlay);
|
||||
}
|
||||
|
||||
|
@ -143,4 +143,8 @@ public abstract class BasinOperatingTileEntity extends KineticTileEntity {
|
||||
|
||||
protected abstract Object getRecipeCacheKey();
|
||||
|
||||
@Override
|
||||
public boolean shouldRenderAsTE() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,14 @@
|
||||
package com.simibubi.create.content.contraptions.relays.advanced;
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import com.simibubi.create.CreateClient;
|
||||
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
|
||||
import com.simibubi.create.foundation.render.instancing.InstancedModel;
|
||||
import com.simibubi.create.foundation.render.instancing.RotatingData;
|
||||
import com.simibubi.create.foundation.render.FastRenderDispatcher;
|
||||
import com.simibubi.create.foundation.tileEntity.renderer.SmartTileEntityRenderer;
|
||||
import com.simibubi.create.foundation.render.SuperByteBuffer;
|
||||
|
||||
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
|
||||
|
||||
public class SpeedControllerRenderer extends SmartTileEntityRenderer<SpeedControllerTileEntity> {
|
||||
@ -18,7 +21,17 @@ public class SpeedControllerRenderer extends SmartTileEntityRenderer<SpeedContro
|
||||
protected void renderSafe(SpeedControllerTileEntity tileEntityIn, float partialTicks, MatrixStack ms,
|
||||
IRenderTypeBuffer buffer, int light, int overlay) {
|
||||
super.renderSafe(tileEntityIn, partialTicks, ms, buffer, light, overlay);
|
||||
// addInstanceData(new InstanceContext.World<>(tileEntityIn));
|
||||
|
||||
if (FastRenderDispatcher.available()) return;
|
||||
|
||||
KineticTileEntityRenderer.renderRotatingBuffer(tileEntityIn, getRotatedModel(tileEntityIn), ms,
|
||||
buffer.getBuffer(RenderType.getSolid()), light);
|
||||
}
|
||||
|
||||
private SuperByteBuffer getRotatedModel(SpeedControllerTileEntity te) {
|
||||
return CreateClient.bufferCache.renderBlockIn(KineticTileEntityRenderer.KINETIC_TILE,
|
||||
KineticTileEntityRenderer.shaft(KineticTileEntityRenderer.getRotationAxisOf(te)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -9,11 +9,9 @@ import com.simibubi.create.CreateClient;
|
||||
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
|
||||
import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack;
|
||||
import com.simibubi.create.foundation.block.render.SpriteShiftEntry;
|
||||
import com.simibubi.create.foundation.render.FastRenderDispatcher;
|
||||
import com.simibubi.create.foundation.render.ShadowRenderHelper;
|
||||
import com.simibubi.create.foundation.render.SuperByteBuffer;
|
||||
import com.simibubi.create.foundation.render.instancing.BeltData;
|
||||
import com.simibubi.create.foundation.render.instancing.InstancedModel;
|
||||
import com.simibubi.create.foundation.render.instancing.RotatingData;
|
||||
import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer;
|
||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||
@ -34,10 +32,8 @@ import net.minecraft.util.Direction.AxisDirection;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
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> {
|
||||
|
||||
@ -54,96 +50,89 @@ public class BeltRenderer extends SafeTileEntityRenderer<BeltTileEntity> {
|
||||
protected void renderSafe(BeltTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer,
|
||||
int light, int overlay) {
|
||||
|
||||
BlockState blockState = te.getBlockState();
|
||||
if (!AllBlocks.BELT.has(blockState))
|
||||
return;
|
||||
if (!FastRenderDispatcher.available()) {
|
||||
|
||||
BeltSlope beltSlope = blockState.get(BeltBlock.SLOPE);
|
||||
BeltPart part = blockState.get(BeltBlock.PART);
|
||||
Direction facing = blockState.get(BeltBlock.HORIZONTAL_FACING);
|
||||
AxisDirection axisDirection = facing.getAxisDirection();
|
||||
BlockState blockState = te.getBlockState();
|
||||
if (!AllBlocks.BELT.has(blockState)) return;
|
||||
|
||||
boolean downward = beltSlope == BeltSlope.DOWNWARD;
|
||||
boolean upward = beltSlope == BeltSlope.UPWARD;
|
||||
boolean diagonal = downward || upward;
|
||||
boolean start = part == BeltPart.START;
|
||||
boolean end = part == BeltPart.END;
|
||||
boolean sideways = beltSlope == BeltSlope.SIDEWAYS;
|
||||
boolean alongX = facing.getAxis() == Axis.X;
|
||||
BeltSlope beltSlope = blockState.get(BeltBlock.SLOPE);
|
||||
BeltPart part = blockState.get(BeltBlock.PART);
|
||||
Direction facing = blockState.get(BeltBlock.HORIZONTAL_FACING);
|
||||
AxisDirection axisDirection = facing.getAxisDirection();
|
||||
|
||||
MatrixStacker msr = MatrixStacker.of(ms);
|
||||
IVertexBuilder vb = buffer.getBuffer(RenderType.getSolid());
|
||||
float renderTick = AnimationTickHolder.getRenderTick();
|
||||
boolean downward = beltSlope == BeltSlope.DOWNWARD;
|
||||
boolean upward = beltSlope == BeltSlope.UPWARD;
|
||||
boolean diagonal = downward || upward;
|
||||
boolean start = part == BeltPart.START;
|
||||
boolean end = part == BeltPart.END;
|
||||
boolean sideways = beltSlope == BeltSlope.SIDEWAYS;
|
||||
boolean alongX = facing.getAxis() == Axis.X;
|
||||
|
||||
ms.push();
|
||||
msr.centre();
|
||||
msr.rotateY(AngleHelper.horizontalAngle(facing) + (upward ? 180 : 0) + (sideways ? 270 : 0));
|
||||
msr.rotateZ(sideways ? 90 : 0);
|
||||
msr.rotateX(!diagonal && beltSlope != BeltSlope.HORIZONTAL ? 90 : 0);
|
||||
msr.unCentre();
|
||||
MatrixStacker msr = MatrixStacker.of(ms);
|
||||
IVertexBuilder vb = buffer.getBuffer(RenderType.getSolid());
|
||||
float renderTick = AnimationTickHolder.getRenderTick();
|
||||
|
||||
if (downward || beltSlope == BeltSlope.VERTICAL && axisDirection == AxisDirection.POSITIVE) {
|
||||
boolean b = start;
|
||||
start = end;
|
||||
end = b;
|
||||
}
|
||||
|
||||
for (boolean bottom : Iterate.trueAndFalse) {
|
||||
|
||||
AllBlockPartials beltPartial = getBeltPartial(diagonal, start, end, bottom);
|
||||
|
||||
SuperByteBuffer beltBuffer = beltPartial.renderOn(blockState)
|
||||
.light(light);
|
||||
|
||||
SpriteShiftEntry spriteShift = getSpriteShiftEntry(diagonal, bottom);
|
||||
|
||||
// UV shift
|
||||
float speed = te.getSpeed();
|
||||
if (speed != 0) {
|
||||
float time = renderTick * axisDirection.getOffset();
|
||||
if (diagonal && (downward ^ alongX) || !sideways && !diagonal && alongX
|
||||
|| sideways && axisDirection == AxisDirection.NEGATIVE)
|
||||
speed = -speed;
|
||||
|
||||
float scrollMult = diagonal ? 3f / 8f : 0.5f;
|
||||
|
||||
float spriteSize = spriteShift.getTarget().getMaxV() - spriteShift.getTarget().getMinV();
|
||||
|
||||
double scroll = speed * time / (36 * 16);
|
||||
scroll = scroll - Math.floor(scroll);
|
||||
scroll = scroll * spriteSize * scrollMult;
|
||||
|
||||
beltBuffer.shiftUVScrolling(spriteShift, (float) scroll);
|
||||
}
|
||||
|
||||
beltBuffer.renderInto(ms, vb);
|
||||
|
||||
// Diagonal belt do not have a separate bottom model
|
||||
if (diagonal)
|
||||
break;
|
||||
}
|
||||
ms.pop();
|
||||
|
||||
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;
|
||||
msr = MatrixStacker.of(modelTransform);
|
||||
ms.push();
|
||||
msr.centre();
|
||||
if (dir.getAxis() == Axis.X)
|
||||
msr.rotateY(90);
|
||||
if (dir.getAxis() == Axis.Y)
|
||||
msr.rotateX(90);
|
||||
msr.rotateX(90);
|
||||
msr.rotateY(AngleHelper.horizontalAngle(facing) + (upward ? 180 : 0) + (sideways ? 270 : 0));
|
||||
msr.rotateZ(sideways ? 90 : 0);
|
||||
msr.rotateX(!diagonal && beltSlope != BeltSlope.HORIZONTAL ? 90 : 0);
|
||||
msr.unCentre();
|
||||
|
||||
SuperByteBuffer superBuffer = CreateClient.bufferCache
|
||||
.renderDirectionalPartial(AllBlockPartials.BELT_PULLEY, blockState, dir, modelTransform);
|
||||
KineticTileEntityRenderer.standardKineticRotationTransform(superBuffer, te, light)
|
||||
.renderInto(ms, vb);
|
||||
if (downward || beltSlope == BeltSlope.VERTICAL && axisDirection == AxisDirection.POSITIVE) {
|
||||
boolean b = start;
|
||||
start = end;
|
||||
end = b;
|
||||
}
|
||||
|
||||
for (boolean bottom : Iterate.trueAndFalse) {
|
||||
|
||||
AllBlockPartials beltPartial = getBeltPartial(diagonal, start, end, bottom);
|
||||
|
||||
SuperByteBuffer beltBuffer = beltPartial.renderOn(blockState).light(light);
|
||||
|
||||
SpriteShiftEntry spriteShift = getSpriteShiftEntry(diagonal, bottom);
|
||||
|
||||
// UV shift
|
||||
float speed = te.getSpeed();
|
||||
if (speed != 0) {
|
||||
float time = renderTick * axisDirection.getOffset();
|
||||
if (diagonal && (downward ^ alongX) || !sideways && !diagonal && alongX || sideways && axisDirection == AxisDirection.NEGATIVE)
|
||||
speed = -speed;
|
||||
|
||||
float scrollMult = diagonal ? 3f / 8f : 0.5f;
|
||||
|
||||
float spriteSize = spriteShift.getTarget().getMaxV() - spriteShift.getTarget().getMinV();
|
||||
|
||||
double scroll = speed * time / (36 * 16);
|
||||
scroll = scroll - Math.floor(scroll);
|
||||
scroll = scroll * spriteSize * scrollMult;
|
||||
|
||||
beltBuffer.shiftUVScrolling(spriteShift, (float) scroll);
|
||||
}
|
||||
|
||||
beltBuffer.renderInto(ms, vb);
|
||||
|
||||
// Diagonal belt do not have a separate bottom model
|
||||
if (diagonal) break;
|
||||
}
|
||||
ms.pop();
|
||||
|
||||
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;
|
||||
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();
|
||||
|
||||
SuperByteBuffer superBuffer = CreateClient.bufferCache.renderDirectionalPartial(AllBlockPartials.BELT_PULLEY, blockState, dir, modelTransform);
|
||||
KineticTileEntityRenderer.standardKineticRotationTransform(superBuffer, te, light).renderInto(ms, vb);
|
||||
}
|
||||
}
|
||||
|
||||
renderItems(te, partialTicks, ms, buffer, light, overlay);
|
||||
|
@ -5,6 +5,7 @@ import com.simibubi.create.AllBlockPartials;
|
||||
import com.simibubi.create.content.contraptions.base.IRotate;
|
||||
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
||||
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
|
||||
import com.simibubi.create.foundation.render.FastRenderDispatcher;
|
||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import com.simibubi.create.foundation.render.SuperByteBuffer;
|
||||
@ -16,6 +17,7 @@ import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.Direction.Axis;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import sun.nio.cs.FastCharsetProvider;
|
||||
|
||||
public class SplitShaftRenderer extends KineticTileEntityRenderer {
|
||||
|
||||
@ -26,6 +28,8 @@ public class SplitShaftRenderer extends KineticTileEntityRenderer {
|
||||
@Override
|
||||
protected void renderSafe(KineticTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer,
|
||||
int light, int overlay) {
|
||||
if (FastRenderDispatcher.available()) return;
|
||||
|
||||
Block block = te.getBlockState().getBlock();
|
||||
final Axis boxAxis = ((IRotate) block).getRotationAxis(te.getBlockState());
|
||||
final BlockPos pos = te.getPos();
|
||||
|
@ -4,6 +4,7 @@ import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import com.simibubi.create.AllBlockPartials;
|
||||
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
||||
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
|
||||
import com.simibubi.create.foundation.render.FastRenderDispatcher;
|
||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import com.simibubi.create.foundation.render.SuperByteBuffer;
|
||||
@ -25,6 +26,8 @@ public class GearboxRenderer extends KineticTileEntityRenderer {
|
||||
@Override
|
||||
protected void renderSafe(KineticTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer,
|
||||
int light, int overlay) {
|
||||
if (FastRenderDispatcher.available()) return;
|
||||
|
||||
final Axis boxAxis = te.getBlockState().get(BlockStateProperties.AXIS);
|
||||
final BlockPos pos = te.getPos();
|
||||
float time = AnimationTickHolder.getRenderTick();
|
||||
|
@ -13,6 +13,7 @@ public class AllCommands {
|
||||
.then(ToggleDebugCommand.register())
|
||||
.then(OverlayConfigCommand.register())
|
||||
.then(FixLightingCommand.register())
|
||||
.then(ToggleExperimentalRenderingCommand.register())
|
||||
|
||||
//dev-util
|
||||
//Comment out for release
|
||||
|
@ -3,6 +3,9 @@ package com.simibubi.create.foundation.command;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.simibubi.create.foundation.render.FastRenderDispatcher;
|
||||
import com.simibubi.create.foundation.render.gl.backend.Backend;
|
||||
import javafx.scene.layout.Background;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
|
||||
import com.simibubi.create.content.contraptions.goggles.GoggleConfigScreen;
|
||||
@ -61,6 +64,7 @@ public class ConfigureConfigPacket extends SimplePacketBase {
|
||||
overlayScreen(() -> Actions::overlayScreen),
|
||||
fixLighting(() -> Actions::experimentalLighting),
|
||||
overlayReset(() -> Actions::overlayReset),
|
||||
experimentalRendering(() -> Actions::experimentalRendering),
|
||||
|
||||
;
|
||||
|
||||
@ -79,6 +83,17 @@ public class ConfigureConfigPacket extends SimplePacketBase {
|
||||
private static void rainbowDebug(String value) {
|
||||
AllConfigs.CLIENT.rainbowDebug.set(Boolean.parseBoolean(value));
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
private static void experimentalRendering(String value) {
|
||||
boolean last = AllConfigs.CLIENT.experimentalRendering.get();
|
||||
AllConfigs.CLIENT.experimentalRendering.set(Boolean.parseBoolean(value));
|
||||
Backend.refreshAvailability();
|
||||
|
||||
if (last != AllConfigs.CLIENT.experimentalRendering.get()) {
|
||||
FastRenderDispatcher.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
private static void overlayReset(String value) {
|
||||
|
@ -0,0 +1,35 @@
|
||||
package com.simibubi.create.foundation.command;
|
||||
|
||||
import com.mojang.brigadier.arguments.BoolArgumentType;
|
||||
import com.mojang.brigadier.builder.ArgumentBuilder;
|
||||
import com.simibubi.create.foundation.networking.AllPackets;
|
||||
import net.minecraft.command.CommandSource;
|
||||
import net.minecraft.command.Commands;
|
||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||
import net.minecraft.util.text.StringTextComponent;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.fml.DistExecutor;
|
||||
import net.minecraftforge.fml.network.PacketDistributor;
|
||||
|
||||
public class ToggleExperimentalRenderingCommand {
|
||||
|
||||
static ArgumentBuilder<CommandSource, ?> register() {
|
||||
return Commands.literal("experimentalRendering")
|
||||
.requires(cs -> cs.hasPermissionLevel(0))
|
||||
.then(Commands.argument("value", BoolArgumentType.bool())
|
||||
.executes(ctx -> {
|
||||
boolean value = BoolArgumentType.getBool(ctx, "value");
|
||||
//DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> AllConfigs.CLIENT.rainbowDebug.set(value));
|
||||
DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> ConfigureConfigPacket.Actions.experimentalRendering.performAction(String.valueOf(value)));
|
||||
|
||||
DistExecutor.runWhenOn(Dist.DEDICATED_SERVER, () -> () ->
|
||||
AllPackets.channel.send(
|
||||
PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) ctx.getSource().getEntity()),
|
||||
new ConfigureConfigPacket(ConfigureConfigPacket.Actions.experimentalRendering.name(), String.valueOf(value))));
|
||||
|
||||
ctx.getSource().sendFeedback(new StringTextComponent((value ? "enabled" : "disabled") + " experimental rendering"), true);
|
||||
|
||||
return 1;
|
||||
}));
|
||||
}
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
package com.simibubi.create.foundation.config;
|
||||
|
||||
import com.simibubi.create.foundation.render.gl.backend.Backend;
|
||||
|
||||
public class CClient extends ConfigBase {
|
||||
|
||||
public ConfigGroup client = group(0, "client",
|
||||
@ -13,6 +15,9 @@ public class CClient extends ConfigBase {
|
||||
public ConfigBool rainbowDebug =
|
||||
b(true, "enableRainbowDebug", "Show colourful debug information while the F3-Menu is open.");
|
||||
|
||||
public ConfigRender experimentalRendering =
|
||||
new ConfigRender("experimentalRendering", true, "Use modern OpenGL features to drastically increase performance.");
|
||||
|
||||
public ConfigInt overlayOffsetX = i(20, Integer.MIN_VALUE, Integer.MAX_VALUE, "overlayOffsetX", "Offset the overlay from goggle- and hover- information by this many pixels on the X axis; Use /create overlay");
|
||||
public ConfigInt overlayOffsetY = i(0, Integer.MIN_VALUE, Integer.MAX_VALUE, "overlayOffsetY", "Offset the overlay from goggle- and hover- information by this many pixels on the Y axis; Use /create overlay");
|
||||
|
||||
@ -21,4 +26,32 @@ public class CClient extends ConfigBase {
|
||||
return "client";
|
||||
}
|
||||
|
||||
public class ConfigRender extends ConfigBool {
|
||||
|
||||
public ConfigRender(String name, boolean def, String... comment) {
|
||||
super(name, def, comment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the configured value and checks if the rendering is actually supported.
|
||||
* @return True if fast rendering is enabled and the current system/configuration is capable.
|
||||
*/
|
||||
@Override
|
||||
public Boolean get() {
|
||||
boolean enabled = super.get();
|
||||
|
||||
if (enabled) {
|
||||
switch (Backend.getAvailability()) {
|
||||
case FULL:
|
||||
case PARTIAL:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.simibubi.create.foundation.mixin;
|
||||
|
||||
import com.simibubi.create.foundation.render.FastRenderDispatcher;
|
||||
import com.simibubi.create.foundation.render.instancing.IInstanceRendered;
|
||||
import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
@ -25,8 +26,10 @@ public class CancelTileEntityRenderMixin {
|
||||
*/
|
||||
@Inject(at = @At("RETURN"), method = "getTileEntities", cancellable = true)
|
||||
private void noRenderInstancedTiles(CallbackInfoReturnable<List<TileEntity>> cir) {
|
||||
// List<TileEntity> tiles = cir.getReturnValue();
|
||||
//
|
||||
// tiles.removeIf(tile -> tile instanceof IInstanceRendered && !((IInstanceRendered) tile).shouldRenderAsTE());
|
||||
if (FastRenderDispatcher.available()) {
|
||||
List<TileEntity> tiles = cir.getReturnValue();
|
||||
|
||||
tiles.removeIf(tile -> tile instanceof IInstanceRendered && !((IInstanceRendered) tile).shouldRenderAsTE());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,12 +3,12 @@ package com.simibubi.create.foundation.render;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.foundation.render.contraption.ContraptionProgram;
|
||||
import com.simibubi.create.foundation.render.gl.BasicProgram;
|
||||
import com.simibubi.create.foundation.render.gl.backend.Backend;
|
||||
import com.simibubi.create.foundation.render.gl.shader.GlProgram;
|
||||
import com.simibubi.create.foundation.render.gl.shader.ProgramSpec;
|
||||
import com.simibubi.create.foundation.render.gl.shader.ShaderConstants;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
import static com.simibubi.create.foundation.render.gl.shader.ShaderHelper.register;
|
||||
|
||||
public class AllProgramSpecs {
|
||||
public static final ProgramSpec<BasicProgram> ROTATING = register(new ProgramSpec<>("rotating", Locations.ROTATING, Locations.INSTANCED, BasicProgram::new));
|
||||
public static final ProgramSpec<BasicProgram> BELT = register(new ProgramSpec<>("belt", Locations.BELT, Locations.INSTANCED, BasicProgram::new));
|
||||
@ -17,6 +17,10 @@ public class AllProgramSpecs {
|
||||
public static final ProgramSpec<ContraptionProgram> CONTRAPTION_BELT = register(new ProgramSpec<>("contraption_belt", Locations.BELT, Locations.CONTRAPTION, ContraptionProgram::new, ShaderConstants.define("CONTRAPTION")));
|
||||
public static final ProgramSpec<ContraptionProgram> CONTRAPTION_ACTOR = register(new ProgramSpec<>("contraption_actor", Locations.CONTRAPTION_ACTOR, Locations.CONTRAPTION, ContraptionProgram::new));
|
||||
|
||||
private static <P extends GlProgram, S extends ProgramSpec<P>> S register(S spec) {
|
||||
return Backend.register(spec);
|
||||
}
|
||||
|
||||
public static class Locations {
|
||||
public static final ResourceLocation INSTANCED = loc("instanced.frag");
|
||||
public static final ResourceLocation CONTRAPTION = loc("contraption.frag");
|
||||
|
@ -3,9 +3,8 @@ 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.config.AllConfigs;
|
||||
import com.simibubi.create.foundation.render.contraption.ContraptionRenderDispatcher;
|
||||
import com.simibubi.create.foundation.render.gl.shader.ShaderHelper;
|
||||
import com.simibubi.create.foundation.render.instancing.TileEntityInstance;
|
||||
import com.simibubi.create.foundation.render.light.ILightListener;
|
||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||
import com.simibubi.create.foundation.utility.WorldAttached;
|
||||
@ -25,6 +24,7 @@ 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.GL20;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
@ -56,18 +56,36 @@ public class FastRenderDispatcher {
|
||||
runQueue(queuedUpdates.get(world), CreateClient.kineticRenderer::update);
|
||||
}
|
||||
|
||||
public static boolean available() {
|
||||
return AllConfigs.CLIENT.experimentalRendering.get();
|
||||
}
|
||||
|
||||
public static void refresh() {
|
||||
RenderWork.enqueue(() -> {
|
||||
CreateClient.kineticRenderer.invalidate();
|
||||
Minecraft.getInstance().worldRenderer.loadRenderers();
|
||||
ClientWorld world = Minecraft.getInstance().world;
|
||||
if (world != null) world.loadedTileEntityList.forEach(CreateClient.kineticRenderer::add);
|
||||
});
|
||||
}
|
||||
|
||||
private static <T> void runQueue(@Nullable ConcurrentHashMap.KeySetView<T, Boolean> changed, Consumer<T> action) {
|
||||
if (changed == null) return;
|
||||
|
||||
// because of potential concurrency issues, we make a copy of what's in the set at the time we get here
|
||||
ArrayList<T> tiles = new ArrayList<>(changed);
|
||||
if (available()) {
|
||||
// because of potential concurrency issues, we make a copy of what's in the set at the time we get here
|
||||
ArrayList<T> tiles = new ArrayList<>(changed);
|
||||
|
||||
tiles.forEach(action);
|
||||
|
||||
changed.removeAll(tiles);
|
||||
tiles.forEach(action);
|
||||
changed.removeAll(tiles);
|
||||
} else {
|
||||
changed.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public static void renderLayer(RenderType type, MatrixStack stack, double cameraX, double cameraY, double cameraZ) {
|
||||
if (!available()) return;
|
||||
|
||||
Matrix4f viewProjection = Matrix4f.translate((float) -cameraX, (float) -cameraY, (float) -cameraZ);
|
||||
viewProjection.multiplyBackward(stack.peek().getModel());
|
||||
viewProjection.multiplyBackward(getProjectionMatrix());
|
||||
@ -82,7 +100,7 @@ public class FastRenderDispatcher {
|
||||
//RenderSystem.disableDepthTest();
|
||||
|
||||
ContraptionRenderDispatcher.renderLayer(type, viewProjection);
|
||||
ShaderHelper.releaseShader();
|
||||
GL20.glUseProgram(0);
|
||||
type.endDrawing();
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,57 @@
|
||||
package com.simibubi.create.foundation.render;
|
||||
|
||||
import com.simibubi.create.foundation.render.gl.backend.Backend;
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Optional;
|
||||
|
||||
public class OptifineHandler {
|
||||
private static Package optifine;
|
||||
private static OptifineHandler handler;
|
||||
|
||||
public final boolean usingShaders;
|
||||
|
||||
public OptifineHandler(boolean usingShaders) {
|
||||
this.usingShaders = usingShaders;
|
||||
}
|
||||
|
||||
public static Optional<OptifineHandler> get() {
|
||||
return Optional.ofNullable(handler);
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
optifine = Package.getPackage("net.optifine");
|
||||
|
||||
if (optifine == null) {
|
||||
Backend.log.info("Optifine not detected.");
|
||||
} else {
|
||||
Backend.log.info("Optifine detected.");
|
||||
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
|
||||
public static void refresh() {
|
||||
if (optifine == null) return;
|
||||
|
||||
File dir = Minecraft.getInstance().gameDir;
|
||||
|
||||
File shaderOptions = new File(dir, "optionsshaders.txt");
|
||||
|
||||
boolean shadersOff = true;
|
||||
try {
|
||||
BufferedReader reader = new BufferedReader(new FileReader(shaderOptions));
|
||||
|
||||
shadersOff = reader.lines().anyMatch(it -> it.replaceAll("\\s", "").equals("shaderPack=OFF"));
|
||||
} catch (FileNotFoundException e) {
|
||||
Backend.log.info("No shader config found.");
|
||||
}
|
||||
|
||||
handler = new OptifineHandler(!shadersOff);
|
||||
}
|
||||
|
||||
public boolean isUsingShaders() {
|
||||
return usingShaders;
|
||||
}
|
||||
}
|
@ -6,8 +6,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Abs
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionHandler;
|
||||
import com.simibubi.create.foundation.render.AllProgramSpecs;
|
||||
import com.simibubi.create.foundation.render.gl.shader.ShaderCallback;
|
||||
import com.simibubi.create.foundation.render.gl.shader.ShaderHelper;
|
||||
import com.simibubi.create.foundation.render.gl.backend.Backend;
|
||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.Matrix4f;
|
||||
@ -95,7 +94,7 @@ public class ContraptionRenderDispatcher {
|
||||
GL11.glEnable(GL13.GL_TEXTURE_3D);
|
||||
GL13.glActiveTexture(GL40.GL_TEXTURE4); // the shaders expect light volumes to be in texture 4
|
||||
|
||||
ContraptionProgram structureShader = ShaderHelper.getProgram(AllProgramSpecs.CONTRAPTION_STRUCTURE);
|
||||
ContraptionProgram structureShader = Backend.getProgram(AllProgramSpecs.CONTRAPTION_STRUCTURE);
|
||||
structureShader.bind(viewProjection, 0);
|
||||
for (RenderedContraption renderer : renderers.values()) {
|
||||
renderer.doRenderLayer(layer, structureShader);
|
||||
|
@ -1,7 +1,7 @@
|
||||
package com.simibubi.create.foundation.render.gl;
|
||||
|
||||
import com.simibubi.create.foundation.render.gl.backend.Backend;
|
||||
import com.simibubi.create.foundation.render.gl.shader.GlProgram;
|
||||
import com.simibubi.create.foundation.render.gl.shader.ShaderHelper;
|
||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||
import net.minecraft.client.renderer.Matrix4f;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
@ -43,9 +43,9 @@ public class BasicProgram extends GlProgram {
|
||||
}
|
||||
|
||||
protected static void uploadMatrixUniform(int uniform, Matrix4f mat) {
|
||||
ShaderHelper.MATRIX_BUFFER.position(0);
|
||||
mat.write(ShaderHelper.MATRIX_BUFFER);
|
||||
ShaderHelper.MATRIX_BUFFER.rewind();
|
||||
GL20.glUniformMatrix4fv(uniform, false, ShaderHelper.MATRIX_BUFFER);
|
||||
Backend.MATRIX_BUFFER.position(0);
|
||||
mat.write(Backend.MATRIX_BUFFER);
|
||||
Backend.MATRIX_BUFFER.rewind();
|
||||
GL20.glUniformMatrix4fv(uniform, false, Backend.MATRIX_BUFFER);
|
||||
}
|
||||
}
|
||||
|
@ -1,20 +1,179 @@
|
||||
package com.simibubi.create.foundation.render.gl.backend;
|
||||
|
||||
import com.simibubi.create.foundation.render.OptifineHandler;
|
||||
import com.simibubi.create.foundation.render.gl.shader.*;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.texture.TextureUtil;
|
||||
import net.minecraft.resources.IReloadableResourceManager;
|
||||
import net.minecraft.resources.IResourceManager;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.resource.IResourceType;
|
||||
import net.minecraftforge.resource.ISelectiveResourceReloadListener;
|
||||
import net.minecraftforge.resource.VanillaResourceType;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.lwjgl.opengl.GL;
|
||||
import org.lwjgl.opengl.GLCapabilities;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class Backend {
|
||||
private static final MapBuffer MAP_BUFFER = MapBuffer.GL30_RANGE;
|
||||
public static final Logger log = LogManager.getLogger(Backend.class);
|
||||
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);
|
||||
|
||||
private Backend() {
|
||||
throw new UnsupportedOperationException();
|
||||
private static final Backend instance = new Backend();
|
||||
public static Backend instance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private static final Map<ResourceLocation, ProgramSpec<?>> registry = new HashMap<>();
|
||||
private static final Map<ProgramSpec<?>, GlProgram> programs = new HashMap<>();
|
||||
|
||||
public static GLCapabilities capabilities;
|
||||
private static RenderingAvailability availability;
|
||||
private static MapBuffer mapBuffer;
|
||||
|
||||
|
||||
|
||||
public static void mapBuffer(int target, int offset, int length, Consumer<ByteBuffer> upload) {
|
||||
MAP_BUFFER.mapBuffer(target, offset, length, upload);
|
||||
mapBuffer.mapBuffer(target, offset, length, upload);
|
||||
}
|
||||
|
||||
public static void mapBuffer(int target, int size, Consumer<ByteBuffer> upload) {
|
||||
MAP_BUFFER.mapBuffer(target, 0, size, upload);
|
||||
mapBuffer.mapBuffer(target, 0, size, upload);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a shader program. TODO: replace with forge registry?
|
||||
*/
|
||||
public static <P extends GlProgram, S extends ProgramSpec<P>> S register(S spec) {
|
||||
ResourceLocation name = spec.name;
|
||||
if (registry.containsKey(name)) {
|
||||
throw new IllegalStateException("Program spec '" + name + "' already registered.");
|
||||
}
|
||||
registry.put(name, spec);
|
||||
return spec;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <P extends GlProgram, S extends ProgramSpec<P>> P getProgram(S spec) {
|
||||
return (P) programs.get(spec);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the most compatible version of a specific OpenGL feature by iterating over enum constants in order.
|
||||
*
|
||||
* @param clazz The class of the versioning enum.
|
||||
* @param <V> The type of the versioning enum.
|
||||
* @return The first defined enum variant to return true.
|
||||
*/
|
||||
public static <V extends Enum<V> & GlVersioned> V getLatest(Class<V> clazz) {
|
||||
return getLatest(clazz, capabilities);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the most compatible version of a specific OpenGL feature by iterating over enum constants in order.
|
||||
*
|
||||
* @param clazz The class of the versioning enum.
|
||||
* @param caps The current system's supported features.
|
||||
* @param <V> The type of the versioning enum.
|
||||
* @return The first defined enum variant to return true.
|
||||
*/
|
||||
public static <V extends Enum<V> & GlVersioned> V getLatest(Class<V> clazz, GLCapabilities caps) {
|
||||
V[] constants = clazz.getEnumConstants();
|
||||
V last = constants[constants.length - 1];
|
||||
if (!last.supported(caps)) {
|
||||
throw new IllegalStateException("");
|
||||
}
|
||||
|
||||
return Arrays.stream(constants).filter(it -> it.supported(caps)).findFirst().orElse(last);
|
||||
}
|
||||
|
||||
public static RenderingAvailability getAvailability() {
|
||||
return availability;
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
// Can be null when running datagenerators due to the unfortunate time we call this
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
if (mc != null && mc.getResourceManager() instanceof IReloadableResourceManager) {
|
||||
ISelectiveResourceReloadListener listener = Backend::onResourceManagerReload;
|
||||
((IReloadableResourceManager) mc.getResourceManager()).addReloadListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
public static void onResourceManagerReload(IResourceManager manager, Predicate<IResourceType> predicate) {
|
||||
if (predicate.test(VanillaResourceType.SHADERS)) {
|
||||
capabilities = GL.createCapabilities();
|
||||
mapBuffer = getLatest(MapBuffer.class);
|
||||
|
||||
OptifineHandler.refresh();
|
||||
refreshAvailability();
|
||||
|
||||
programs.values().forEach(GlProgram::delete);
|
||||
programs.clear();
|
||||
for (ProgramSpec<?> shader : registry.values()) {
|
||||
loadProgram(manager, shader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static <P extends GlProgram, S extends ProgramSpec<P>> void loadProgram(IResourceManager manager, S programSpec) {
|
||||
GlShader vert = null;
|
||||
GlShader frag = null;
|
||||
try {
|
||||
vert = loadShader(manager, programSpec.getVert(), ShaderType.VERTEX, programSpec.defines);
|
||||
frag = loadShader(manager, programSpec.getFrag(), ShaderType.FRAGMENT, programSpec.defines);
|
||||
|
||||
P program = GlProgram.builder(programSpec.name)
|
||||
.attachShader(vert)
|
||||
.attachShader(frag)
|
||||
.build(programSpec.factory);
|
||||
|
||||
programs.put(programSpec, program);
|
||||
|
||||
log.info("Loaded program {}", programSpec.name);
|
||||
} catch (IOException ex) {
|
||||
log.error("Failed to load program {}", programSpec.name, ex);
|
||||
} finally {
|
||||
if (vert != null) vert.delete();
|
||||
if (frag != null) frag.delete();
|
||||
}
|
||||
}
|
||||
|
||||
private static GlShader loadShader(IResourceManager manager, ResourceLocation name, ShaderType type, GlShader.PreProcessor preProcessor) throws IOException {
|
||||
try (InputStream is = new BufferedInputStream(manager.getResource(name).getInputStream())) {
|
||||
String source = TextureUtil.func_225687_b_(is);
|
||||
|
||||
if (source == null) {
|
||||
throw new IOException("Could not load program " + name);
|
||||
} else {
|
||||
return new GlShader(type, name, source, preProcessor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void refreshAvailability() {
|
||||
if (capabilities.OpenGL33) {
|
||||
availability = RenderingAvailability.FULL;
|
||||
|
||||
OptifineHandler.get()
|
||||
.filter(OptifineHandler::isUsingShaders)
|
||||
.ifPresent(it -> availability = RenderingAvailability.OPTIFINE_SHADERS);
|
||||
} else {
|
||||
availability = RenderingAvailability.INCAPABLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,8 @@
|
||||
package com.simibubi.create.foundation.render.gl.backend;
|
||||
|
||||
import org.lwjgl.opengl.GLCapabilities;
|
||||
|
||||
|
||||
public interface GlVersioned {
|
||||
boolean supported(GLCapabilities caps);
|
||||
}
|
@ -1,15 +1,19 @@
|
||||
package com.simibubi.create.foundation.render.gl.backend;
|
||||
|
||||
import org.lwjgl.opengl.ARBMapBufferRange;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
import org.lwjgl.opengl.*;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public enum MapBuffer {
|
||||
public enum MapBuffer implements GlVersioned {
|
||||
|
||||
GL30_RANGE {
|
||||
@Override
|
||||
public boolean supported(GLCapabilities caps) {
|
||||
return caps.OpenGL30;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mapBuffer(int target, int offset, int length, Consumer<ByteBuffer> upload) {
|
||||
ByteBuffer buffer = GL30.glMapBufferRange(target, offset, length, GL30.GL_MAP_WRITE_BIT | GL30.GL_MAP_INVALIDATE_RANGE_BIT);
|
||||
@ -21,6 +25,11 @@ public enum MapBuffer {
|
||||
}
|
||||
},
|
||||
ARB_RANGE {
|
||||
@Override
|
||||
public boolean supported(GLCapabilities caps) {
|
||||
return caps.GL_ARB_map_buffer_range;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mapBuffer(int target, int offset, int length, Consumer<ByteBuffer> upload) {
|
||||
ByteBuffer buffer = ARBMapBufferRange.glMapBufferRange(target, offset, length, GL30.GL_MAP_WRITE_BIT | GL30.GL_MAP_INVALIDATE_RANGE_BIT);
|
||||
@ -32,6 +41,11 @@ public enum MapBuffer {
|
||||
}
|
||||
},
|
||||
GL15_MAP {
|
||||
@Override
|
||||
public boolean supported(GLCapabilities caps) {
|
||||
return caps.OpenGL15;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mapBuffer(int target, int offset, int length, Consumer<ByteBuffer> upload) {
|
||||
ByteBuffer buffer = GL15.glMapBuffer(target, GL15.GL_WRITE_ONLY);
|
||||
@ -43,6 +57,11 @@ public enum MapBuffer {
|
||||
}
|
||||
},
|
||||
UNSUPPORTED {
|
||||
@Override
|
||||
public boolean supported(GLCapabilities caps) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mapBuffer(int target, int offset, int length, Consumer<ByteBuffer> upload) {
|
||||
throw new UnsupportedOperationException("glMapBuffer not supported");
|
||||
|
@ -0,0 +1,27 @@
|
||||
package com.simibubi.create.foundation.render.gl.backend;
|
||||
|
||||
public enum RenderingAvailability {
|
||||
/**
|
||||
* The current system does not support enough
|
||||
* OpenGL features to enable fast rendering.
|
||||
*/
|
||||
INCAPABLE,
|
||||
|
||||
/**
|
||||
* The current system supports OpenGL 3.3.
|
||||
*/
|
||||
FULL,
|
||||
|
||||
/**
|
||||
* The current system supports OpenGL 2.0,
|
||||
* or some ARBs that make it equivalent.
|
||||
*/
|
||||
PARTIAL,
|
||||
|
||||
/**
|
||||
* It doesn't matter what the current system
|
||||
* supports because Optifine is installed and
|
||||
* a shaderpack is enabled.
|
||||
*/
|
||||
OPTIFINE_SHADERS,
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package com.simibubi.create.foundation.render.gl.shader;
|
||||
|
||||
import com.simibubi.create.foundation.render.gl.GlObject;
|
||||
import com.simibubi.create.foundation.render.gl.backend.Backend;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
|
||||
@ -29,13 +30,12 @@ public abstract class GlProgram extends GlObject {
|
||||
* Retrieves the index of the uniform with the given name.
|
||||
* @param uniform The name of the uniform to find the index of
|
||||
* @return The uniform's index
|
||||
* @throws NullPointerException If no uniform exists with the given name
|
||||
*/
|
||||
public int getUniformLocation(String uniform) {
|
||||
int index = GL20.glGetUniformLocation(this.handle(), uniform);
|
||||
|
||||
if (index < 0) {
|
||||
ShaderHelper.log.error("No uniform exists in program '" + this.name + "' with name: " + uniform);
|
||||
Backend.log.warn("No active uniform '{}' exists in program '{}'. Could be unused.", uniform, this.name);
|
||||
}
|
||||
|
||||
return index;
|
||||
@ -93,7 +93,7 @@ public abstract class GlProgram extends GlObject {
|
||||
String log = GL20.glGetProgramInfoLog(this.program);
|
||||
|
||||
if (!log.isEmpty()) {
|
||||
ShaderHelper.log.warn("Program link log for " + this.name + ": " + log);
|
||||
Backend.log.warn("Program link log for " + this.name + ": " + log);
|
||||
}
|
||||
|
||||
int result = GL20.glGetProgrami(this.program, GL20.GL_LINK_STATUS);
|
||||
|
@ -1,8 +1,7 @@
|
||||
package com.simibubi.create.foundation.render.gl.shader;
|
||||
|
||||
import com.simibubi.create.foundation.render.gl.GlObject;
|
||||
import com.simibubi.create.foundation.render.gl.shader.ShaderHelper;
|
||||
import com.simibubi.create.foundation.render.gl.shader.ShaderType;
|
||||
import com.simibubi.create.foundation.render.gl.backend.Backend;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
|
||||
@ -18,7 +17,7 @@ public class GlShader extends GlObject {
|
||||
|
||||
if (preProcessor != null) {
|
||||
source = preProcessor.process(source);
|
||||
ShaderHelper.log.info("Preprocessor run on " + name + ":\n" + source);
|
||||
Backend.log.info("Preprocessor run on " + name);// + ":\n" + source);
|
||||
}
|
||||
|
||||
GL20.glShaderSource(handle, source);
|
||||
@ -27,7 +26,7 @@ public class GlShader extends GlObject {
|
||||
String log = GL20.glGetShaderInfoLog(handle);
|
||||
|
||||
if (!log.isEmpty()) {
|
||||
ShaderHelper.log.warn("Shader compilation log for " + name + ": " + log);
|
||||
Backend.log.warn("Shader compilation log for " + name + ": " + log);
|
||||
}
|
||||
|
||||
if (GL20.glGetShaderi(handle, GL20.GL_COMPILE_STATUS) != GL20.GL_TRUE) {
|
||||
|
@ -1,109 +0,0 @@
|
||||
package com.simibubi.create.foundation.render.gl.shader;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.simibubi.create.content.contraptions.KineticDebugger;
|
||||
import com.simibubi.create.foundation.render.gl.BasicProgram;
|
||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.Matrix4f;
|
||||
import net.minecraft.client.renderer.texture.TextureUtil;
|
||||
import net.minecraft.client.shader.ShaderLinkHelper;
|
||||
import net.minecraft.resources.IReloadableResourceManager;
|
||||
import net.minecraft.resources.IResourceManager;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.resource.ISelectiveResourceReloadListener;
|
||||
import net.minecraftforge.resource.VanillaResourceType;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ShaderHelper {
|
||||
|
||||
public static final Logger log = LogManager.getLogger(ShaderHelper.class);
|
||||
|
||||
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);
|
||||
|
||||
private static final Map<ResourceLocation, ProgramSpec<?>> REGISTRY = new HashMap<>();
|
||||
private static final Map<ProgramSpec<?>, GlProgram> PROGRAMS = new HashMap<>();
|
||||
|
||||
public static <P extends GlProgram, S extends ProgramSpec<P>> S register(S spec) {
|
||||
ResourceLocation name = spec.name;
|
||||
if (REGISTRY.containsKey(name)) {
|
||||
throw new IllegalStateException("Program spec '" + name + "' already registered.");
|
||||
}
|
||||
REGISTRY.put(name, spec);
|
||||
return spec;
|
||||
}
|
||||
|
||||
public static void initShaders() {
|
||||
// Can be null when running datagenerators due to the unfortunate time we call this
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
if (mc != null && mc.getResourceManager() instanceof IReloadableResourceManager) {
|
||||
ISelectiveResourceReloadListener listener = (manager, predicate) -> {
|
||||
if (predicate.test(VanillaResourceType.SHADERS)) {
|
||||
PROGRAMS.values().forEach(GlProgram::delete);
|
||||
PROGRAMS.clear();
|
||||
for (ProgramSpec<?> shader : REGISTRY.values()) {
|
||||
loadProgram(manager, shader);
|
||||
}
|
||||
}
|
||||
};
|
||||
((IReloadableResourceManager) mc.getResourceManager()).addReloadListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <P extends GlProgram, S extends ProgramSpec<P>> P getProgram(S spec) {
|
||||
return (P) PROGRAMS.get(spec);
|
||||
}
|
||||
|
||||
public static void releaseShader() {
|
||||
GL20.glUseProgram(0);
|
||||
}
|
||||
|
||||
private static <P extends GlProgram, S extends ProgramSpec<P>> void loadProgram(IResourceManager manager, S programSpec) {
|
||||
GlShader vert = null;
|
||||
GlShader frag = null;
|
||||
try {
|
||||
vert = loadShader(manager, programSpec.getVert(), ShaderType.VERTEX, programSpec.defines);
|
||||
frag = loadShader(manager, programSpec.getFrag(), ShaderType.FRAGMENT, programSpec.defines);
|
||||
|
||||
P program = GlProgram.builder(programSpec.name)
|
||||
.attachShader(vert)
|
||||
.attachShader(frag)
|
||||
.build(programSpec.factory);
|
||||
|
||||
PROGRAMS.put(programSpec, program);
|
||||
|
||||
log.info("Loaded program {}", programSpec.name);
|
||||
} catch (IOException ex) {
|
||||
log.error("Failed to load program {}", programSpec.name, ex);
|
||||
} finally {
|
||||
if (vert != null) vert.delete();
|
||||
if (frag != null) frag.delete();
|
||||
}
|
||||
}
|
||||
|
||||
private static GlShader loadShader(IResourceManager manager, ResourceLocation name, ShaderType type, GlShader.PreProcessor preProcessor) throws IOException {
|
||||
try (InputStream is = new BufferedInputStream(manager.getResource(name).getInputStream())) {
|
||||
String source = TextureUtil.func_225687_b_(is);
|
||||
|
||||
if (source == null) {
|
||||
throw new IOException("Could not load program " + name);
|
||||
} else {
|
||||
return new GlShader(type, name, source, preProcessor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -18,7 +18,7 @@ public class InstancedTileRenderRegistry {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
public <T extends TileEntity> TileEntityInstance<? super T> create(InstancedTileRenderer manager, T tile) {
|
||||
public <T extends TileEntity> TileEntityInstance<? super T> create(InstancedTileRenderer<?> manager, T tile) {
|
||||
TileEntityType<?> type = tile.getType();
|
||||
IRendererFactory<? super T> factory = (IRendererFactory<? super T>) this.renderers.get(type);
|
||||
|
||||
|
@ -3,11 +3,11 @@ package com.simibubi.create.foundation.render.instancing;
|
||||
import com.simibubi.create.foundation.render.FastRenderDispatcher;
|
||||
import com.simibubi.create.foundation.render.gl.BasicProgram;
|
||||
import com.simibubi.create.foundation.render.gl.shader.ShaderCallback;
|
||||
import com.simibubi.create.foundation.render.gl.shader.ShaderHelper;
|
||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||
import net.minecraft.client.renderer.Matrix4f;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.HashMap;
|
||||
@ -42,15 +42,14 @@ public abstract class InstancedTileRenderer<P extends BasicProgram> {
|
||||
if (instance != null) {
|
||||
return (TileEntityInstance<? super T>) instance;
|
||||
} else if (create) {
|
||||
return null;
|
||||
// TileEntityInstance<? super T> renderer = InstancedTileRenderRegistry.instance.create(this, tile);
|
||||
//
|
||||
// if (renderer != null) {
|
||||
// FastRenderDispatcher.addedLastTick.get(tile.getWorld()).add(tile);
|
||||
// instances.put(tile, renderer);
|
||||
// }
|
||||
//
|
||||
// return renderer;
|
||||
TileEntityInstance<? super T> renderer = InstancedTileRenderRegistry.instance.create(this, tile);
|
||||
|
||||
if (renderer != null) {
|
||||
FastRenderDispatcher.addedLastTick.get(tile.getWorld()).add(tile);
|
||||
instances.put(tile, renderer);
|
||||
}
|
||||
|
||||
return renderer;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@ -116,6 +115,6 @@ public abstract class InstancedTileRenderer<P extends BasicProgram> {
|
||||
material.render(layer, viewProjection, callback);
|
||||
}
|
||||
|
||||
ShaderHelper.releaseShader();
|
||||
GL20.glUseProgram(0);
|
||||
}
|
||||
}
|
||||
|
@ -8,9 +8,9 @@ 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.gl.BasicProgram;
|
||||
import com.simibubi.create.foundation.render.gl.backend.Backend;
|
||||
import com.simibubi.create.foundation.render.gl.shader.ProgramSpec;
|
||||
import com.simibubi.create.foundation.render.gl.shader.ShaderCallback;
|
||||
import com.simibubi.create.foundation.render.gl.shader.ShaderHelper;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.BlockRendererDispatcher;
|
||||
@ -63,7 +63,7 @@ public class RenderMaterial<P extends BasicProgram, MODEL extends InstancedModel
|
||||
}
|
||||
|
||||
public void render(RenderType layer, Matrix4f viewProjection, ShaderCallback<P> setup) {
|
||||
P program = ShaderHelper.getProgram(programSpec);
|
||||
P program = Backend.getProgram(programSpec);
|
||||
program.bind(viewProjection, 0);
|
||||
|
||||
if (setup != null) setup.call(program);
|
||||
|
@ -2,7 +2,6 @@ package com.simibubi.create.foundation.render.light;
|
||||
|
||||
import com.simibubi.create.foundation.render.RenderWork;
|
||||
import com.simibubi.create.foundation.render.gl.GlTexture;
|
||||
import com.simibubi.create.foundation.render.gl.shader.ShaderHelper;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.SectionPos;
|
||||
import net.minecraft.world.ILightReader;
|
||||
|
Loading…
Reference in New Issue
Block a user