some micro optimizations.

cache hot getters.
reduce number of calls to getBeltFacing() in BeltRenderer.
preserve floating point accuracy over (insanely) long play times.
rotate some normals and light some quads.
This commit is contained in:
JozsefA 2021-02-08 21:17:25 -08:00
parent ee9962b27b
commit cfff806df4
19 changed files with 109 additions and 83 deletions

View file

@ -11,7 +11,7 @@ import net.minecraft.util.Direction.Axis;
public abstract class AnimatedKinetics implements IDrawable {
public static float getCurrentAngle() {
return ((AnimationTickHolder.ticks + AnimationTickHolder.getPartialTicks()) * 4f) % 360;
return ((AnimationTickHolder.getRenderTick()) * 4f) % 360;
}
protected BlockState shaft(Axis axis) {

View file

@ -15,8 +15,6 @@ import net.minecraftforge.fluids.FluidStack;
import java.util.List;
import static com.simibubi.create.foundation.utility.AnimationTickHolder.ticks;
public class AnimatedSpout extends AnimatedKinetics {
private List<FluidStack> fluids;
@ -38,7 +36,7 @@ public class AnimatedSpout extends AnimatedKinetics {
.scale(scale)
.render();
float cycle = (ticks + AnimationTickHolder.getPartialTicks()) % 30;
float cycle = AnimationTickHolder.getRenderTick() % 30;
float squeeze = cycle < 20 ? MathHelper.sin((float) (cycle / 20f * Math.PI)) : 0;
squeeze *= 20;

View file

@ -26,7 +26,6 @@ import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.AxisDirection;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.World;
@ -463,11 +462,6 @@ public abstract class KineticTileEntity extends SmartTileEntity
return overStressed;
}
@Override
public AxisAlignedBB getRenderBoundingBox() {
return super.getRenderBoundingBox();
}
@Override
public double getMaxRenderDistanceSquared() {
return 16384.0D; // TODO: make this a config option

View file

@ -92,9 +92,9 @@ public class CuckooClockTileEntity extends KineticTileEntity {
moveHands(hours, minutes);
if (animationType == Animation.NONE) {
if (AnimationTickHolder.ticks % 32 == 0)
if (AnimationTickHolder.getTicks() % 32 == 0)
playSound(SoundEvents.BLOCK_NOTE_BLOCK_HAT, 1 / 16f, 2f);
else if (AnimationTickHolder.ticks % 16 == 0)
else if (AnimationTickHolder.getTicks() % 16 == 0)
playSound(SoundEvents.BLOCK_NOTE_BLOCK_HAT, 1 / 16f, 1.5f);
} else {

View file

@ -6,7 +6,6 @@ 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;
@ -178,7 +177,7 @@ public class MechanicalCrafterRenderer extends SafeTileEntityRenderer<Mechanical
renderAndTransform(te, AllBlockPartials.MECHANICAL_CRAFTER_BELT_FRAME, blockState, pos);
if (te.phase == Phase.EXPORTING) {
int textureIndex = (int) ((te.getCountDownSpeed() / 128f * AnimationTickHolder.ticks));
int textureIndex = (int) ((te.getCountDownSpeed() / 128f * AnimationTickHolder.getTicks()));
beltBuffer.shiftUVtoSheet(AllSpriteShifts.CRAFTER_THINGIES, (textureIndex % 4) / 4f, 0, 1);
}

View file

@ -5,7 +5,6 @@ import com.simibubi.create.content.contraptions.goggles.GogglesItem;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.ColorHelper;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.player.ClientPlayerEntity;
import net.minecraft.client.particle.IAnimatedSprite;
@ -67,7 +66,7 @@ public class RotationIndicatorParticle extends SimpleAnimatedParticle {
}
public void move(double x, double y, double z) {
float time = AnimationTickHolder.ticks;
float time = AnimationTickHolder.getTicks();
float angle = (float) ((time * speed) % 360) - (speed / 2 * age * (((float) age) / maxAge));
Vec3d position = VecHelper.rotate(this.offset.scale(radius), angle, axis).add(origin);
posX = position.x;

View file

@ -1,14 +1,5 @@
package com.simibubi.create.content.contraptions.processing;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.Random;
import javax.annotation.Nonnull;
import com.simibubi.create.AllParticleTypes;
import com.simibubi.create.AllTags;
import com.simibubi.create.content.contraptions.components.mixer.MechanicalMixerTileEntity;
@ -25,15 +16,8 @@ import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputB
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour;
import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour;
import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour.TankSegment;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.IntAttached;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.LerpedFloat;
import com.simibubi.create.foundation.utility.*;
import com.simibubi.create.foundation.utility.LerpedFloat.Chaser;
import com.simibubi.create.foundation.utility.NBTHelper;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.item.ItemStack;
@ -63,6 +47,9 @@ import net.minecraftforge.items.IItemHandlerModifiable;
import net.minecraftforge.items.ItemHandlerHelper;
import net.minecraftforge.items.wrapper.CombinedInvWrapper;
import javax.annotation.Nonnull;
import java.util.*;
public class BasinTileEntity extends SmartTileEntity {
private boolean areFluidsMoving;
@ -571,7 +558,7 @@ public class BasinTileEntity extends SmartTileEntity {
Vec3d pointer = new Vec3d(1, 0, 0).scale(1 / 16f);
float interval = 360f / segments;
Vec3d centerOf = VecHelper.getCenterOf(pos);
float intervalOffset = (AnimationTickHolder.ticks * 18) % 360;
float intervalOffset = (AnimationTickHolder.getTicks() * 18) % 360;
int currentSegment = 0;
for (SmartFluidTankBehaviour behaviour : getTanks()) {

View file

@ -170,16 +170,17 @@ public class BeltRenderer extends SafeTileEntityRenderer<BeltTileEntity> {
ms.push();
Vec3i directionVec = te.getBeltFacing()
.getDirectionVec();
Direction beltFacing = te.getBeltFacing();
Vec3i directionVec = beltFacing
.getDirectionVec();
Vec3d beltStartOffset = new Vec3d(directionVec).scale(-.5)
.add(.5, 13 / 16f + .125f, .5);
ms.translate(beltStartOffset.x, beltStartOffset.y, beltStartOffset.z);
BeltSlope slope = te.getBlockState()
.get(BeltBlock.SLOPE);
int verticality = slope == BeltSlope.DOWNWARD ? -1 : slope == BeltSlope.UPWARD ? 1 : 0;
boolean slopeAlongX = te.getBeltFacing()
.getAxis() == Axis.X;
boolean slopeAlongX = beltFacing
.getAxis() == Axis.X;
for (TransportedItemStack transported : te.getInventory()
.getTransportedItems()) {
@ -205,16 +206,16 @@ public class BeltRenderer extends SafeTileEntityRenderer<BeltTileEntity> {
.add(0, verticalMovement, 0);
boolean onSlope =
slope != BeltSlope.HORIZONTAL && MathHelper.clamp(offset, .5f, te.beltLength - .5f) == offset;
boolean tiltForward = (slope == BeltSlope.DOWNWARD ^ te.getBeltFacing()
.getAxisDirection() == AxisDirection.POSITIVE) == (te.getBeltFacing()
.getAxis() == Axis.Z);
boolean tiltForward = (slope == BeltSlope.DOWNWARD ^ beltFacing
.getAxisDirection() == AxisDirection.POSITIVE) == (beltFacing
.getAxis() == Axis.Z);
float slopeAngle = onSlope ? tiltForward ? -45 : 45 : 0;
ms.translate(offsetVec.x, offsetVec.y, offsetVec.z);
boolean alongX = te.getBeltFacing()
.rotateY()
.getAxis() == Axis.X;
boolean alongX = beltFacing
.rotateY()
.getAxis() == Axis.X;
if (!alongX)
sideOffset *= -1;
ms.translate(alongX ? sideOffset : 0, 0, alongX ? 0 : sideOffset);

View file

@ -63,8 +63,8 @@ public class BeltTileEntity extends KineticTileEntity {
public CompoundNBT trackerUpdateTag;
// client
public byte blockLight;
public byte skyLight;
public byte blockLight = -1;
public byte skyLight = -1;
public static enum CasingType {
NONE, ANDESITE, BRASS;
@ -137,11 +137,17 @@ public class BeltTileEntity extends KineticTileEntity {
return super.calculateStressApplied();
}
private AxisAlignedBB cachedBoundingBox;
@Override
public AxisAlignedBB getRenderBoundingBox() {
if (!isController())
return super.getRenderBoundingBox();
return super.getRenderBoundingBox().grow(beltLength + 1);
if (cachedBoundingBox == null) {
if (!isController())
cachedBoundingBox = super.getRenderBoundingBox();
else
cachedBoundingBox = super.getRenderBoundingBox().grow(beltLength + 1);
}
return cachedBoundingBox;
}
protected void initializeItemHandler() {
@ -261,6 +267,7 @@ public class BeltTileEntity extends KineticTileEntity {
public void setController(BlockPos controller) {
this.controller = controller;
cachedBoundingBox = null;
}
public BlockPos getController() {

View file

@ -48,7 +48,7 @@ public class SandPaperItemRenderer extends ItemStackTileEntityRenderer {
// Reverse bobbing
float time = (float) (!jeiMode ? player.getItemInUseCount()
: (-AnimationTickHolder.ticks) % stack.getUseDuration()) - partialTicks + 1.0F;
: (-AnimationTickHolder.getTicks()) % stack.getUseDuration()) - partialTicks + 1.0F;
if (time / (float) stack.getUseDuration() < 0.8F) {
float bobbing = -MathHelper.abs(MathHelper.cos(time / 4.0F * (float) Math.PI) * 0.1F);

View file

@ -6,12 +6,11 @@ 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.content.logistics.block.mechanicalArm.ArmTileEntity.Phase;
import com.simibubi.create.foundation.render.SuperByteBuffer;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.ColorHelper;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.MatrixStacker;
import com.simibubi.create.foundation.render.SuperByteBuffer;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.IRenderTypeBuffer;
@ -56,7 +55,7 @@ public class ArmRenderer extends KineticTileEntityRenderer {
lowerArmAngle = MathHelper.lerp((MathHelper.sin(renderTick / 4) + 1) / 2, -45, 15);
upperArmAngle = MathHelper.lerp((MathHelper.sin(renderTick / 8) + 1) / 4, -45, 95);
headAngle = -lowerArmAngle;
color = ColorHelper.rainbowColor(AnimationTickHolder.ticks * 100);
color = ColorHelper.rainbowColor(AnimationTickHolder.getTicks() * 100);
}
ms.push();

View file

@ -50,7 +50,6 @@ import net.minecraftforge.client.event.EntityViewRenderEvent;
import net.minecraftforge.client.event.RenderGameOverlayEvent;
import net.minecraftforge.client.event.RenderGameOverlayEvent.ElementType;
import net.minecraftforge.client.event.RenderWorldLastEvent;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.event.TickEvent.ClientTickEvent;
import net.minecraftforge.event.TickEvent.Phase;
import net.minecraftforge.event.TickEvent.RenderTickEvent;
@ -114,13 +113,13 @@ public class ClientEvents {
@SubscribeEvent
public static void onLoadWorld(WorldEvent.Load event) {
CreateClient.invalidateRenderers();
AnimationTickHolder.ticks = 0;
AnimationTickHolder.reset();
}
@SubscribeEvent
public static void onUnloadWorld(WorldEvent.Unload event) {
CreateClient.invalidateRenderers();
AnimationTickHolder.ticks = 0;
AnimationTickHolder.reset();
}
@SubscribeEvent

View file

@ -40,6 +40,12 @@ public class CClient extends ConfigBase {
public Boolean get() {
return super.get() && Backend.canUse();
}
@Override
public void set(Boolean value) {
super.set(value);
Backend.enabled = get();
}
}
}

View file

@ -3,7 +3,6 @@ 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.backend.Backend;
import com.simibubi.create.foundation.render.gl.backend.OptifineHandler;
@ -59,7 +58,7 @@ public class FastRenderDispatcher {
}
public static boolean available() {
return AllConfigs.CLIENT.experimentalRendering.get();
return Backend.enabled;
}
public static void refresh() {

View file

@ -1,24 +1,21 @@
package com.simibubi.create.foundation.render;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.util.function.Consumer;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.vertex.IVertexBuilder;
import com.simibubi.create.foundation.block.render.SpriteShiftEntry;
import it.unimi.dsi.fastutil.longs.Long2DoubleMap;
import it.unimi.dsi.fastutil.longs.Long2DoubleOpenHashMap;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.Matrix4f;
import net.minecraft.client.renderer.Vector4f;
import net.minecraft.client.renderer.*;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.LightType;
import net.minecraft.world.World;
import net.minecraftforge.client.model.pipeline.LightUtil;
import java.nio.Buffer;
import java.nio.ByteBuffer;
public class SuperByteBuffer extends TemplateBuffer {
@ -60,6 +57,7 @@ public class SuperByteBuffer extends TemplateBuffer {
private static final Long2DoubleMap skyLightCache = new Long2DoubleOpenHashMap();
private static final Long2DoubleMap blockLightCache = new Long2DoubleOpenHashMap();
Vector4f pos = new Vector4f();
Vector3f normal = new Vector3f();
Vector4f lightPos = new Vector4f();
public void renderInto(MatrixStack input, IVertexBuilder builder) {
@ -68,12 +66,18 @@ public class SuperByteBuffer extends TemplateBuffer {
return;
((Buffer) buffer).rewind();
Matrix4f t = input.peek()
.getModel()
.copy();
Matrix3f normalMat = transforms.peek()
.getNormal()
.copy();
//normalMat.multiply(transforms.peek().getNormal());
Matrix4f modelMat = input.peek()
.getModel()
.copy();
Matrix4f localTransforms = transforms.peek()
.getModel();
t.multiply(localTransforms);
.getModel();
modelMat.multiply(localTransforms);
if (shouldLight && lightTransform != null) {
skyLightCache.clear();
@ -90,16 +94,33 @@ public class SuperByteBuffer extends TemplateBuffer {
byte g = getG(buffer, i);
byte b = getB(buffer, i);
byte a = getA(buffer, i);
float normalX = getNX(buffer, i) / 127f;
float normalY = getNY(buffer, i) / 127f;
float normalZ = getNZ(buffer, i) / 127f;
float staticDiffuse = LightUtil.diffuseLight(normalX, normalY, normalZ);
normal.set(normalX, normalY, normalZ);
normal.transform(normalMat);
float instanceDiffuse = LightUtil.diffuseLight(normal.getX(), normal.getY(), normal.getZ());
pos.set(x, y, z, 1F);
pos.transform(t);
pos.transform(modelMat);
builder.vertex(pos.getX(), pos.getY(), pos.getZ());
//builder.color((byte) Math.max(0, normal.getX() * 255), (byte) Math.max(0, normal.getY() * 255), (byte) Math.max(0, normal.getZ() * 255), a);
if (shouldColor) {
float lum = (r < 0 ? 255 + r : r) / 256f;
builder.color((int) (this.r * lum), (int) (this.g * lum), (int) (this.b * lum), this.a);
} else
builder.color(r, g, b, a);
//float lum = (r < 0 ? 255 + r : r) / 256f;
int colorR = Math.min(255, (int) (((float) this.r) * instanceDiffuse));
int colorG = Math.min(255, (int) (((float) this.g) * instanceDiffuse));
int colorB = Math.min(255, (int) (((float) this.b) * instanceDiffuse));
builder.color(colorR, colorG, colorB, this.a);
} else {
float diffuseMult = instanceDiffuse / staticDiffuse;
int colorR = Math.min(255, (int) (((float) Byte.toUnsignedInt(r)) * diffuseMult));
int colorG = Math.min(255, (int) (((float) Byte.toUnsignedInt(g)) * diffuseMult));
int colorB = Math.min(255, (int) (((float) Byte.toUnsignedInt(b)) * diffuseMult));
builder.color(colorR, colorG, colorB, a);
}
float u = getU(buffer, i);
float v = getV(buffer, i);
@ -121,7 +142,7 @@ public class SuperByteBuffer extends TemplateBuffer {
} else
builder.light(getLight(buffer, i));
builder.normal(getNX(buffer, i), getNY(buffer, i), getNZ(buffer, i))
builder.normal(normal.getX(), normal.getY(), normal.getZ())
.endVertex();
}

View file

@ -36,7 +36,7 @@ public class BasicProgram extends GlProgram {
public void bind(Matrix4f viewProjection, int debugMode) {
super.bind();
GL20.glUniform1i(uTicks, AnimationTickHolder.ticks);
GL20.glUniform1i(uTicks, AnimationTickHolder.getTicks());
GL20.glUniform1f(uTime, AnimationTickHolder.getRenderTick());
uploadMatrixUniform(uViewProjection, viewProjection);
GL20.glUniform1i(uDebug, debugMode);

View file

@ -1,6 +1,10 @@
package com.simibubi.create.foundation.render.gl.backend;
import com.simibubi.create.foundation.render.gl.shader.*;
import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.render.gl.shader.GlProgram;
import com.simibubi.create.foundation.render.gl.shader.GlShader;
import com.simibubi.create.foundation.render.gl.shader.ProgramSpec;
import com.simibubi.create.foundation.render.gl.shader.ShaderType;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.texture.TextureUtil;
import net.minecraft.resources.IReloadableResourceManager;
@ -35,6 +39,8 @@ public class Backend {
private static final Map<ResourceLocation, ProgramSpec<?>> registry = new HashMap<>();
private static final Map<ProgramSpec<?>, GlProgram> programs = new HashMap<>();
public static boolean enabled;
public static GLCapabilities capabilities;
private static SystemCapability capability;
private static MapBuffer mapBuffer;
@ -143,6 +149,8 @@ public class Backend {
} else {
capability = SystemCapability.INCAPABLE;
}
enabled = AllConfigs.CLIENT.experimentalRendering.get();
}
private static <P extends GlProgram, S extends ProgramSpec<P>> void loadProgram(IResourceManager manager, S programSpec) {

View file

@ -93,7 +93,7 @@ public abstract class InstancedTileRenderer<P extends BasicProgram> {
public void clean() {
// Clean up twice a second. This doesn't have to happen every tick,
// but this does need to be run to ensure we don't miss anything.
if (AnimationTickHolder.ticks % 10 == 0) {
if (AnimationTickHolder.getTicks() % 10 == 0) {
instances.keySet().stream().filter(TileEntity::isRemoved).forEach(instances::remove);
}
}

View file

@ -4,14 +4,20 @@ import net.minecraft.client.Minecraft;
public class AnimationTickHolder {
public static int ticks;
private static int ticks;
public static void reset() {
ticks = 0;
}
public static void tick() {
if (!Minecraft.getInstance().isGamePaused()) ticks++;
if (!Minecraft.getInstance().isGamePaused()) {
ticks = (ticks + 1) % 1_728_000; // wrap around every 24 hours so we maintain enough floating point precision
}
}
public static float getRenderTick() {
return ticks + getPartialTicks();
return getTicks() + getPartialTicks();
}
public static float getPartialTicks() {
@ -19,4 +25,7 @@ public class AnimationTickHolder {
return (mc.isGamePaused() ? mc.renderPartialTicksPaused : mc.getRenderPartialTicks());
}
public static int getTicks() {
return ticks;
}
}