From f7c45e5486e312a38857c034778aee3ed8ba60a7 Mon Sep 17 00:00:00 2001 From: Jozufozu Date: Mon, 6 Dec 2021 23:36:14 -0800 Subject: [PATCH] Get started on a batching engine - An Engine is a MaterialManager and a RenderDispatcher - Refactor InstanceManager's ctor to use the MaterialManager interface instead of the concrete type - MaterialManagerImpl -> InstancingEngine - Add skeleton for BatchingEngine - Hack in InstanceWorld to switch between the 2 - Rename/move existing MaterialManager impl to new package --- .../backend/instancing/CPUInstancer.java | 39 ++++++++++++++ .../backend/instancing/InstanceManager.java | 8 ++- .../backend/instancing/InstanceWorld.java | 36 ++++++++----- .../entity/EntityInstanceManager.java | 4 +- .../instancing/tile/TileInstanceManager.java | 4 +- .../flywheel/backend/material/Engine.java | 4 ++ .../backend/material/RenderDispatcher.java | 28 ++++++++++ .../material/batching/BatchedMaterial.java | 46 ++++++++++++++++ .../batching/BatchedMaterialGroup.java | 52 ++++++++++++++++++ .../material/batching/BatchingEngine.java | 54 +++++++++++++++++++ .../material/batching/package-info.java | 6 +++ .../InstancedMaterial.java} | 8 +-- .../InstancedMaterialGroup.java} | 30 ++++++----- .../InstancedMaterialRenderer.java} | 8 +-- .../InstancingEngine.java} | 47 +++++++++------- .../flywheel/backend/struct/Batched.java | 13 +++++ .../backend/struct/BatchingTransformer.java | 11 ++++ .../flywheel/backend/struct/StructType.java | 2 + .../core/crumbling/CrumblingGroup.java | 12 ++--- .../crumbling/CrumblingInstanceManager.java | 4 +- .../core/crumbling/CrumblingRenderer.java | 21 ++++---- .../materials/model/ModelTransformer.java | 12 +++++ .../core/materials/model/ModelType.java | 10 +++- .../core/materials/oriented/OrientedType.java | 10 +++- .../flywheel/mixin/RenderHooksMixin.java | 8 +-- 25 files changed, 388 insertions(+), 89 deletions(-) create mode 100644 src/main/java/com/jozufozu/flywheel/backend/instancing/CPUInstancer.java create mode 100644 src/main/java/com/jozufozu/flywheel/backend/material/Engine.java create mode 100644 src/main/java/com/jozufozu/flywheel/backend/material/RenderDispatcher.java create mode 100644 src/main/java/com/jozufozu/flywheel/backend/material/batching/BatchedMaterial.java create mode 100644 src/main/java/com/jozufozu/flywheel/backend/material/batching/BatchedMaterialGroup.java create mode 100644 src/main/java/com/jozufozu/flywheel/backend/material/batching/BatchingEngine.java create mode 100644 src/main/java/com/jozufozu/flywheel/backend/material/batching/package-info.java rename src/main/java/com/jozufozu/flywheel/backend/material/{MaterialImpl.java => instancing/InstancedMaterial.java} (87%) rename src/main/java/com/jozufozu/flywheel/backend/material/{MaterialGroupImpl.java => instancing/InstancedMaterialGroup.java} (52%) rename src/main/java/com/jozufozu/flywheel/backend/material/{MaterialRenderer.java => instancing/InstancedMaterialRenderer.java} (78%) rename src/main/java/com/jozufozu/flywheel/backend/material/{MaterialManagerImpl.java => instancing/InstancingEngine.java} (72%) create mode 100644 src/main/java/com/jozufozu/flywheel/backend/struct/Batched.java create mode 100644 src/main/java/com/jozufozu/flywheel/backend/struct/BatchingTransformer.java create mode 100644 src/main/java/com/jozufozu/flywheel/core/materials/model/ModelTransformer.java diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/CPUInstancer.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/CPUInstancer.java new file mode 100644 index 000000000..eadfa9db8 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/CPUInstancer.java @@ -0,0 +1,39 @@ +package com.jozufozu.flywheel.backend.instancing; + +import com.jozufozu.flywheel.backend.struct.BatchingTransformer; +import com.jozufozu.flywheel.backend.struct.StructType; +import com.jozufozu.flywheel.core.model.IModel; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; + +public class CPUInstancer extends AbstractInstancer { + + private final BatchingTransformer renderer; + + public CPUInstancer(StructType type, IModel modelData) { + super(type, modelData); + + renderer = type.asBatched() + .getTransformer(modelData); + } + + public void drawAll(PoseStack stack, VertexConsumer buffer) { + if (renderer == null) { + return; + } + + renderSetup(); + + for (D d : data) { + renderer.draw(d, stack, buffer); + } + } + + protected void renderSetup() { + if (anyToRemove) { + removeDeletedInstances(); + } + + anyToRemove = anyToUpdate = false; + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceManager.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceManager.java index b10936ca6..cece70c00 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceManager.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceManager.java @@ -10,7 +10,7 @@ import javax.annotation.Nullable; import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.material.MaterialManager; -import com.jozufozu.flywheel.backend.material.MaterialManagerImpl; +import com.jozufozu.flywheel.backend.material.instancing.InstancingEngine; import com.jozufozu.flywheel.light.LightUpdater; import com.mojang.math.Vector3f; @@ -19,7 +19,7 @@ import net.minecraft.client.Camera; import net.minecraft.core.BlockPos; import net.minecraft.util.Mth; -public abstract class InstanceManager implements MaterialManagerImpl.OriginShiftListener { +public abstract class InstanceManager implements InstancingEngine.OriginShiftListener { public final MaterialManager materialManager; @@ -33,7 +33,7 @@ public abstract class InstanceManager implements MaterialManagerImpl.OriginSh protected int frame; protected int tick; - public InstanceManager(MaterialManagerImpl materialManager) { + public InstanceManager(MaterialManager materialManager) { this.materialManager = materialManager; this.queuedUpdates = new HashSet<>(64); this.queuedAdditions = new HashSet<>(64); @@ -41,8 +41,6 @@ public abstract class InstanceManager implements MaterialManagerImpl.OriginSh this.dynamicInstances = new Object2ObjectOpenHashMap<>(); this.tickableInstances = new Object2ObjectOpenHashMap<>(); - - materialManager.addListener(this); } /** diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceWorld.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceWorld.java index 4f1d0f8a6..391b36824 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceWorld.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceWorld.java @@ -2,8 +2,9 @@ package com.jozufozu.flywheel.backend.instancing; import com.jozufozu.flywheel.backend.instancing.entity.EntityInstanceManager; import com.jozufozu.flywheel.backend.instancing.tile.TileInstanceManager; -import com.jozufozu.flywheel.backend.material.MaterialManager; -import com.jozufozu.flywheel.backend.material.MaterialManagerImpl; +import com.jozufozu.flywheel.backend.material.Engine; +import com.jozufozu.flywheel.backend.material.instancing.InstancingEngine; +import com.jozufozu.flywheel.backend.material.batching.BatchingEngine; import com.jozufozu.flywheel.core.Contexts; import com.jozufozu.flywheel.core.shader.WorldProgram; import com.jozufozu.flywheel.event.BeginFrameEvent; @@ -22,20 +23,29 @@ import net.minecraft.world.level.block.entity.BlockEntity; *

