diff --git a/src/main/java/com/simibubi/create/AllBlockPartials.java b/src/main/java/com/simibubi/create/AllBlockPartials.java index 2635a4a21..1eb2881ad 100644 --- a/src/main/java/com/simibubi/create/AllBlockPartials.java +++ b/src/main/java/com/simibubi/create/AllBlockPartials.java @@ -7,6 +7,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.Supplier; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.content.contraptions.base.KineticTileEntity; @@ -219,11 +220,11 @@ public class AllBlockPartials { } public InstanceBuffer renderOnRotating(InstanceContext ctx, BlockState referenceState) { - return ctx.getKinetics().renderPartialRotating(this, referenceState); + return ctx.getRotating().getModel(this, referenceState); } public InstanceBuffer renderOnBelt(InstanceContext ctx, BlockState referenceState) { - return ctx.getKinetics().renderPartialBelt(this, referenceState); + return ctx.getBelts().getModel(this, referenceState); } public InstanceBuffer renderOnDirectionalSouthRotating(InstanceContext ctx, BlockState referenceState) { @@ -232,14 +233,16 @@ public class AllBlockPartials { } public InstanceBuffer renderOnDirectionalSouthRotating(InstanceContext ctx, BlockState referenceState, Direction facing) { - MatrixStack ms = new MatrixStack(); - // TODO 1.15 find a way to cache this model matrix computation - MatrixStacker.of(ms) - .centre() - .rotateY(AngleHelper.horizontalAngle(facing)) - .rotateX(AngleHelper.verticalAngle(facing)) - .unCentre(); - return ctx.getKinetics().renderDirectionalPartialInstanced(this, referenceState, facing, ms); + Supplier ms = () -> { + MatrixStack stack = new MatrixStack(); + MatrixStacker.of(stack) + .centre() + .rotateY(AngleHelper.horizontalAngle(facing)) + .rotateX(AngleHelper.verticalAngle(facing)) + .unCentre(); + return stack; + }; + return ctx.getRotating().getModel(this, referenceState, facing, ms); } } diff --git a/src/main/java/com/simibubi/create/CreateClient.java b/src/main/java/com/simibubi/create/CreateClient.java index ca349a611..02fbacc5d 100644 --- a/src/main/java/com/simibubi/create/CreateClient.java +++ b/src/main/java/com/simibubi/create/CreateClient.java @@ -16,8 +16,7 @@ import com.simibubi.create.foundation.block.render.CustomBlockModels; import com.simibubi.create.foundation.block.render.SpriteShifter; import com.simibubi.create.foundation.item.CustomItemModels; import com.simibubi.create.foundation.item.CustomRenderedItems; -import com.simibubi.create.foundation.render.ContraptionRenderDispatcher; -import com.simibubi.create.foundation.render.RenderedContraption; +import com.simibubi.create.foundation.render.contraption.ContraptionRenderDispatcher; import com.simibubi.create.foundation.render.FastKineticRenderer; import com.simibubi.create.foundation.render.SuperByteBufferCache; import com.simibubi.create.foundation.utility.outliner.Outliner; diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntityRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntityRenderer.java index c064f762e..4f969416b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntityRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntityRenderer.java @@ -5,7 +5,7 @@ import com.simibubi.create.AllBlocks; import com.simibubi.create.content.contraptions.KineticDebugger; import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock; import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.render.SuperByteBufferCache.Compartment; +import com.simibubi.create.foundation.render.Compartment; import com.simibubi.create.foundation.render.instancing.IInstancedTileEntityRenderer; import com.simibubi.create.foundation.render.instancing.InstanceBuffer; import com.simibubi.create.foundation.render.instancing.InstanceContext; @@ -61,12 +61,12 @@ public class KineticTileEntityRenderer extends SafeTileEntityRenderer void renderRotatingKineticBlock(InstanceContext ctx, BlockState renderedState) { - InstanceBuffer instancedRenderer = ctx.getKinetics().renderBlockInstanced(KINETIC_TILE, renderedState); + InstanceBuffer instancedRenderer = ctx.getRotating().getModel(KINETIC_TILE, renderedState); renderRotatingBuffer(ctx, instancedRenderer); } public static void markForRebuild(InstanceContext ctx, BlockState renderedState) { - ctx.getKinetics().renderBlockInstanced(KINETIC_TILE, renderedState).clearInstanceData(); + ctx.getRotating().getModel(KINETIC_TILE, renderedState).clearInstanceData(); } public static void renderRotatingBuffer(InstanceContext ctx, InstanceBuffer instancer) { @@ -151,7 +151,7 @@ public class KineticTileEntityRenderer extends SafeTileEntityRenderer getRotatedModel(InstanceContext ctx) { - return ctx.getKinetics().renderBlockInstanced(KINETIC_TILE, getRenderedBlockState(ctx.te)); + return ctx.getRotating().getModel(KINETIC_TILE, getRenderedBlockState(ctx.te)); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillMovementBehaviour.java index 62f8c319d..00f01202b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillMovementBehaviour.java @@ -34,6 +34,11 @@ public class DrillMovementBehaviour extends BlockBreakingMovementBehaviour { DrillRenderer.renderInContraption(context, ms, msLocal, buffer); } + @Override + public void addInstance(MovementContext context) { + super.addInstance(context); + } + @Override protected DamageSource getDamageSource() { return DrillBlock.damageSourceDrill; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillRenderer.java index a54f8ff93..ca8474509 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillRenderer.java @@ -37,6 +37,10 @@ public class DrillRenderer extends KineticTileEntityRenderer { return AllBlockPartials.DRILL_HEAD.renderOnDirectionalSouth(state); } + public static void addInstanceForContraption(MovementContext context) { + //AllBlockPartials.DRILL_HEAD. + } + public static void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffer) { MatrixStack[] matrixStacks = new MatrixStack[] { ms, msLocal }; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawRenderer.java index 75536539d..e35d85a0b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawRenderer.java @@ -141,7 +141,7 @@ public class SawRenderer extends SafeTileEntityRenderer implement BlockState state = te.getBlockState(); if (state.get(FACING).getAxis().isHorizontal()) return AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(ctx, state.rotate(te.getWorld(), te.getPos(), Rotation.CLOCKWISE_180)); - return ctx.getKinetics().renderBlockInstanced(KineticTileEntityRenderer.KINETIC_TILE, + return ctx.getRotating().getModel(KineticTileEntityRenderer.KINETIC_TILE, getRenderedBlockState(te)); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntityRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntityRenderer.java index 2634d9f64..bb0e58296 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntityRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntityRenderer.java @@ -2,9 +2,7 @@ package com.simibubi.create.content.contraptions.components.structureMovement; import com.mojang.blaze3d.matrix.MatrixStack; -import com.simibubi.create.foundation.render.ContraptionRenderDispatcher; -import com.simibubi.create.foundation.render.RenderedContraption; -import net.java.games.input.Controller; +import com.simibubi.create.foundation.render.contraption.ContraptionRenderDispatcher; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.culling.ClippingHelperImpl; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionRenderer.java index 9b00b8f6e..b839f558d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionRenderer.java @@ -12,7 +12,7 @@ import com.simibubi.create.CreateClient; import com.simibubi.create.foundation.utility.MatrixStacker; import com.simibubi.create.foundation.render.SuperByteBuffer; import com.simibubi.create.foundation.render.SuperByteBufferCache; -import com.simibubi.create.foundation.render.SuperByteBufferCache.Compartment; +import com.simibubi.create.foundation.render.Compartment; import com.simibubi.create.foundation.render.TileEntityRenderHelper; import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovementBehaviour.java index bf25055fe..b4b3bf220 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovementBehaviour.java @@ -55,6 +55,9 @@ public abstract class MovementBehaviour { public void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffer) {} + @OnlyIn(Dist.CLIENT) + public void addInstance(MovementContext context) {} + public void onSpeedChanged(MovementContext context, Vec3d oldMotion, Vec3d motion) { } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/SpeedControllerRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/SpeedControllerRenderer.java index 073a6a792..5fade0d1d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/SpeedControllerRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/SpeedControllerRenderer.java @@ -34,7 +34,7 @@ public class SpeedControllerRenderer extends SmartTileEntityRenderer getRotatedModel(InstanceContext ctx) { - return ctx.getKinetics().renderBlockInstanced(KineticTileEntityRenderer.KINETIC_TILE, + return ctx.getRotating().getModel(KineticTileEntityRenderer.KINETIC_TILE, KineticTileEntityRenderer.shaft(KineticTileEntityRenderer.getRotationAxisOf(ctx.te))); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltRenderer.java index bc8628880..c39af13c3 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltRenderer.java @@ -30,6 +30,7 @@ import net.minecraft.util.math.Vec3i; import net.minecraft.world.LightType; import java.util.Random; +import java.util.function.Supplier; public class BeltRenderer extends SafeTileEntityRenderer implements IInstancedTileEntityRenderer { @@ -82,8 +83,6 @@ public class BeltRenderer extends SafeTileEntityRenderer impleme end = b; } - FastKineticRenderer fastKineticRenderer = ctx.getKinetics(); - for (boolean bottom : Iterate.trueAndFalse) { AllBlockPartials beltPartial = diagonal @@ -128,23 +127,7 @@ public class BeltRenderer extends SafeTileEntityRenderer impleme } if (te.hasPulley()) { - // TODO 1.15 find a way to cache this model matrix computation - MatrixStack modelTransform = new MatrixStack(); - Direction dir = blockState.get(BeltBlock.HORIZONTAL_FACING) - .rotateY(); - if (sideways) - dir = Direction.UP; - MatrixStacker msr = MatrixStacker.of(modelTransform); - msr.centre(); - if (dir.getAxis() == Axis.X) - msr.rotateY(90); - if (dir.getAxis() == Axis.Y) - msr.rotateX(90); - msr.rotateX(90); - msr.unCentre(); - - InstanceBuffer rotatingBuffer = fastKineticRenderer - .renderDirectionalPartialInstanced(AllBlockPartials.BELT_PULLEY, blockState, dir, modelTransform); + InstanceBuffer rotatingBuffer = getPulleyModel(ctx, blockState, sideways); KineticTileEntityRenderer.renderRotatingBuffer(ctx, rotatingBuffer); } } @@ -152,7 +135,6 @@ public class BeltRenderer extends SafeTileEntityRenderer impleme @Override public void markForRebuild(InstanceContext ctx) { BeltTileEntity te = ctx.te; - FastKineticRenderer fastKineticRenderer = ctx.getKinetics(); BlockState blockState = te.getBlockState(); if (!AllBlocks.BELT.has(blockState)) @@ -197,25 +179,34 @@ public class BeltRenderer extends SafeTileEntityRenderer impleme break; } - // TODO 1.15 find a way to cache this model matrix computation - MatrixStack modelTransform = new MatrixStack(); + InstanceBuffer rotatingBuffer = getPulleyModel(ctx, blockState, sideways); + + rotatingBuffer.clearInstanceData(); + } + + private InstanceBuffer getPulleyModel(InstanceContext ctx, BlockState blockState, boolean sideways) { Direction dir = blockState.get(BeltBlock.HORIZONTAL_FACING) .rotateY(); if (sideways) dir = Direction.UP; - MatrixStacker msr = MatrixStacker.of(modelTransform); - msr.centre(); - if (dir.getAxis() == Axis.X) - msr.rotateY(90); - if (dir.getAxis() == Axis.Y) + + Axis axis = dir.getAxis(); + + Supplier ms = () -> { + MatrixStack modelTransform = new MatrixStack(); + MatrixStacker msr = MatrixStacker.of(modelTransform); + msr.centre(); + if (axis == Axis.X) + msr.rotateY(90); + if (axis == Axis.Y) + msr.rotateX(90); msr.rotateX(90); - msr.rotateX(90); - msr.unCentre(); + msr.unCentre(); - InstanceBuffer rotatingBuffer = fastKineticRenderer - .renderDirectionalPartialInstanced(AllBlockPartials.BELT_PULLEY, blockState, dir, modelTransform); + return modelTransform; + }; - rotatingBuffer.clearInstanceData(); + return ctx.getRotating().getModel(AllBlockPartials.BELT_PULLEY, blockState, dir, ms); } protected void renderItems(BeltTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, diff --git a/src/main/java/com/simibubi/create/foundation/render/Compartment.java b/src/main/java/com/simibubi/create/foundation/render/Compartment.java new file mode 100644 index 000000000..646eb7191 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/Compartment.java @@ -0,0 +1,12 @@ +package com.simibubi.create.foundation.render; + +import com.simibubi.create.AllBlockPartials; +import net.minecraft.block.BlockState; +import net.minecraft.util.Direction; +import org.apache.commons.lang3.tuple.Pair; + +public class Compartment { + public static final Compartment GENERIC_TILE = new Compartment<>(); + public static final Compartment PARTIAL = new Compartment<>(); + public static final Compartment> DIRECTIONAL_PARTIAL = new Compartment<>(); +} diff --git a/src/main/java/com/simibubi/create/foundation/render/FastKineticRenderer.java b/src/main/java/com/simibubi/create/foundation/render/FastKineticRenderer.java index 3d0764187..d35a580b2 100644 --- a/src/main/java/com/simibubi/create/foundation/render/FastKineticRenderer.java +++ b/src/main/java/com/simibubi/create/foundation/render/FastKineticRenderer.java @@ -1,56 +1,42 @@ package com.simibubi.create.foundation.render; -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import com.mojang.blaze3d.matrix.MatrixStack; -import com.mojang.blaze3d.systems.RenderSystem; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; +import com.simibubi.create.foundation.render.contraption.RenderedContraption; import com.simibubi.create.foundation.render.instancing.*; import com.simibubi.create.foundation.render.shader.Shader; import com.simibubi.create.foundation.render.shader.ShaderCallback; import com.simibubi.create.foundation.render.shader.ShaderHelper; -import net.minecraft.block.BlockState; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.*; -import net.minecraft.client.renderer.model.IBakedModel; -import net.minecraft.client.renderer.texture.Texture; import net.minecraft.client.renderer.tileentity.TileEntityRenderer; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; -import net.minecraft.inventory.container.PlayerContainer; import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.Direction; import net.minecraft.world.World; -import org.apache.commons.lang3.tuple.Pair; -import org.lwjgl.opengl.GL11; -import org.lwjgl.opengl.GL13; -import org.lwjgl.opengl.GL40; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.concurrent.ExecutionException; -import java.util.function.Consumer; -import java.util.function.Supplier; - -import static com.simibubi.create.foundation.render.SuperByteBufferCache.PARTIAL; public class FastKineticRenderer { - Map, Cache>> rotating; - Map, Cache>> belts; + protected Map, RenderMaterial> materials = new HashMap<>(); public boolean dirty = false; public FastKineticRenderer() { - rotating = new HashMap<>(); - belts = new HashMap<>(); - registerCompartment(SuperByteBufferCache.PARTIAL); - registerCompartment(SuperByteBufferCache.DIRECTIONAL_PARTIAL); - registerCompartment(KineticTileEntityRenderer.KINETIC_TILE); + registerMaterials(); } - public void buildTileEntityBuffers(World world) { + public void registerMaterials() { + materials.put(KineticRenderMaterials.BELTS, new RenderMaterial<>(Shader.BELT, BeltBuffer::new)); + materials.put(KineticRenderMaterials.ROTATING, new RenderMaterial<>(Shader.ROTATING, RotatingBuffer::new)); + } + @SuppressWarnings("unchecked") + public > RenderMaterial get(MaterialType materialType) { + return (RenderMaterial) materials.get(materialType); + } + + @SuppressWarnings("unchecked") + public void buildTileEntityBuffers(World world) { List tileEntities = world.loadedTileEntityList; if (!tileEntities.isEmpty()) { @@ -66,11 +52,11 @@ public class FastKineticRenderer { } } - void addInstancedData(T te, IInstancedTileEntityRenderer renderer) { + public void addInstancedData(T te, IInstancedTileEntityRenderer renderer) { renderer.addInstanceData(new InstanceContext.World<>(te)); } - void addInstancedData(RenderedContraption c, T te, IInstancedTileEntityRenderer renderer) { + public void addInstancedData(RenderedContraption c, T te, IInstancedTileEntityRenderer renderer) { renderer.addInstanceData(new InstanceContext.Contraption<>(te, c)); } @@ -80,141 +66,45 @@ public class FastKineticRenderer { * guaranteed to be no race conditions with the render thread, i.e. when constructing a FastContraptionRenderer. */ public void markAllDirty() { - runOnAll(InstanceBuffer::markDirty); + for (RenderMaterial material : materials.values()) { + material.runOnAll(InstanceBuffer::markDirty); + } } public void invalidate() { - runOnAll(InstanceBuffer::delete); - belts.values().forEach(Cache::invalidateAll); - rotating.values().forEach(Cache::invalidateAll); + for (RenderMaterial material : materials.values()) { + material.runOnAll(InstanceBuffer::delete); + } dirty = true; } - private void runOnAll(Consumer> f) { - for (Cache> cache : rotating.values()) { - for (InstanceBuffer renderer : cache.asMap().values()) { - f.accept(renderer); - } - } - - for (Cache> cache : belts.values()) { - for (InstanceBuffer renderer : cache.asMap().values()) { - f.accept(renderer); - } - } + public void render(RenderType layer, Matrix4f projection, Matrix4f view) { + render(layer, projection, view, null); } - void renderBelts() { - for (Cache> cache : belts.values()) { - for (InstanceBuffer type : cache.asMap().values()) { - if (!type.isEmpty()) { - type.render(); - } - } - } - } - - void renderRotating() { - for (Cache> cache : rotating.values()) { - for (InstanceBuffer rotatingDataInstanceBuffer : cache.asMap().values()) { - if (!rotatingDataInstanceBuffer.isEmpty()) { - rotatingDataInstanceBuffer.render(); - } - } - } - } - - public void renderInstancesAsWorld(RenderType layer, Matrix4f projection, Matrix4f view) { + protected void prepareFrame() { if (dirty) { buildTileEntityBuffers(Minecraft.getInstance().world); markAllDirty(); dirty = false; } + } + + public void render(RenderType layer, Matrix4f projection, Matrix4f view, ShaderCallback callback) { + prepareFrame(); layer.startDrawing(); - ShaderCallback callback = ShaderHelper.getViewProjectionCallback(projection, view); - - ShaderHelper.useShader(Shader.ROTATING, callback); - renderRotating(); - - ShaderHelper.useShader(Shader.BELT, callback); - renderBelts(); + for (RenderMaterial material : materials.values()) { + material.render(projection, view, callback); + } ShaderHelper.releaseShader(); layer.endDrawing(); } - public void registerCompartment(SuperByteBufferCache.Compartment instance) { - rotating.put(instance, CacheBuilder.newBuilder().build()); - belts.put(instance, CacheBuilder.newBuilder().build()); - } - - public InstanceBuffer renderPartialRotating(AllBlockPartials partial, BlockState referenceState) { - return getRotating(PARTIAL, partial, () -> rotatingInstancedRenderer(partial.get(), referenceState)); - } - - public InstanceBuffer renderPartialBelt(AllBlockPartials partial, BlockState referenceState) { - return getBelt(PARTIAL, partial, () -> beltInstancedRenderer(partial.get(), referenceState)); - } - - public InstanceBuffer renderDirectionalPartialInstanced(AllBlockPartials partial, BlockState referenceState, Direction dir, - MatrixStack modelTransform) { - return getRotating(SuperByteBufferCache.DIRECTIONAL_PARTIAL, Pair.of(dir, partial), - () -> rotatingInstancedRenderer(partial.get(), referenceState, modelTransform)); - } - - public InstanceBuffer renderBlockInstanced(SuperByteBufferCache.Compartment compartment, BlockState toRender) { - return getRotating(compartment, toRender, () -> rotatingInstancedRenderer(toRender)); - } - - public InstanceBuffer getRotating(SuperByteBufferCache.Compartment compartment, T key, Supplier> supplier) { - Cache> compartmentCache = this.rotating.get(compartment); - try { - return compartmentCache.get(key, supplier::get); - } catch (ExecutionException e) { - e.printStackTrace(); - return null; - } - } - - public InstanceBuffer getBelt(SuperByteBufferCache.Compartment compartment, T key, Supplier> supplier) { - Cache> compartmentCache = this.belts.get(compartment); - try { - return compartmentCache.get(key, supplier::get); - } catch (ExecutionException e) { - e.printStackTrace(); - return null; - } - } - - private InstanceBuffer rotatingInstancedRenderer(BlockState renderedState) { - BlockRendererDispatcher dispatcher = Minecraft.getInstance().getBlockRendererDispatcher(); - return rotatingInstancedRenderer(dispatcher.getModelForState(renderedState), renderedState); - } - - private InstanceBuffer rotatingInstancedRenderer(IBakedModel model, BlockState renderedState) { - return rotatingInstancedRenderer(model, renderedState, new MatrixStack()); - } - - private InstanceBuffer beltInstancedRenderer(IBakedModel model, BlockState renderedState) { - return beltInstancedRenderer(model, renderedState, new MatrixStack()); - } - - private InstanceBuffer rotatingInstancedRenderer(IBakedModel model, BlockState referenceState, MatrixStack ms) { - BufferBuilder builder = SuperByteBufferCache.getBufferBuilder(model, referenceState, ms); - - return new RotatingBuffer(builder); - } - - private InstanceBuffer beltInstancedRenderer(IBakedModel model, BlockState referenceState, MatrixStack ms) { - BufferBuilder builder = SuperByteBufferCache.getBufferBuilder(model, referenceState, ms); - - return new BeltBuffer(builder); - } - public static RenderType getKineticRenderLayer() { return RenderType.getCutoutMipped(); } diff --git a/src/main/java/com/simibubi/create/foundation/render/FastRenderDispatcher.java b/src/main/java/com/simibubi/create/foundation/render/FastRenderDispatcher.java index b5353d5dd..f79c59c74 100644 --- a/src/main/java/com/simibubi/create/foundation/render/FastRenderDispatcher.java +++ b/src/main/java/com/simibubi/create/foundation/render/FastRenderDispatcher.java @@ -3,6 +3,7 @@ package com.simibubi.create.foundation.render; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.systems.RenderSystem; import com.simibubi.create.CreateClient; +import com.simibubi.create.foundation.render.contraption.ContraptionRenderDispatcher; import com.simibubi.create.foundation.render.instancing.IInstanceRendered; import com.simibubi.create.foundation.render.instancing.IInstancedTileEntityRenderer; import com.simibubi.create.foundation.render.instancing.InstanceContext; @@ -24,7 +25,6 @@ import net.minecraft.world.ILightReader; import net.minecraft.world.LightType; import net.minecraft.world.chunk.Chunk; import org.lwjgl.opengl.GL11; -import org.lwjgl.opengl.GL30; import java.util.Map; @@ -46,7 +46,7 @@ public class FastRenderDispatcher { RenderSystem.enableDepthTest(); RenderSystem.enableCull(); GL11.glCullFace(GL11.GL_BACK); - CreateClient.kineticRenderer.renderInstancesAsWorld(type, projection, view); + CreateClient.kineticRenderer.render(type, projection, view); RenderSystem.disableCull(); //RenderSystem.disableDepthTest(); } diff --git a/src/main/java/com/simibubi/create/foundation/render/SuperByteBufferCache.java b/src/main/java/com/simibubi/create/foundation/render/SuperByteBufferCache.java index 39c8e33de..ab9e0fafa 100644 --- a/src/main/java/com/simibubi/create/foundation/render/SuperByteBufferCache.java +++ b/src/main/java/com/simibubi/create/foundation/render/SuperByteBufferCache.java @@ -27,20 +27,13 @@ import net.minecraft.util.math.BlockPos; public class SuperByteBufferCache { - public static class Compartment { - } - - public static final Compartment GENERIC_TILE = new Compartment<>(); - public static final Compartment PARTIAL = new Compartment<>(); - public static final Compartment> DIRECTIONAL_PARTIAL = new Compartment<>(); - Map, Cache> cache; public SuperByteBufferCache() { cache = new HashMap<>(); - registerCompartment(GENERIC_TILE); - registerCompartment(PARTIAL); - registerCompartment(DIRECTIONAL_PARTIAL); + registerCompartment(Compartment.GENERIC_TILE); + registerCompartment(Compartment.PARTIAL); + registerCompartment(Compartment.DIRECTIONAL_PARTIAL); } public SuperByteBuffer renderBlock(BlockState toRender) { @@ -48,23 +41,23 @@ public class SuperByteBufferCache { } public SuperByteBuffer renderPartial(AllBlockPartials partial, BlockState referenceState) { - return get(PARTIAL, partial, () -> standardModelRender(partial.get(), referenceState)); + return get(Compartment.PARTIAL, partial, () -> standardModelRender(partial.get(), referenceState)); } public SuperByteBuffer renderPartial(AllBlockPartials partial, BlockState referenceState, MatrixStack modelTransform) { - return get(PARTIAL, partial, () -> standardModelRender(partial.get(), referenceState, modelTransform)); + return get(Compartment.PARTIAL, partial, () -> standardModelRender(partial.get(), referenceState, modelTransform)); } public SuperByteBuffer renderDirectionalPartial(AllBlockPartials partial, BlockState referenceState, Direction dir) { - return get(DIRECTIONAL_PARTIAL, Pair.of(dir, partial), - () -> standardModelRender(partial.get(), referenceState)); + return get(Compartment.DIRECTIONAL_PARTIAL, Pair.of(dir, partial), + () -> standardModelRender(partial.get(), referenceState)); } public SuperByteBuffer renderDirectionalPartial(AllBlockPartials partial, BlockState referenceState, Direction dir, MatrixStack modelTransform) { - return get(DIRECTIONAL_PARTIAL, Pair.of(dir, partial), - () -> standardModelRender(partial.get(), referenceState, modelTransform)); + return get(Compartment.DIRECTIONAL_PARTIAL, Pair.of(dir, partial), + () -> standardModelRender(partial.get(), referenceState, modelTransform)); } public SuperByteBuffer renderBlockIn(Compartment compartment, BlockState toRender) { @@ -72,7 +65,7 @@ public class SuperByteBufferCache { } SuperByteBuffer getGeneric(BlockState key, Supplier supplier) { - return get(GENERIC_TILE, key, supplier); + return get(Compartment.GENERIC_TILE, key, supplier); } public SuperByteBuffer get(Compartment compartment, T key, Supplier supplier) { diff --git a/src/main/java/com/simibubi/create/foundation/render/ContraptionBuffer.java b/src/main/java/com/simibubi/create/foundation/render/contraption/ContraptionBuffer.java similarity index 92% rename from src/main/java/com/simibubi/create/foundation/render/ContraptionBuffer.java rename to src/main/java/com/simibubi/create/foundation/render/contraption/ContraptionBuffer.java index 89e76292a..d9d59f0e9 100644 --- a/src/main/java/com/simibubi/create/foundation/render/ContraptionBuffer.java +++ b/src/main/java/com/simibubi/create/foundation/render/contraption/ContraptionBuffer.java @@ -1,6 +1,7 @@ -package com.simibubi.create.foundation.render; +package com.simibubi.create.foundation.render.contraption; import com.mojang.blaze3d.platform.GlStateManager; +import com.simibubi.create.foundation.render.GPUBuffer; import com.simibubi.create.foundation.render.instancing.InstanceBuffer; import com.simibubi.create.foundation.render.instancing.VertexFormat; import net.minecraft.client.renderer.BufferBuilder; diff --git a/src/main/java/com/simibubi/create/foundation/render/contraption/ContraptionKineticRenderer.java b/src/main/java/com/simibubi/create/foundation/render/contraption/ContraptionKineticRenderer.java new file mode 100644 index 000000000..b06626d16 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/contraption/ContraptionKineticRenderer.java @@ -0,0 +1,25 @@ +package com.simibubi.create.foundation.render.contraption; + +import com.simibubi.create.foundation.render.FastKineticRenderer; +import com.simibubi.create.foundation.render.instancing.BeltBuffer; +import com.simibubi.create.foundation.render.instancing.KineticRenderMaterials; +import com.simibubi.create.foundation.render.instancing.RenderMaterial; +import com.simibubi.create.foundation.render.instancing.RotatingBuffer; +import com.simibubi.create.foundation.render.shader.Shader; +import com.simibubi.create.foundation.render.shader.ShaderCallback; +import com.simibubi.create.foundation.render.shader.ShaderHelper; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.Matrix4f; +import net.minecraft.client.renderer.RenderType; + +public class ContraptionKineticRenderer extends FastKineticRenderer { + + @Override + public void registerMaterials() { + materials.put(KineticRenderMaterials.BELTS, new RenderMaterial<>(Shader.CONTRAPTION_BELT, BeltBuffer::new)); + materials.put(KineticRenderMaterials.ROTATING, new RenderMaterial<>(Shader.CONTRAPTION_ROTATING, RotatingBuffer::new)); + } + + @Override + protected void prepareFrame() {} +} diff --git a/src/main/java/com/simibubi/create/foundation/render/ContraptionRenderDispatcher.java b/src/main/java/com/simibubi/create/foundation/render/contraption/ContraptionRenderDispatcher.java similarity index 80% rename from src/main/java/com/simibubi/create/foundation/render/ContraptionRenderDispatcher.java rename to src/main/java/com/simibubi/create/foundation/render/contraption/ContraptionRenderDispatcher.java index 0689583a7..039c3ed27 100644 --- a/src/main/java/com/simibubi/create/foundation/render/ContraptionRenderDispatcher.java +++ b/src/main/java/com/simibubi/create/foundation/render/contraption/ContraptionRenderDispatcher.java @@ -1,17 +1,13 @@ -package com.simibubi.create.foundation.render; +package com.simibubi.create.foundation.render.contraption; import com.mojang.blaze3d.matrix.MatrixStack; -import com.mojang.blaze3d.platform.GlStateManager; -import com.mojang.blaze3d.systems.RenderSystem; import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; -import com.simibubi.create.foundation.render.light.LightVolume; +import com.simibubi.create.foundation.render.FastKineticRenderer; import com.simibubi.create.foundation.render.shader.Shader; import com.simibubi.create.foundation.render.shader.ShaderCallback; import com.simibubi.create.foundation.render.shader.ShaderHelper; -import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.Matrix4f; import net.minecraft.client.renderer.RenderType; -import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.SectionPos; import net.minecraft.world.ILightReader; import net.minecraft.world.LightType; @@ -64,17 +60,8 @@ public class ContraptionRenderDispatcher { } if (renderType == FastKineticRenderer.getKineticRenderLayer()) { - int rotatingShader = ShaderHelper.useShader(Shader.CONTRAPTION_ROTATING, callback); for (RenderedContraption renderer : renderers.values()) { - renderer.setup(rotatingShader); - renderer.kinetics.renderRotating(); - renderer.teardown(); - } - - int beltShader = ShaderHelper.useShader(Shader.CONTRAPTION_BELT, callback); - for (RenderedContraption renderer : renderers.values()) { - renderer.setup(beltShader); - renderer.kinetics.renderBelts(); + renderer.kinetics.render(renderType, projectionMat, viewMat, renderer::setup); renderer.teardown(); } } diff --git a/src/main/java/com/simibubi/create/foundation/render/RenderedContraption.java b/src/main/java/com/simibubi/create/foundation/render/contraption/RenderedContraption.java similarity index 80% rename from src/main/java/com/simibubi/create/foundation/render/RenderedContraption.java rename to src/main/java/com/simibubi/create/foundation/render/contraption/RenderedContraption.java index 07f87978c..e000cb20e 100644 --- a/src/main/java/com/simibubi/create/foundation/render/RenderedContraption.java +++ b/src/main/java/com/simibubi/create/foundation/render/contraption/RenderedContraption.java @@ -1,12 +1,15 @@ -package com.simibubi.create.foundation.render; +package com.simibubi.create.foundation.render.contraption; import com.mojang.blaze3d.platform.GlStateManager; +import com.simibubi.create.AllMovementBehaviours; import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionRenderer; +import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; +import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; +import com.simibubi.create.foundation.render.FastKineticRenderer; import com.simibubi.create.foundation.render.instancing.IInstanceRendered; import com.simibubi.create.foundation.render.instancing.IInstancedTileEntityRenderer; import com.simibubi.create.foundation.render.light.ContraptionLighter; -import com.simibubi.create.foundation.render.light.LightVolume; import com.simibubi.create.foundation.render.shader.ShaderHelper; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.Matrix4f; @@ -14,15 +17,11 @@ import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.tileentity.TileEntityRenderer; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.math.AxisAlignedBB; -import net.minecraft.util.math.SectionPos; -import net.minecraft.world.ILightReader; -import net.minecraft.world.LightType; import net.minecraft.world.World; -import org.lwjgl.opengl.GL20; +import net.minecraft.world.gen.feature.template.Template; +import org.apache.commons.lang3.tuple.MutablePair; import java.nio.FloatBuffer; -import java.util.Collection; import java.util.HashMap; import java.util.List; @@ -31,7 +30,7 @@ public class RenderedContraption { private final ContraptionLighter lighter; - public final FastKineticRenderer kinetics; + public final ContraptionKineticRenderer kinetics; private Contraption contraption; @@ -40,7 +39,7 @@ public class RenderedContraption { public RenderedContraption(World world, Contraption contraption) { this.contraption = contraption; this.lighter = contraption.makeLighter(); - this.kinetics = new FastKineticRenderer(); + this.kinetics = new ContraptionKineticRenderer(); buildLayers(contraption); buildInstancedTiles(contraption); @@ -98,6 +97,21 @@ public class RenderedContraption { kinetics.markAllDirty(); } + private void buildActors(Contraption c) { + List> actors = c.getActors(); + + for (MutablePair actor : actors) { + Template.BlockInfo blockInfo = actor.left; + MovementContext context = actor.right; + + MovementBehaviour movementBehaviour = AllMovementBehaviours.of(blockInfo.state); + + if (movementBehaviour != null) { + movementBehaviour.addInstance(context); + } + } + } + void setRenderSettings(Matrix4f model) { this.model = model; } diff --git a/src/main/java/com/simibubi/create/foundation/render/instancing/DynamicInstanceBuffer.java b/src/main/java/com/simibubi/create/foundation/render/instancing/DynamicInstanceBuffer.java index 0abba029c..e4e90992d 100644 --- a/src/main/java/com/simibubi/create/foundation/render/instancing/DynamicInstanceBuffer.java +++ b/src/main/java/com/simibubi/create/foundation/render/instancing/DynamicInstanceBuffer.java @@ -27,4 +27,11 @@ public abstract class DynamicInstanceBuffer { this.te = te; } + public RenderMaterial> getRotating() { + return getKinetics().get(KineticRenderMaterials.ROTATING); + } + + public RenderMaterial> getBelts() { + return getKinetics().get(KineticRenderMaterials.BELTS); + } + public abstract FastKineticRenderer getKinetics(); public abstract boolean checkWorldLight(); diff --git a/src/main/java/com/simibubi/create/foundation/render/instancing/KineticRenderMaterials.java b/src/main/java/com/simibubi/create/foundation/render/instancing/KineticRenderMaterials.java new file mode 100644 index 000000000..5c0d4e658 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/instancing/KineticRenderMaterials.java @@ -0,0 +1,6 @@ +package com.simibubi.create.foundation.render.instancing; + +public class KineticRenderMaterials { + public static final MaterialType> ROTATING = new MaterialType<>(); + public static final MaterialType> BELTS = new MaterialType<>(); +} diff --git a/src/main/java/com/simibubi/create/foundation/render/instancing/MaterialType.java b/src/main/java/com/simibubi/create/foundation/render/instancing/MaterialType.java new file mode 100644 index 000000000..d3ef03f94 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/instancing/MaterialType.java @@ -0,0 +1,3 @@ +package com.simibubi.create.foundation.render.instancing; + +public class MaterialType { } diff --git a/src/main/java/com/simibubi/create/foundation/render/instancing/ModelFactory.java b/src/main/java/com/simibubi/create/foundation/render/instancing/ModelFactory.java new file mode 100644 index 000000000..36120053b --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/instancing/ModelFactory.java @@ -0,0 +1,8 @@ +package com.simibubi.create.foundation.render.instancing; + +import net.minecraft.client.renderer.BufferBuilder; + +@FunctionalInterface +public interface ModelFactory> { + B convert(BufferBuilder buf); +} diff --git a/src/main/java/com/simibubi/create/foundation/render/instancing/RenderMaterial.java b/src/main/java/com/simibubi/create/foundation/render/instancing/RenderMaterial.java new file mode 100644 index 000000000..0679ec855 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/instancing/RenderMaterial.java @@ -0,0 +1,131 @@ +package com.simibubi.create.foundation.render.instancing; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; +import com.simibubi.create.foundation.render.Compartment; +import com.simibubi.create.foundation.render.SuperByteBufferCache; +import com.simibubi.create.foundation.render.shader.Shader; +import com.simibubi.create.foundation.render.shader.ShaderCallback; +import com.simibubi.create.foundation.render.shader.ShaderHelper; +import net.minecraft.block.BlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BlockRendererDispatcher; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.Matrix4f; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.model.IBakedModel; +import net.minecraft.util.Direction; +import org.apache.commons.lang3.tuple.Pair; +import org.lwjgl.opengl.GL40; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.function.Consumer; +import java.util.function.Supplier; + +import static com.simibubi.create.foundation.render.Compartment.PARTIAL; + +public class RenderMaterial> { + + protected final Map, Cache> models; + protected final ModelFactory factory; + protected final Shader shader; + + public RenderMaterial(Shader shader, ModelFactory factory) { + this.models = new HashMap<>(); + this.factory = factory; + this.shader = shader; + registerCompartment(Compartment.PARTIAL); + registerCompartment(Compartment.DIRECTIONAL_PARTIAL); + registerCompartment(KineticTileEntityRenderer.KINETIC_TILE); + } + + public void render(Matrix4f projection, Matrix4f view) { + render(projection, view, null); + } + + public void render(Matrix4f projection, Matrix4f view, ShaderCallback setup) { + int handle = setupShader(projection, view); + if (setup != null) setup.call(handle); + makeRenderCalls(); + teardown(); + } + + protected int setupShader(Matrix4f projection, Matrix4f view) { + ShaderCallback callback = ShaderHelper.getViewProjectionCallback(projection, view); + + return ShaderHelper.useShader(shader, callback); + } + + public void teardown() {} + + public void delete() { + runOnAll(InstanceBuffer::delete); + models.values().forEach(Cache::invalidateAll); + } + + protected void makeRenderCalls() { + for (Cache cache : models.values()) { + for (MODEL model : cache.asMap().values()) { + if (!model.isEmpty()) { + model.render(); + } + } + } + } + + public void runOnAll(Consumer f) { + for (Cache cache : models.values()) { + for (MODEL model : cache.asMap().values()) { + f.accept(model); + } + } + } + + public void registerCompartment(Compartment instance) { + models.put(instance, CacheBuilder.newBuilder().build()); + } + + public MODEL getModel(AllBlockPartials partial, BlockState referenceState) { + return get(PARTIAL, partial, () -> buildModel(partial.get(), referenceState)); + } + + public MODEL getModel(AllBlockPartials partial, BlockState referenceState, Direction dir, Supplier modelTransform) { + return get(Compartment.DIRECTIONAL_PARTIAL, Pair.of(dir, partial), + () -> buildModel(partial.get(), referenceState, modelTransform.get())); + } + + public MODEL getModel(Compartment compartment, BlockState toRender) { + return get(compartment, toRender, () -> buildModel(toRender)); + } + + public MODEL get(Compartment compartment, T key, Supplier supplier) { + Cache compartmentCache = models.get(compartment); + try { + return compartmentCache.get(key, supplier::get); + } catch (ExecutionException e) { + e.printStackTrace(); + return null; + } + } + + private MODEL buildModel(BlockState renderedState) { + BlockRendererDispatcher dispatcher = Minecraft.getInstance().getBlockRendererDispatcher(); + return buildModel(dispatcher.getModelForState(renderedState), renderedState); + } + + private MODEL buildModel(IBakedModel model, BlockState renderedState) { + return buildModel(model, renderedState, new MatrixStack()); + } + + private MODEL buildModel(IBakedModel model, BlockState referenceState, MatrixStack ms) { + BufferBuilder builder = SuperByteBufferCache.getBufferBuilder(model, referenceState, ms); + + return factory.convert(builder); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/render/light/LightVolume.java b/src/main/java/com/simibubi/create/foundation/render/light/LightVolume.java index 0f896cd2b..aae5a6b28 100644 --- a/src/main/java/com/simibubi/create/foundation/render/light/LightVolume.java +++ b/src/main/java/com/simibubi/create/foundation/render/light/LightVolume.java @@ -159,6 +159,7 @@ public class LightVolume { // just in case something goes wrong or we accidentally call this before this volume is properly disposed of. if (glTexture == 0 || lightData == null) return; + GL13.glActiveTexture(GL40.GL_TEXTURE4); GL12.glBindTexture(GL12.GL_TEXTURE_3D, glTexture); GL11.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_MIN_FILTER, GL13.GL_LINEAR); GL11.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_MAG_FILTER, GL13.GL_LINEAR); diff --git a/src/main/java/com/simibubi/create/foundation/render/light/LightVolumeDebugger.java b/src/main/java/com/simibubi/create/foundation/render/light/LightVolumeDebugger.java index 287532a40..651d0c5eb 100644 --- a/src/main/java/com/simibubi/create/foundation/render/light/LightVolumeDebugger.java +++ b/src/main/java/com/simibubi/create/foundation/render/light/LightVolumeDebugger.java @@ -1,7 +1,7 @@ package com.simibubi.create.foundation.render.light; import com.mojang.blaze3d.matrix.MatrixStack; -import com.simibubi.create.foundation.render.ContraptionRenderDispatcher; +import com.simibubi.create.foundation.render.contraption.ContraptionRenderDispatcher; import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer; import com.simibubi.create.foundation.utility.Pair; import com.simibubi.create.foundation.utility.outliner.AABBOutline; diff --git a/src/main/java/com/simibubi/create/foundation/render/shader/ShaderHelper.java b/src/main/java/com/simibubi/create/foundation/render/shader/ShaderHelper.java index 63e79bcf4..e0f915231 100644 --- a/src/main/java/com/simibubi/create/foundation/render/shader/ShaderHelper.java +++ b/src/main/java/com/simibubi/create/foundation/render/shader/ShaderHelper.java @@ -31,7 +31,7 @@ public class ShaderHelper { public static final Logger log = LogManager.getLogger("shader"); - public static final FloatBuffer FLOAT_BUFFER = MemoryUtil.memAllocFloat(1); + public static final FloatBuffer FLOAT_BUFFER = MemoryUtil.memAllocFloat(1); // TODO: these leak 80 bytes of memory per program launch public static final FloatBuffer VEC3_BUFFER = MemoryUtil.memAllocFloat(3); public static final FloatBuffer MATRIX_BUFFER = MemoryUtil.memAllocFloat(16);