*/ public class InstanceWorld { - protected final MaterialManagerImpl materialManager; + protected final Engine engine; protected final InstanceManager entityInstanceManager; protected final InstanceManager tileEntityInstanceManager; public InstanceWorld() { - materialManager = MaterialManagerImpl.builder(Contexts.WORLD) - .build(); - entityInstanceManager = new EntityInstanceManager(materialManager); - tileEntityInstanceManager = new TileInstanceManager(materialManager); - } + boolean batching = false; - public MaterialManager getMaterialManager() { - return materialManager; + if (batching) { + engine = new BatchingEngine(); + entityInstanceManager = new EntityInstanceManager(engine); + tileEntityInstanceManager = new TileInstanceManager(engine); + } else { + InstancingEngine manager = InstancingEngine.builder(Contexts.WORLD) + .build(); + + entityInstanceManager = new EntityInstanceManager(manager); + tileEntityInstanceManager = new TileInstanceManager(manager); + + manager.addListener(entityInstanceManager); + manager.addListener(tileEntityInstanceManager); + engine = manager; + } } public InstanceManager getEntityInstanceManager() { @@ -50,7 +60,7 @@ public class InstanceWorld { * Free all acquired resources and invalidate this instance world. */ public void delete() { - materialManager.delete(); + engine.delete(); } /** @@ -73,7 +83,7 @@ public class InstanceWorld { *

*/ public void beginFrame(BeginFrameEvent event) { - materialManager.beginFrame(event.getInfo()); + engine.beginFrame(event.getInfo()); tileEntityInstanceManager.beginFrame(event.getInfo()); entityInstanceManager.beginFrame(event.getInfo()); @@ -99,6 +109,6 @@ public class InstanceWorld { * Draw the given layer. */ public void renderLayer(RenderLayerEvent event) { - materialManager.render(event.layer, event.viewProjection, event.camX, event.camY, event.camZ); + engine.render(event, event.buffers.bufferSource()); } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityInstanceManager.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityInstanceManager.java index db9ba49ec..cb3759e5b 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityInstanceManager.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityInstanceManager.java @@ -4,7 +4,7 @@ import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.instancing.AbstractInstance; import com.jozufozu.flywheel.backend.instancing.InstanceManager; import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry; -import com.jozufozu.flywheel.backend.material.MaterialManagerImpl; +import com.jozufozu.flywheel.backend.material.MaterialManager; import net.minecraft.core.BlockPos; import net.minecraft.world.entity.Entity; @@ -13,7 +13,7 @@ import net.minecraft.world.level.Level; public class EntityInstanceManager extends InstanceManager { - public EntityInstanceManager(MaterialManagerImpl materialManager) { + public EntityInstanceManager(MaterialManager materialManager) { super(materialManager); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/tile/TileInstanceManager.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/tile/TileInstanceManager.java index 40505b260..234c2d7cb 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/tile/TileInstanceManager.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/tile/TileInstanceManager.java @@ -4,7 +4,7 @@ import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.instancing.AbstractInstance; import com.jozufozu.flywheel.backend.instancing.InstanceManager; import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry; -import com.jozufozu.flywheel.backend.material.MaterialManagerImpl; +import com.jozufozu.flywheel.backend.material.MaterialManager; import net.minecraft.core.BlockPos; import net.minecraft.world.level.BlockGetter; @@ -13,7 +13,7 @@ import net.minecraft.world.level.block.entity.BlockEntity; public class TileInstanceManager extends InstanceManager { - public TileInstanceManager(MaterialManagerImpl materialManager) { + public TileInstanceManager(MaterialManager materialManager) { super(materialManager); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/material/Engine.java b/src/main/java/com/jozufozu/flywheel/backend/material/Engine.java new file mode 100644 index 000000000..215764bfb --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/material/Engine.java @@ -0,0 +1,4 @@ +package com.jozufozu.flywheel.backend.material; + +public interface Engine extends RenderDispatcher, MaterialManager { +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/material/RenderDispatcher.java b/src/main/java/com/jozufozu/flywheel/backend/material/RenderDispatcher.java new file mode 100644 index 000000000..a528d0f0f --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/material/RenderDispatcher.java @@ -0,0 +1,28 @@ +package com.jozufozu.flywheel.backend.material; + +import com.jozufozu.flywheel.backend.state.RenderLayer; +import com.jozufozu.flywheel.event.RenderLayerEvent; + +import net.minecraft.client.Camera; +import net.minecraft.client.renderer.MultiBufferSource; + +public interface RenderDispatcher { + /** + * Render every model for every material. + * + * @param layer Which of the 3 {@link RenderLayer render layers} is being drawn? + * @param viewProjection How do we get from camera space to clip space? + */ + void render(RenderLayerEvent event, MultiBufferSource buffers); + + /** + * Maintain the integer origin coordinate to be within a certain distance from the camera in all directions. + *

+ * This prevents floating point precision issues at high coordinates. + */ + void beginFrame(Camera info); + + default void delete() { + + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/material/batching/BatchedMaterial.java b/src/main/java/com/jozufozu/flywheel/backend/material/batching/BatchedMaterial.java new file mode 100644 index 000000000..96a93766a --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/material/batching/BatchedMaterial.java @@ -0,0 +1,46 @@ +package com.jozufozu.flywheel.backend.material.batching; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.Supplier; + +import com.jozufozu.flywheel.backend.instancing.CPUInstancer; +import com.jozufozu.flywheel.backend.instancing.InstanceData; +import com.jozufozu.flywheel.backend.instancing.Instancer; +import com.jozufozu.flywheel.backend.material.Material; +import com.jozufozu.flywheel.backend.material.MaterialSpec; +import com.jozufozu.flywheel.backend.struct.StructType; +import com.jozufozu.flywheel.core.model.IModel; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; + +public class BatchedMaterial implements Material { + + protected final Map> models; + private final StructType type; + + public BatchedMaterial(MaterialSpec spec) { + type = spec.getInstanceType(); + + this.models = new HashMap<>(); + } + + @Override + public Instancer model(Object key, Supplier modelSupplier) { + return models.computeIfAbsent(key, $ -> new CPUInstancer<>(type, modelSupplier.get())); + } + + public void render(PoseStack stack, VertexConsumer buffer) { + for (CPUInstancer instancer : models.values()) { + instancer.drawAll(stack, buffer); + } + } + + /** + * Clear all instance data without freeing resources. + */ + public void clear() { + models.values() + .forEach(CPUInstancer::clear); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/material/batching/BatchedMaterialGroup.java b/src/main/java/com/jozufozu/flywheel/backend/material/batching/BatchedMaterialGroup.java new file mode 100644 index 000000000..b843897dd --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/material/batching/BatchedMaterialGroup.java @@ -0,0 +1,52 @@ +package com.jozufozu.flywheel.backend.material.batching; + +import java.util.HashMap; +import java.util.Map; + +import com.jozufozu.flywheel.backend.instancing.InstanceData; +import com.jozufozu.flywheel.backend.material.MaterialGroup; +import com.jozufozu.flywheel.backend.material.MaterialSpec; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; + +public class BatchedMaterialGroup implements MaterialGroup { + + protected final RenderType state; + + private final Map, BatchedMaterial> materials = new HashMap<>(); + + public BatchedMaterialGroup(RenderType state) { + this.state = state; + } + + /** + * Get the material as defined by the given {@link MaterialSpec spec}. + * @param spec The material you want to create instances with. + * @param The type representing the per instance data. + * @return A + */ + @SuppressWarnings("unchecked") + @Override + public BatchedMaterial material(MaterialSpec spec) { + return (BatchedMaterial) materials.computeIfAbsent(spec, BatchedMaterial::new); + } + + public void render(PoseStack stack, MultiBufferSource source) { + VertexConsumer buffer = source.getBuffer(state); + + for (BatchedMaterial value : materials.values()) { + value.render(stack, buffer); + } + } + + public void clear() { + materials.values().forEach(BatchedMaterial::clear); + } + + public void delete() { + materials.clear(); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/material/batching/BatchingEngine.java b/src/main/java/com/jozufozu/flywheel/backend/material/batching/BatchingEngine.java new file mode 100644 index 000000000..c7d0d3354 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/material/batching/BatchingEngine.java @@ -0,0 +1,54 @@ +package com.jozufozu.flywheel.backend.material.batching; + +import java.util.EnumMap; +import java.util.HashMap; +import java.util.Map; + +import com.jozufozu.flywheel.backend.material.Engine; +import com.jozufozu.flywheel.backend.material.MaterialGroup; +import com.jozufozu.flywheel.backend.state.RenderLayer; +import com.jozufozu.flywheel.event.RenderLayerEvent; + +import net.minecraft.client.Camera; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Vec3i; + +public class BatchingEngine implements Engine { + + protected BlockPos originCoordinate = BlockPos.ZERO; + + protected final Map> layers; + + public BatchingEngine() { + this.layers = new EnumMap<>(RenderLayer.class); + for (RenderLayer value : RenderLayer.values()) { + layers.put(value, new HashMap<>()); + } + } + + @Override + public MaterialGroup state(RenderLayer layer, RenderType state) { + return layers.get(layer).computeIfAbsent(state, BatchedMaterialGroup::new); + } + + @Override + public Vec3i getOriginCoordinate() { + return originCoordinate; + } + + @Override + public void render(RenderLayerEvent event, MultiBufferSource buffers) { + for (Map.Entry entry : layers.get(event.getLayer()).entrySet()) { + BatchedMaterialGroup group = entry.getValue(); + + group.render(event.stack, buffers); + } + } + + @Override + public void beginFrame(Camera info) { + + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/material/batching/package-info.java b/src/main/java/com/jozufozu/flywheel/backend/material/batching/package-info.java new file mode 100644 index 000000000..c9e565892 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/material/batching/package-info.java @@ -0,0 +1,6 @@ +@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault +package com.jozufozu.flywheel.backend.material.batching; + +import javax.annotation.ParametersAreNonnullByDefault; + +import net.minecraft.MethodsReturnNonnullByDefault; diff --git a/src/main/java/com/jozufozu/flywheel/backend/material/MaterialImpl.java b/src/main/java/com/jozufozu/flywheel/backend/material/instancing/InstancedMaterial.java similarity index 87% rename from src/main/java/com/jozufozu/flywheel/backend/material/MaterialImpl.java rename to src/main/java/com/jozufozu/flywheel/backend/material/instancing/InstancedMaterial.java index acef52c2c..c0704162f 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/material/MaterialImpl.java +++ b/src/main/java/com/jozufozu/flywheel/backend/material/instancing/InstancedMaterial.java @@ -1,4 +1,4 @@ -package com.jozufozu.flywheel.backend.material; +package com.jozufozu.flywheel.backend.material.instancing; import java.util.concurrent.ExecutionException; import java.util.function.Supplier; @@ -9,6 +9,8 @@ import com.jozufozu.flywheel.backend.RenderWork; import com.jozufozu.flywheel.backend.instancing.GPUInstancer; import com.jozufozu.flywheel.backend.instancing.InstanceData; import com.jozufozu.flywheel.backend.instancing.Instancer; +import com.jozufozu.flywheel.backend.material.Material; +import com.jozufozu.flywheel.backend.material.MaterialSpec; import com.jozufozu.flywheel.backend.model.ModelPool; import com.jozufozu.flywheel.backend.struct.StructType; import com.jozufozu.flywheel.core.model.IModel; @@ -17,13 +19,13 @@ import com.jozufozu.flywheel.core.model.IModel; * A collection of Instancers that all have the same format. * @param */ -public class MaterialImpl implements Material { +public class InstancedMaterial implements Material { final ModelPool modelPool; protected final Cache> models; protected final StructType type; - public MaterialImpl(MaterialSpec spec) { + public InstancedMaterial(MaterialSpec spec) { this.type = spec.getInstanceType(); modelPool = new ModelPool(spec.getModelFormat(), 64); diff --git a/src/main/java/com/jozufozu/flywheel/backend/material/MaterialGroupImpl.java b/src/main/java/com/jozufozu/flywheel/backend/material/instancing/InstancedMaterialGroup.java similarity index 52% rename from src/main/java/com/jozufozu/flywheel/backend/material/MaterialGroupImpl.java rename to src/main/java/com/jozufozu/flywheel/backend/material/instancing/InstancedMaterialGroup.java index f8c8405c3..5933a97d0 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/material/MaterialGroupImpl.java +++ b/src/main/java/com/jozufozu/flywheel/backend/material/instancing/InstancedMaterialGroup.java @@ -1,10 +1,12 @@ -package com.jozufozu.flywheel.backend.material; +package com.jozufozu.flywheel.backend.material.instancing; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import com.jozufozu.flywheel.backend.instancing.InstanceData; +import com.jozufozu.flywheel.backend.material.MaterialGroup; +import com.jozufozu.flywheel.backend.material.MaterialSpec; import com.jozufozu.flywheel.core.shader.WorldProgram; import com.jozufozu.flywheel.util.TextureBinder; import com.mojang.math.Matrix4f; @@ -17,15 +19,15 @@ import net.minecraft.client.renderer.RenderType; * The children of a material group will all be rendered at the same time. * No guarantees are made about the order of draw calls. */ -public class MaterialGroupImpl

implements MaterialGroup { +public class InstancedMaterialGroup

implements MaterialGroup { - protected final MaterialManagerImpl

owner; + protected final InstancingEngine

owner; - protected final ArrayList> renderers = new ArrayList<>(); + protected final ArrayList> renderers = new ArrayList<>(); - private final Map, MaterialImpl> materials = new HashMap<>(); + private final Map, InstancedMaterial> materials = new HashMap<>(); - public MaterialGroupImpl(MaterialManagerImpl

owner) { + public InstancedMaterialGroup(InstancingEngine

owner) { this.owner = owner; } @@ -37,14 +39,14 @@ public class MaterialGroupImpl

implements MaterialGroup */ @SuppressWarnings("unchecked") @Override - public MaterialImpl material(MaterialSpec spec) { - return (MaterialImpl) materials.computeIfAbsent(spec, this::createInstanceMaterial); + public InstancedMaterial material(MaterialSpec spec) { + return (InstancedMaterial) materials.computeIfAbsent(spec, this::createInstanceMaterial); } public void render(RenderType type, Matrix4f viewProjection, double camX, double camY, double camZ) { type.setupRenderState(); TextureBinder.bindActiveTextures(); - for (MaterialRenderer

renderer : renderers) { + for (InstancedMaterialRenderer

renderer : renderers) { renderer.render(viewProjection, camX, camY, camZ); } type.clearRenderState(); @@ -55,21 +57,21 @@ public class MaterialGroupImpl

implements MaterialGroup } public void clear() { - materials.values().forEach(MaterialImpl::clear); + materials.values().forEach(InstancedMaterial::clear); } public void delete() { materials.values() - .forEach(MaterialImpl::delete); + .forEach(InstancedMaterial::delete); materials.clear(); renderers.clear(); } - private MaterialImpl createInstanceMaterial(MaterialSpec type) { - MaterialImpl material = new MaterialImpl<>(type); + private InstancedMaterial createInstanceMaterial(MaterialSpec type) { + InstancedMaterial material = new InstancedMaterial<>(type); - this.renderers.add(new MaterialRenderer<>(owner.getProgram(type.getProgramName()), material, this::setup)); + this.renderers.add(new InstancedMaterialRenderer<>(owner.getProgram(type.getProgramName()), material, this::setup)); return material; } diff --git a/src/main/java/com/jozufozu/flywheel/backend/material/MaterialRenderer.java b/src/main/java/com/jozufozu/flywheel/backend/material/instancing/InstancedMaterialRenderer.java similarity index 78% rename from src/main/java/com/jozufozu/flywheel/backend/material/MaterialRenderer.java rename to src/main/java/com/jozufozu/flywheel/backend/material/instancing/InstancedMaterialRenderer.java index bbffa0881..ac8c64e16 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/material/MaterialRenderer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/material/instancing/InstancedMaterialRenderer.java @@ -1,4 +1,4 @@ -package com.jozufozu.flywheel.backend.material; +package com.jozufozu.flywheel.backend.material.instancing; import java.util.Collection; import java.util.function.Consumer; @@ -8,14 +8,14 @@ import com.jozufozu.flywheel.backend.instancing.GPUInstancer; import com.jozufozu.flywheel.core.shader.WorldProgram; import com.mojang.math.Matrix4f; -public class MaterialRenderer

{ +public class InstancedMaterialRenderer

{ protected final Supplier

program; - protected final MaterialImpl material; + protected final InstancedMaterial material; protected final Consumer

setupFunc; - public MaterialRenderer(Supplier

programSupplier, MaterialImpl material, Consumer

setupFunc) { + public InstancedMaterialRenderer(Supplier

programSupplier, InstancedMaterial material, Consumer

setupFunc) { this.program = programSupplier; this.material = material; this.setupFunc = setupFunc; diff --git a/src/main/java/com/jozufozu/flywheel/backend/material/MaterialManagerImpl.java b/src/main/java/com/jozufozu/flywheel/backend/material/instancing/InstancingEngine.java similarity index 72% rename from src/main/java/com/jozufozu/flywheel/backend/material/MaterialManagerImpl.java rename to src/main/java/com/jozufozu/flywheel/backend/material/instancing/InstancingEngine.java index 7e5cca536..25fa707c9 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/material/MaterialManagerImpl.java +++ b/src/main/java/com/jozufozu/flywheel/backend/material/instancing/InstancingEngine.java @@ -1,4 +1,4 @@ -package com.jozufozu.flywheel.backend.material; +package com.jozufozu.flywheel.backend.material.instancing; import java.util.EnumMap; import java.util.HashMap; @@ -7,20 +7,24 @@ import java.util.function.Supplier; import com.jozufozu.flywheel.backend.gl.GlVertexArray; import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType; +import com.jozufozu.flywheel.backend.material.Engine; +import com.jozufozu.flywheel.backend.material.MaterialGroup; import com.jozufozu.flywheel.backend.state.RenderLayer; import com.jozufozu.flywheel.core.WorldContext; import com.jozufozu.flywheel.core.shader.WorldProgram; +import com.jozufozu.flywheel.event.RenderLayerEvent; import com.jozufozu.flywheel.util.WeakHashSet; import com.mojang.math.Matrix4f; import net.minecraft.client.Camera; +import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.core.BlockPos; import net.minecraft.core.Vec3i; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.Mth; -public class MaterialManagerImpl

implements MaterialManager { +public class InstancingEngine

implements Engine { public static int MAX_ORIGIN_DISTANCE = 100; @@ -30,19 +34,19 @@ public class MaterialManagerImpl

implements MaterialMana protected final GroupFactory

groupFactory; protected final boolean ignoreOriginCoordinate; - protected final Map>> layers; + protected final Map>> layers; private final WeakHashSet listeners; - public MaterialManagerImpl(WorldContext

context) { - this(context, MaterialGroupImpl::new, false); + public InstancingEngine(WorldContext

context) { + this(context, InstancedMaterialGroup::new, false); } public static

Builder

builder(WorldContext

context) { return new Builder<>(context); } - public MaterialManagerImpl(WorldContext

context, GroupFactory

groupFactory, boolean ignoreOriginCoordinate) { + public InstancingEngine(WorldContext

context, GroupFactory

groupFactory, boolean ignoreOriginCoordinate) { this.context = context; this.ignoreOriginCoordinate = ignoreOriginCoordinate; @@ -69,10 +73,13 @@ public class MaterialManagerImpl

implements MaterialMana /** * Render every model for every material. - * @param layer Which of the 3 {@link RenderLayer render layers} is being drawn? - * @param viewProjection How do we get from camera space to clip space? */ - public void render(RenderLayer layer, Matrix4f viewProjection, double camX, double camY, double camZ) { + @Override + public void render(RenderLayerEvent event, MultiBufferSource buffers) { + double camX = event.camX; + double camY = event.camY; + double camZ = event.camZ; + Matrix4f viewProjection = event.viewProjection; if (!ignoreOriginCoordinate) { camX -= originCoordinate.getX(); camY -= originCoordinate.getY(); @@ -85,9 +92,9 @@ public class MaterialManagerImpl

implements MaterialMana viewProjection = translate; } - for (Map.Entry> entry : layers.get(layer).entrySet()) { + for (Map.Entry> entry : layers.get(event.getLayer()).entrySet()) { RenderType state = entry.getKey(); - MaterialGroupImpl

group = entry.getValue(); + InstancedMaterialGroup

group = entry.getValue(); group.render(state, viewProjection, camX, camY, camZ); } @@ -97,10 +104,11 @@ public class MaterialManagerImpl

implements MaterialMana GlVertexArray.unbind(); } + @Override public void delete() { - for (Map> groups : layers.values()) { + for (Map> groups : layers.values()) { - groups.values().forEach(MaterialGroupImpl::delete); + groups.values().forEach(InstancedMaterialGroup::delete); } } @@ -122,6 +130,7 @@ public class MaterialManagerImpl

implements MaterialMana * * This prevents floating point precision issues at high coordinates. */ + @Override public void beginFrame(Camera info) { int cX = Mth.floor(info.getPosition().x); int cY = Mth.floor(info.getPosition().y); @@ -135,8 +144,8 @@ public class MaterialManagerImpl

implements MaterialMana originCoordinate = new BlockPos(cX, cY, cZ); - for (Map> groups : layers.values()) { - groups.values().forEach(MaterialGroupImpl::clear); + for (Map> groups : layers.values()) { + groups.values().forEach(InstancedMaterialGroup::clear); } listeners.forEach(OriginShiftListener::onOriginShift); @@ -150,12 +159,12 @@ public class MaterialManagerImpl

implements MaterialMana @FunctionalInterface public interface GroupFactory

{ - MaterialGroupImpl

create(MaterialManagerImpl

materialManager); + InstancedMaterialGroup

create(InstancingEngine

materialManager); } public static class Builder

{ protected final WorldContext

context; - protected GroupFactory

groupFactory = MaterialGroupImpl::new; + protected GroupFactory

groupFactory = InstancedMaterialGroup::new; protected boolean ignoreOriginCoordinate; public Builder(WorldContext

context) { @@ -172,8 +181,8 @@ public class MaterialManagerImpl

implements MaterialMana return this; } - public MaterialManagerImpl

build() { - return new MaterialManagerImpl<>(context, groupFactory, ignoreOriginCoordinate); + public InstancingEngine

build() { + return new InstancingEngine<>(context, groupFactory, ignoreOriginCoordinate); } } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/struct/Batched.java b/src/main/java/com/jozufozu/flywheel/backend/struct/Batched.java new file mode 100644 index 000000000..d3b1f6724 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/struct/Batched.java @@ -0,0 +1,13 @@ +package com.jozufozu.flywheel.backend.struct; + +import com.jozufozu.flywheel.core.model.IModel; + +public interface Batched extends StructType { + + BatchingTransformer getTransformer(IModel model); + + @Override + default Batched asBatched() { + return this; + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/struct/BatchingTransformer.java b/src/main/java/com/jozufozu/flywheel/backend/struct/BatchingTransformer.java new file mode 100644 index 000000000..75f709761 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/struct/BatchingTransformer.java @@ -0,0 +1,11 @@ +package com.jozufozu.flywheel.backend.struct; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; + +public abstract class BatchingTransformer { + + public void draw(S s, PoseStack stack, VertexConsumer consumer) { + + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/struct/StructType.java b/src/main/java/com/jozufozu/flywheel/backend/struct/StructType.java index fc1d7be41..6591a5faa 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/struct/StructType.java +++ b/src/main/java/com/jozufozu/flywheel/backend/struct/StructType.java @@ -19,4 +19,6 @@ public interface StructType { VertexFormat format(); Writeable asWriteable(); + + Batched asBatched(); } diff --git a/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingGroup.java b/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingGroup.java index cf096be15..58f6c4d88 100644 --- a/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingGroup.java +++ b/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingGroup.java @@ -1,8 +1,8 @@ package com.jozufozu.flywheel.core.crumbling; -import com.jozufozu.flywheel.backend.material.MaterialGroupImpl; -import com.jozufozu.flywheel.backend.material.MaterialManagerImpl; -import com.jozufozu.flywheel.backend.material.MaterialRenderer; +import com.jozufozu.flywheel.backend.material.instancing.InstancedMaterialGroup; +import com.jozufozu.flywheel.backend.material.instancing.InstancingEngine; +import com.jozufozu.flywheel.backend.material.instancing.InstancedMaterialRenderer; import com.jozufozu.flywheel.core.atlas.AtlasInfo; import com.jozufozu.flywheel.core.atlas.SheetData; import com.jozufozu.flywheel.util.RenderTextures; @@ -13,12 +13,12 @@ import com.mojang.math.Matrix4f; import net.minecraft.client.renderer.RenderType; import net.minecraft.resources.ResourceLocation; -public class CrumblingGroup

extends MaterialGroupImpl

{ +public class CrumblingGroup

extends InstancedMaterialGroup

{ private int width; private int height; - public CrumblingGroup(MaterialManagerImpl

owner) { + public CrumblingGroup(InstancingEngine

owner) { super(owner); } @@ -40,7 +40,7 @@ public class CrumblingGroup

extends MaterialGroupImp RenderSystem.setShaderTexture(4, breakingTex); TextureBinder.bindActiveTextures(); - for (MaterialRenderer

renderer : renderers) { + for (InstancedMaterialRenderer

renderer : renderers) { renderer.render(viewProjection, camX, camY, camZ); } diff --git a/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingInstanceManager.java b/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingInstanceManager.java index 814b83af6..75e75247c 100644 --- a/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingInstanceManager.java +++ b/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingInstanceManager.java @@ -1,13 +1,13 @@ package com.jozufozu.flywheel.core.crumbling; import com.jozufozu.flywheel.backend.instancing.tile.TileInstanceManager; -import com.jozufozu.flywheel.backend.material.MaterialManagerImpl; +import com.jozufozu.flywheel.backend.material.MaterialManager; import net.minecraft.core.BlockPos; public class CrumblingInstanceManager extends TileInstanceManager { - public CrumblingInstanceManager(MaterialManagerImpl materialManager) { + public CrumblingInstanceManager(MaterialManager materialManager) { super(materialManager); } diff --git a/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingRenderer.java b/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingRenderer.java index a91049aec..2844df589 100644 --- a/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingRenderer.java +++ b/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingRenderer.java @@ -6,17 +6,15 @@ import java.util.SortedSet; import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.gl.GlTextureUnit; -import com.jozufozu.flywheel.backend.gl.error.GlError; import com.jozufozu.flywheel.backend.instancing.InstanceManager; -import com.jozufozu.flywheel.backend.material.MaterialManagerImpl; -import com.jozufozu.flywheel.backend.state.RenderLayer; +import com.jozufozu.flywheel.backend.material.instancing.InstancingEngine; import com.jozufozu.flywheel.core.Contexts; import com.jozufozu.flywheel.event.ReloadRenderersEvent; +import com.jozufozu.flywheel.event.RenderLayerEvent; import com.jozufozu.flywheel.mixin.LevelRendererAccessor; import com.jozufozu.flywheel.util.Lazy; import com.jozufozu.flywheel.util.Pair; import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.math.Matrix4f; import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; @@ -55,17 +53,17 @@ public class CrumblingRenderer { INVALIDATOR = state.getSecond(); } - public static void renderBreaking(ClientLevel world, Matrix4f viewProjection, double cameraX, double cameraY, double cameraZ) { + public static void renderBreaking(RenderLayerEvent event) { if (!Backend.getInstance() - .canUseInstancing(world)) return; + .canUseInstancing(event.getWorld())) return; - Int2ObjectMap> activeStages = getActiveStageTiles(world); + Int2ObjectMap> activeStages = getActiveStageTiles(event.getWorld()); if (activeStages.isEmpty()) return; State state = STATE.get(); InstanceManager instanceManager = state.instanceManager; - MaterialManagerImpl materials = state.materialManager; + InstancingEngine materials = state.materialManager; TextureManager textureManager = Minecraft.getInstance().getTextureManager(); Camera info = Minecraft.getInstance().gameRenderer.getMainCamera(); @@ -79,7 +77,7 @@ public class CrumblingRenderer { instanceManager.beginFrame(info); - materials.render(RenderLayer.SOLID, viewProjection, cameraX, cameraY, cameraZ); + materials.render(event, null); instanceManager.invalidate(); } @@ -133,14 +131,15 @@ public class CrumblingRenderer { } private static class State { - private final MaterialManagerImpl materialManager; + private final InstancingEngine materialManager; private final InstanceManager instanceManager; private State() { - materialManager = MaterialManagerImpl.builder(Contexts.CRUMBLING) + materialManager = InstancingEngine.builder(Contexts.CRUMBLING) .setGroupFactory(CrumblingGroup::new) .build(); instanceManager = new CrumblingInstanceManager(materialManager); + materialManager.addListener(instanceManager); } private void kill() { diff --git a/src/main/java/com/jozufozu/flywheel/core/materials/model/ModelTransformer.java b/src/main/java/com/jozufozu/flywheel/core/materials/model/ModelTransformer.java new file mode 100644 index 000000000..941df358b --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/materials/model/ModelTransformer.java @@ -0,0 +1,12 @@ +package com.jozufozu.flywheel.core.materials.model; + +import com.jozufozu.flywheel.backend.struct.BatchingTransformer; +import com.jozufozu.flywheel.core.model.IModel; + +public class ModelTransformer extends BatchingTransformer { + public ModelTransformer(IModel model) { + + + //model.buffer(); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/core/materials/model/ModelType.java b/src/main/java/com/jozufozu/flywheel/core/materials/model/ModelType.java index 6c66b0833..9074fdf50 100644 --- a/src/main/java/com/jozufozu/flywheel/core/materials/model/ModelType.java +++ b/src/main/java/com/jozufozu/flywheel/core/materials/model/ModelType.java @@ -2,12 +2,15 @@ package com.jozufozu.flywheel.core.materials.model; import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat; import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; +import com.jozufozu.flywheel.backend.struct.Batched; +import com.jozufozu.flywheel.backend.struct.BatchingTransformer; import com.jozufozu.flywheel.backend.struct.StructWriter; import com.jozufozu.flywheel.backend.struct.Writeable; import com.jozufozu.flywheel.core.Formats; import com.jozufozu.flywheel.core.materials.model.writer.UnsafeModelWriter; +import com.jozufozu.flywheel.core.model.IModel; -public class ModelType implements Writeable { +public class ModelType implements Writeable, Batched { @Override public ModelData create() { @@ -23,4 +26,9 @@ public class ModelType implements Writeable { public StructWriter getWriter(VecBuffer backing) { return new UnsafeModelWriter(backing, this); } + + @Override + public BatchingTransformer getTransformer(IModel model) { + return null; + } } diff --git a/src/main/java/com/jozufozu/flywheel/core/materials/oriented/OrientedType.java b/src/main/java/com/jozufozu/flywheel/core/materials/oriented/OrientedType.java index 1d78185b9..468bbb597 100644 --- a/src/main/java/com/jozufozu/flywheel/core/materials/oriented/OrientedType.java +++ b/src/main/java/com/jozufozu/flywheel/core/materials/oriented/OrientedType.java @@ -2,12 +2,15 @@ package com.jozufozu.flywheel.core.materials.oriented; import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat; import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; +import com.jozufozu.flywheel.backend.struct.Batched; +import com.jozufozu.flywheel.backend.struct.BatchingTransformer; import com.jozufozu.flywheel.backend.struct.StructWriter; import com.jozufozu.flywheel.backend.struct.Writeable; import com.jozufozu.flywheel.core.Formats; import com.jozufozu.flywheel.core.materials.oriented.writer.UnsafeOrientedWriter; +import com.jozufozu.flywheel.core.model.IModel; -public class OrientedType implements Writeable { +public class OrientedType implements Writeable, Batched { @Override public OrientedData create() { @@ -23,4 +26,9 @@ public class OrientedType implements Writeable { public StructWriter getWriter(VecBuffer backing) { return new UnsafeOrientedWriter(backing, this); } + + @Override + public BatchingTransformer getTransformer(IModel model) { + return null; + } } diff --git a/src/main/java/com/jozufozu/flywheel/mixin/RenderHooksMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/RenderHooksMixin.java index 7a9c82540..482532474 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/RenderHooksMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/RenderHooksMixin.java @@ -82,13 +82,9 @@ public class RenderHooksMixin { if (!Backend.getInstance() .available()) return; - Matrix4f view = stack.last() - .pose(); - Matrix4f viewProjection = view.copy(); - viewProjection.multiplyBackward(RenderSystem.getProjectionMatrix()); - Vec3 cameraPos = info.getPosition(); - CrumblingRenderer.renderBreaking(level, viewProjection, cameraPos.x, cameraPos.y, cameraPos.z); + + CrumblingRenderer.renderBreaking(new RenderLayerEvent(level, null, stack, null, cameraPos.x, cameraPos.y, cameraPos.z)); if (!OptifineHandler.usingShaders()) GL20.glUseProgram(0); }