Merge branch '1.17/dev' into 1.18/dev

This commit is contained in:
Jozufozu 2021-12-07 21:19:06 -08:00
commit fd0343c48b
26 changed files with 388 additions and 90 deletions

View file

@ -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<D extends InstanceData> extends AbstractInstancer<D> {
private final BatchingTransformer<D> renderer;
public CPUInstancer(StructType<D> 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;
}
}

View file

@ -10,7 +10,7 @@ import javax.annotation.Nullable;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.material.MaterialManager; 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.jozufozu.flywheel.light.LightUpdater;
import com.mojang.math.Vector3f; import com.mojang.math.Vector3f;
@ -19,7 +19,7 @@ import net.minecraft.client.Camera;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
public abstract class InstanceManager<T> implements MaterialManagerImpl.OriginShiftListener { public abstract class InstanceManager<T> implements InstancingEngine.OriginShiftListener {
public final MaterialManager materialManager; public final MaterialManager materialManager;
@ -33,7 +33,7 @@ public abstract class InstanceManager<T> implements MaterialManagerImpl.OriginSh
protected int frame; protected int frame;
protected int tick; protected int tick;
public InstanceManager(MaterialManagerImpl<?> materialManager) { public InstanceManager(MaterialManager materialManager) {
this.materialManager = materialManager; this.materialManager = materialManager;
this.queuedUpdates = new HashSet<>(64); this.queuedUpdates = new HashSet<>(64);
this.queuedAdditions = new HashSet<>(64); this.queuedAdditions = new HashSet<>(64);
@ -41,8 +41,6 @@ public abstract class InstanceManager<T> implements MaterialManagerImpl.OriginSh
this.dynamicInstances = new Object2ObjectOpenHashMap<>(); this.dynamicInstances = new Object2ObjectOpenHashMap<>();
this.tickableInstances = new Object2ObjectOpenHashMap<>(); this.tickableInstances = new Object2ObjectOpenHashMap<>();
materialManager.addListener(this);
} }
/** /**

View file

@ -2,8 +2,9 @@ package com.jozufozu.flywheel.backend.instancing;
import com.jozufozu.flywheel.backend.instancing.entity.EntityInstanceManager; import com.jozufozu.flywheel.backend.instancing.entity.EntityInstanceManager;
import com.jozufozu.flywheel.backend.instancing.tile.TileInstanceManager; import com.jozufozu.flywheel.backend.instancing.tile.TileInstanceManager;
import com.jozufozu.flywheel.backend.material.MaterialManager; import com.jozufozu.flywheel.backend.material.Engine;
import com.jozufozu.flywheel.backend.material.MaterialManagerImpl; 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.Contexts;
import com.jozufozu.flywheel.core.shader.WorldProgram; import com.jozufozu.flywheel.core.shader.WorldProgram;
import com.jozufozu.flywheel.event.BeginFrameEvent; import com.jozufozu.flywheel.event.BeginFrameEvent;
@ -22,20 +23,28 @@ import net.minecraft.world.level.block.entity.BlockEntity;
* </p> * </p>
*/ */
public class InstanceWorld { public class InstanceWorld {
protected final MaterialManagerImpl<WorldProgram> materialManager; protected final Engine engine;
protected final InstanceManager<Entity> entityInstanceManager; protected final InstanceManager<Entity> entityInstanceManager;
protected final InstanceManager<BlockEntity> tileEntityInstanceManager; protected final InstanceManager<BlockEntity> tileEntityInstanceManager;
public InstanceWorld() { public InstanceWorld() {
materialManager = MaterialManagerImpl.builder(Contexts.WORLD) // TODO: finish impl
.build(); if (false) {
entityInstanceManager = new EntityInstanceManager(materialManager); engine = new BatchingEngine();
tileEntityInstanceManager = new TileInstanceManager(materialManager); entityInstanceManager = new EntityInstanceManager(engine);
} tileEntityInstanceManager = new TileInstanceManager(engine);
} else {
InstancingEngine<WorldProgram> manager = InstancingEngine.builder(Contexts.WORLD)
.build();
public MaterialManager getMaterialManager() { entityInstanceManager = new EntityInstanceManager(manager);
return materialManager; tileEntityInstanceManager = new TileInstanceManager(manager);
manager.addListener(entityInstanceManager);
manager.addListener(tileEntityInstanceManager);
engine = manager;
}
} }
public InstanceManager<Entity> getEntityInstanceManager() { public InstanceManager<Entity> getEntityInstanceManager() {
@ -50,7 +59,7 @@ public class InstanceWorld {
* Free all acquired resources and invalidate this instance world. * Free all acquired resources and invalidate this instance world.
*/ */
public void delete() { public void delete() {
materialManager.delete(); engine.delete();
} }
/** /**
@ -73,7 +82,7 @@ public class InstanceWorld {
* </p> * </p>
*/ */
public void beginFrame(BeginFrameEvent event) { public void beginFrame(BeginFrameEvent event) {
materialManager.beginFrame(event.getInfo()); engine.beginFrame(event.getInfo());
tileEntityInstanceManager.beginFrame(event.getInfo()); tileEntityInstanceManager.beginFrame(event.getInfo());
entityInstanceManager.beginFrame(event.getInfo()); entityInstanceManager.beginFrame(event.getInfo());
@ -99,6 +108,6 @@ public class InstanceWorld {
* Draw the given layer. * Draw the given layer.
*/ */
public void renderLayer(RenderLayerEvent event) { public void renderLayer(RenderLayerEvent event) {
materialManager.render(event.layer, event.viewProjection, event.camX, event.camY, event.camZ); engine.render(event, event.buffers.bufferSource());
} }
} }

View file

@ -4,7 +4,7 @@ import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.instancing.AbstractInstance; import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
import com.jozufozu.flywheel.backend.instancing.InstanceManager; import com.jozufozu.flywheel.backend.instancing.InstanceManager;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry; 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.core.BlockPos;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
@ -13,7 +13,7 @@ import net.minecraft.world.level.Level;
public class EntityInstanceManager extends InstanceManager<Entity> { public class EntityInstanceManager extends InstanceManager<Entity> {
public EntityInstanceManager(MaterialManagerImpl<?> materialManager) { public EntityInstanceManager(MaterialManager materialManager) {
super(materialManager); super(materialManager);
} }

View file

@ -4,7 +4,7 @@ import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.instancing.AbstractInstance; import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
import com.jozufozu.flywheel.backend.instancing.InstanceManager; import com.jozufozu.flywheel.backend.instancing.InstanceManager;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry; 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.core.BlockPos;
import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.BlockGetter;
@ -13,7 +13,7 @@ import net.minecraft.world.level.block.entity.BlockEntity;
public class TileInstanceManager extends InstanceManager<BlockEntity> { public class TileInstanceManager extends InstanceManager<BlockEntity> {
public TileInstanceManager(MaterialManagerImpl<?> materialManager) { public TileInstanceManager(MaterialManager materialManager) {
super(materialManager); super(materialManager);
} }

View file

@ -0,0 +1,4 @@
package com.jozufozu.flywheel.backend.material;
public interface Engine extends RenderDispatcher, MaterialManager {
}

View file

@ -11,7 +11,7 @@ public interface MaterialManager {
* Get a material group that will render in the given layer with the given state. * Get a material group that will render in the given layer with the given state.
* *
* @param layer The {@link RenderLayer} you want to draw in. * @param layer The {@link RenderLayer} you want to draw in.
* @param state The {@link net.minecraft.client.renderer.RenderType} you need to draw with. * @param state The {@link RenderType} you need to draw with.
* @return A material group whose children will * @return A material group whose children will
*/ */
MaterialGroup state(RenderLayer layer, RenderType state); MaterialGroup state(RenderLayer layer, RenderType state);

View file

@ -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.
* <p>
* This prevents floating point precision issues at high coordinates.
*/
void beginFrame(Camera info);
default void delete() {
}
}

View file

@ -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<D extends InstanceData> implements Material<D> {
protected final Map<Object, CPUInstancer<D>> models;
private final StructType<D> type;
public BatchedMaterial(MaterialSpec<D> spec) {
type = spec.getInstanceType();
this.models = new HashMap<>();
}
@Override
public Instancer<D> model(Object key, Supplier<IModel> modelSupplier) {
return models.computeIfAbsent(key, $ -> new CPUInstancer<>(type, modelSupplier.get()));
}
public void render(PoseStack stack, VertexConsumer buffer) {
for (CPUInstancer<D> instancer : models.values()) {
instancer.drawAll(stack, buffer);
}
}
/**
* Clear all instance data without freeing resources.
*/
public void clear() {
models.values()
.forEach(CPUInstancer::clear);
}
}

View file

@ -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<MaterialSpec<?>, 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 <D> The type representing the per instance data.
* @return A
*/
@SuppressWarnings("unchecked")
@Override
public <D extends InstanceData> BatchedMaterial<D> material(MaterialSpec<D> spec) {
return (BatchedMaterial<D>) 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();
}
}

View file

@ -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<RenderLayer, Map<RenderType, BatchedMaterialGroup>> 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<RenderType, BatchedMaterialGroup> entry : layers.get(event.getLayer()).entrySet()) {
BatchedMaterialGroup group = entry.getValue();
group.render(event.stack, buffers);
}
}
@Override
public void beginFrame(Camera info) {
}
}

View file

@ -0,0 +1,6 @@
@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault
package com.jozufozu.flywheel.backend.material.batching;
import javax.annotation.ParametersAreNonnullByDefault;
import net.minecraft.MethodsReturnNonnullByDefault;

View file

@ -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.concurrent.ExecutionException;
import java.util.function.Supplier; 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.GPUInstancer;
import com.jozufozu.flywheel.backend.instancing.InstanceData; import com.jozufozu.flywheel.backend.instancing.InstanceData;
import com.jozufozu.flywheel.backend.instancing.Instancer; 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.model.ModelPool;
import com.jozufozu.flywheel.backend.struct.StructType; import com.jozufozu.flywheel.backend.struct.StructType;
import com.jozufozu.flywheel.core.model.IModel; 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. * A collection of Instancers that all have the same format.
* @param <D> * @param <D>
*/ */
public class MaterialImpl<D extends InstanceData> implements Material<D> { public class InstancedMaterial<D extends InstanceData> implements Material<D> {
final ModelPool modelPool; final ModelPool modelPool;
protected final Cache<Object, GPUInstancer<D>> models; protected final Cache<Object, GPUInstancer<D>> models;
protected final StructType<D> type; protected final StructType<D> type;
public MaterialImpl(MaterialSpec<D> spec) { public InstancedMaterial(MaterialSpec<D> spec) {
this.type = spec.getInstanceType(); this.type = spec.getInstanceType();
modelPool = new ModelPool(spec.getModelFormat(), 64); modelPool = new ModelPool(spec.getModelFormat(), 64);

View file

@ -1,10 +1,12 @@
package com.jozufozu.flywheel.backend.material; package com.jozufozu.flywheel.backend.material.instancing;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import com.jozufozu.flywheel.backend.instancing.InstanceData; 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.core.shader.WorldProgram;
import com.jozufozu.flywheel.util.TextureBinder; import com.jozufozu.flywheel.util.TextureBinder;
import com.mojang.math.Matrix4f; 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. * The children of a material group will all be rendered at the same time.
* No guarantees are made about the order of draw calls. * No guarantees are made about the order of draw calls.
*/ */
public class MaterialGroupImpl<P extends WorldProgram> implements MaterialGroup { public class InstancedMaterialGroup<P extends WorldProgram> implements MaterialGroup {
protected final MaterialManagerImpl<P> owner; protected final InstancingEngine<P> owner;
protected final ArrayList<MaterialRenderer<P>> renderers = new ArrayList<>(); protected final ArrayList<InstancedMaterialRenderer<P>> renderers = new ArrayList<>();
private final Map<MaterialSpec<?>, MaterialImpl<?>> materials = new HashMap<>(); private final Map<MaterialSpec<?>, InstancedMaterial<?>> materials = new HashMap<>();
public MaterialGroupImpl(MaterialManagerImpl<P> owner) { public InstancedMaterialGroup(InstancingEngine<P> owner) {
this.owner = owner; this.owner = owner;
} }
@ -37,14 +39,14 @@ public class MaterialGroupImpl<P extends WorldProgram> implements MaterialGroup
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public <D extends InstanceData> MaterialImpl<D> material(MaterialSpec<D> spec) { public <D extends InstanceData> InstancedMaterial<D> material(MaterialSpec<D> spec) {
return (MaterialImpl<D>) materials.computeIfAbsent(spec, this::createInstanceMaterial); return (InstancedMaterial<D>) materials.computeIfAbsent(spec, this::createInstanceMaterial);
} }
public void render(RenderType type, Matrix4f viewProjection, double camX, double camY, double camZ) { public void render(RenderType type, Matrix4f viewProjection, double camX, double camY, double camZ) {
type.setupRenderState(); type.setupRenderState();
TextureBinder.bindActiveTextures(); TextureBinder.bindActiveTextures();
for (MaterialRenderer<P> renderer : renderers) { for (InstancedMaterialRenderer<P> renderer : renderers) {
renderer.render(viewProjection, camX, camY, camZ); renderer.render(viewProjection, camX, camY, camZ);
} }
type.clearRenderState(); type.clearRenderState();
@ -55,21 +57,21 @@ public class MaterialGroupImpl<P extends WorldProgram> implements MaterialGroup
} }
public void clear() { public void clear() {
materials.values().forEach(MaterialImpl::clear); materials.values().forEach(InstancedMaterial::clear);
} }
public void delete() { public void delete() {
materials.values() materials.values()
.forEach(MaterialImpl::delete); .forEach(InstancedMaterial::delete);
materials.clear(); materials.clear();
renderers.clear(); renderers.clear();
} }
private MaterialImpl<?> createInstanceMaterial(MaterialSpec<?> type) { private InstancedMaterial<?> createInstanceMaterial(MaterialSpec<?> type) {
MaterialImpl<?> material = new MaterialImpl<>(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; return material;
} }

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.backend.material; package com.jozufozu.flywheel.backend.material.instancing;
import java.util.Collection; import java.util.Collection;
import java.util.function.Consumer; 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.jozufozu.flywheel.core.shader.WorldProgram;
import com.mojang.math.Matrix4f; import com.mojang.math.Matrix4f;
public class MaterialRenderer<P extends WorldProgram> { public class InstancedMaterialRenderer<P extends WorldProgram> {
protected final Supplier<P> program; protected final Supplier<P> program;
protected final MaterialImpl<?> material; protected final InstancedMaterial<?> material;
protected final Consumer<P> setupFunc; protected final Consumer<P> setupFunc;
public MaterialRenderer(Supplier<P> programSupplier, MaterialImpl<?> material, Consumer<P> setupFunc) { public InstancedMaterialRenderer(Supplier<P> programSupplier, InstancedMaterial<?> material, Consumer<P> setupFunc) {
this.program = programSupplier; this.program = programSupplier;
this.material = material; this.material = material;
this.setupFunc = setupFunc; this.setupFunc = setupFunc;

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.backend.material; package com.jozufozu.flywheel.backend.material.instancing;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.HashMap; 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.GlVertexArray;
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType; 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.backend.state.RenderLayer;
import com.jozufozu.flywheel.core.WorldContext; import com.jozufozu.flywheel.core.WorldContext;
import com.jozufozu.flywheel.core.shader.WorldProgram; import com.jozufozu.flywheel.core.shader.WorldProgram;
import com.jozufozu.flywheel.event.RenderLayerEvent;
import com.jozufozu.flywheel.util.WeakHashSet; import com.jozufozu.flywheel.util.WeakHashSet;
import com.mojang.math.Matrix4f; import com.mojang.math.Matrix4f;
import net.minecraft.client.Camera; import net.minecraft.client.Camera;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderType;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Vec3i; import net.minecraft.core.Vec3i;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
public class MaterialManagerImpl<P extends WorldProgram> implements MaterialManager { public class InstancingEngine<P extends WorldProgram> implements Engine {
public static int MAX_ORIGIN_DISTANCE = 100; public static int MAX_ORIGIN_DISTANCE = 100;
@ -30,19 +34,19 @@ public class MaterialManagerImpl<P extends WorldProgram> implements MaterialMana
protected final GroupFactory<P> groupFactory; protected final GroupFactory<P> groupFactory;
protected final boolean ignoreOriginCoordinate; protected final boolean ignoreOriginCoordinate;
protected final Map<RenderLayer, Map<RenderType, MaterialGroupImpl<P>>> layers; protected final Map<RenderLayer, Map<RenderType, InstancedMaterialGroup<P>>> layers;
private final WeakHashSet<OriginShiftListener> listeners; private final WeakHashSet<OriginShiftListener> listeners;
public MaterialManagerImpl(WorldContext<P> context) { public InstancingEngine(WorldContext<P> context) {
this(context, MaterialGroupImpl::new, false); this(context, InstancedMaterialGroup::new, false);
} }
public static <P extends WorldProgram> Builder<P> builder(WorldContext<P> context) { public static <P extends WorldProgram> Builder<P> builder(WorldContext<P> context) {
return new Builder<>(context); return new Builder<>(context);
} }
public MaterialManagerImpl(WorldContext<P> context, GroupFactory<P> groupFactory, boolean ignoreOriginCoordinate) { public InstancingEngine(WorldContext<P> context, GroupFactory<P> groupFactory, boolean ignoreOriginCoordinate) {
this.context = context; this.context = context;
this.ignoreOriginCoordinate = ignoreOriginCoordinate; this.ignoreOriginCoordinate = ignoreOriginCoordinate;
@ -69,10 +73,13 @@ public class MaterialManagerImpl<P extends WorldProgram> implements MaterialMana
/** /**
* Render every model for every material. * 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) { if (!ignoreOriginCoordinate) {
camX -= originCoordinate.getX(); camX -= originCoordinate.getX();
camY -= originCoordinate.getY(); camY -= originCoordinate.getY();
@ -85,9 +92,9 @@ public class MaterialManagerImpl<P extends WorldProgram> implements MaterialMana
viewProjection = translate; viewProjection = translate;
} }
for (Map.Entry<RenderType, MaterialGroupImpl<P>> entry : layers.get(layer).entrySet()) { for (Map.Entry<RenderType, InstancedMaterialGroup<P>> entry : layers.get(event.getLayer()).entrySet()) {
RenderType state = entry.getKey(); RenderType state = entry.getKey();
MaterialGroupImpl<P> group = entry.getValue(); InstancedMaterialGroup<P> group = entry.getValue();
group.render(state, viewProjection, camX, camY, camZ); group.render(state, viewProjection, camX, camY, camZ);
} }
@ -97,10 +104,11 @@ public class MaterialManagerImpl<P extends WorldProgram> implements MaterialMana
GlVertexArray.unbind(); GlVertexArray.unbind();
} }
@Override
public void delete() { public void delete() {
for (Map<RenderType, MaterialGroupImpl<P>> groups : layers.values()) { for (Map<RenderType, InstancedMaterialGroup<P>> groups : layers.values()) {
groups.values().forEach(MaterialGroupImpl::delete); groups.values().forEach(InstancedMaterialGroup::delete);
} }
} }
@ -122,6 +130,7 @@ public class MaterialManagerImpl<P extends WorldProgram> implements MaterialMana
* *
* This prevents floating point precision issues at high coordinates. * This prevents floating point precision issues at high coordinates.
*/ */
@Override
public void beginFrame(Camera info) { public void beginFrame(Camera info) {
int cX = Mth.floor(info.getPosition().x); int cX = Mth.floor(info.getPosition().x);
int cY = Mth.floor(info.getPosition().y); int cY = Mth.floor(info.getPosition().y);
@ -135,8 +144,8 @@ public class MaterialManagerImpl<P extends WorldProgram> implements MaterialMana
originCoordinate = new BlockPos(cX, cY, cZ); originCoordinate = new BlockPos(cX, cY, cZ);
for (Map<RenderType, MaterialGroupImpl<P>> groups : layers.values()) { for (Map<RenderType, InstancedMaterialGroup<P>> groups : layers.values()) {
groups.values().forEach(MaterialGroupImpl::clear); groups.values().forEach(InstancedMaterialGroup::clear);
} }
listeners.forEach(OriginShiftListener::onOriginShift); listeners.forEach(OriginShiftListener::onOriginShift);
@ -150,12 +159,12 @@ public class MaterialManagerImpl<P extends WorldProgram> implements MaterialMana
@FunctionalInterface @FunctionalInterface
public interface GroupFactory<P extends WorldProgram> { public interface GroupFactory<P extends WorldProgram> {
MaterialGroupImpl<P> create(MaterialManagerImpl<P> materialManager); InstancedMaterialGroup<P> create(InstancingEngine<P> materialManager);
} }
public static class Builder<P extends WorldProgram> { public static class Builder<P extends WorldProgram> {
protected final WorldContext<P> context; protected final WorldContext<P> context;
protected GroupFactory<P> groupFactory = MaterialGroupImpl::new; protected GroupFactory<P> groupFactory = InstancedMaterialGroup::new;
protected boolean ignoreOriginCoordinate; protected boolean ignoreOriginCoordinate;
public Builder(WorldContext<P> context) { public Builder(WorldContext<P> context) {
@ -172,8 +181,8 @@ public class MaterialManagerImpl<P extends WorldProgram> implements MaterialMana
return this; return this;
} }
public MaterialManagerImpl<P> build() { public InstancingEngine<P> build() {
return new MaterialManagerImpl<>(context, groupFactory, ignoreOriginCoordinate); return new InstancingEngine<>(context, groupFactory, ignoreOriginCoordinate);
} }
} }
} }

View file

@ -0,0 +1,13 @@
package com.jozufozu.flywheel.backend.struct;
import com.jozufozu.flywheel.core.model.IModel;
public interface Batched<S> extends StructType<S> {
BatchingTransformer<S> getTransformer(IModel model);
@Override
default Batched<S> asBatched() {
return this;
}
}

View file

@ -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<S> {
public void draw(S s, PoseStack stack, VertexConsumer consumer) {
}
}

View file

@ -19,4 +19,6 @@ public interface StructType<S> {
VertexFormat format(); VertexFormat format();
Writeable<S> asWriteable(); Writeable<S> asWriteable();
Batched<S> asBatched();
} }

View file

@ -1,8 +1,8 @@
package com.jozufozu.flywheel.core.crumbling; package com.jozufozu.flywheel.core.crumbling;
import com.jozufozu.flywheel.backend.material.MaterialGroupImpl; import com.jozufozu.flywheel.backend.material.instancing.InstancedMaterialGroup;
import com.jozufozu.flywheel.backend.material.MaterialManagerImpl; import com.jozufozu.flywheel.backend.material.instancing.InstancingEngine;
import com.jozufozu.flywheel.backend.material.MaterialRenderer; import com.jozufozu.flywheel.backend.material.instancing.InstancedMaterialRenderer;
import com.jozufozu.flywheel.core.atlas.AtlasInfo; import com.jozufozu.flywheel.core.atlas.AtlasInfo;
import com.jozufozu.flywheel.core.atlas.SheetData; import com.jozufozu.flywheel.core.atlas.SheetData;
import com.jozufozu.flywheel.util.RenderTextures; import com.jozufozu.flywheel.util.RenderTextures;
@ -13,12 +13,12 @@ import com.mojang.math.Matrix4f;
import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderType;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
public class CrumblingGroup<P extends CrumblingProgram> extends MaterialGroupImpl<P> { public class CrumblingGroup<P extends CrumblingProgram> extends InstancedMaterialGroup<P> {
private int width; private int width;
private int height; private int height;
public CrumblingGroup(MaterialManagerImpl<P> owner) { public CrumblingGroup(InstancingEngine<P> owner) {
super(owner); super(owner);
} }
@ -40,7 +40,7 @@ public class CrumblingGroup<P extends CrumblingProgram> extends MaterialGroupImp
RenderSystem.setShaderTexture(4, breakingTex); RenderSystem.setShaderTexture(4, breakingTex);
TextureBinder.bindActiveTextures(); TextureBinder.bindActiveTextures();
for (MaterialRenderer<P> renderer : renderers) { for (InstancedMaterialRenderer<P> renderer : renderers) {
renderer.render(viewProjection, camX, camY, camZ); renderer.render(viewProjection, camX, camY, camZ);
} }

View file

@ -1,13 +1,13 @@
package com.jozufozu.flywheel.core.crumbling; package com.jozufozu.flywheel.core.crumbling;
import com.jozufozu.flywheel.backend.instancing.tile.TileInstanceManager; 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; import net.minecraft.core.BlockPos;
public class CrumblingInstanceManager extends TileInstanceManager { public class CrumblingInstanceManager extends TileInstanceManager {
public CrumblingInstanceManager(MaterialManagerImpl<?> materialManager) { public CrumblingInstanceManager(MaterialManager materialManager) {
super(materialManager); super(materialManager);
} }

View file

@ -6,17 +6,15 @@ import java.util.SortedSet;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.gl.GlTextureUnit; 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.instancing.InstanceManager;
import com.jozufozu.flywheel.backend.material.MaterialManagerImpl; import com.jozufozu.flywheel.backend.material.instancing.InstancingEngine;
import com.jozufozu.flywheel.backend.state.RenderLayer;
import com.jozufozu.flywheel.core.Contexts; import com.jozufozu.flywheel.core.Contexts;
import com.jozufozu.flywheel.event.ReloadRenderersEvent; import com.jozufozu.flywheel.event.ReloadRenderersEvent;
import com.jozufozu.flywheel.event.RenderLayerEvent;
import com.jozufozu.flywheel.mixin.LevelRendererAccessor; import com.jozufozu.flywheel.mixin.LevelRendererAccessor;
import com.jozufozu.flywheel.util.Lazy; import com.jozufozu.flywheel.util.Lazy;
import com.jozufozu.flywheel.util.Pair; import com.jozufozu.flywheel.util.Pair;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.math.Matrix4f;
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
@ -55,17 +53,17 @@ public class CrumblingRenderer {
INVALIDATOR = state.getSecond(); 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() if (!Backend.getInstance()
.canUseInstancing(world)) return; .canUseInstancing(event.getWorld())) return;
Int2ObjectMap<List<BlockEntity>> activeStages = getActiveStageTiles(world); Int2ObjectMap<List<BlockEntity>> activeStages = getActiveStageTiles(event.getWorld());
if (activeStages.isEmpty()) return; if (activeStages.isEmpty()) return;
State state = STATE.get(); State state = STATE.get();
InstanceManager<BlockEntity> instanceManager = state.instanceManager; InstanceManager<BlockEntity> instanceManager = state.instanceManager;
MaterialManagerImpl<CrumblingProgram> materials = state.materialManager; InstancingEngine<CrumblingProgram> materials = state.materialManager;
TextureManager textureManager = Minecraft.getInstance().getTextureManager(); TextureManager textureManager = Minecraft.getInstance().getTextureManager();
Camera info = Minecraft.getInstance().gameRenderer.getMainCamera(); Camera info = Minecraft.getInstance().gameRenderer.getMainCamera();
@ -79,7 +77,7 @@ public class CrumblingRenderer {
instanceManager.beginFrame(info); instanceManager.beginFrame(info);
materials.render(RenderLayer.SOLID, viewProjection, cameraX, cameraY, cameraZ); materials.render(event, null);
instanceManager.invalidate(); instanceManager.invalidate();
} }
@ -133,14 +131,15 @@ public class CrumblingRenderer {
} }
private static class State { private static class State {
private final MaterialManagerImpl<CrumblingProgram> materialManager; private final InstancingEngine<CrumblingProgram> materialManager;
private final InstanceManager<BlockEntity> instanceManager; private final InstanceManager<BlockEntity> instanceManager;
private State() { private State() {
materialManager = MaterialManagerImpl.builder(Contexts.CRUMBLING) materialManager = InstancingEngine.builder(Contexts.CRUMBLING)
.setGroupFactory(CrumblingGroup::new) .setGroupFactory(CrumblingGroup::new)
.build(); .build();
instanceManager = new CrumblingInstanceManager(materialManager); instanceManager = new CrumblingInstanceManager(materialManager);
materialManager.addListener(instanceManager);
} }
private void kill() { private void kill() {

View file

@ -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<ModelData> {
public ModelTransformer(IModel model) {
//model.buffer();
}
}

View file

@ -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.attrib.VertexFormat;
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; 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.StructWriter;
import com.jozufozu.flywheel.backend.struct.Writeable; import com.jozufozu.flywheel.backend.struct.Writeable;
import com.jozufozu.flywheel.core.Formats; import com.jozufozu.flywheel.core.Formats;
import com.jozufozu.flywheel.core.materials.model.writer.UnsafeModelWriter; import com.jozufozu.flywheel.core.materials.model.writer.UnsafeModelWriter;
import com.jozufozu.flywheel.core.model.IModel;
public class ModelType implements Writeable<ModelData> { public class ModelType implements Writeable<ModelData>, Batched<ModelData> {
@Override @Override
public ModelData create() { public ModelData create() {
@ -23,4 +26,9 @@ public class ModelType implements Writeable<ModelData> {
public StructWriter<ModelData> getWriter(VecBuffer backing) { public StructWriter<ModelData> getWriter(VecBuffer backing) {
return new UnsafeModelWriter(backing, this); return new UnsafeModelWriter(backing, this);
} }
@Override
public BatchingTransformer<ModelData> getTransformer(IModel model) {
return null;
}
} }

View file

@ -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.attrib.VertexFormat;
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; 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.StructWriter;
import com.jozufozu.flywheel.backend.struct.Writeable; import com.jozufozu.flywheel.backend.struct.Writeable;
import com.jozufozu.flywheel.core.Formats; import com.jozufozu.flywheel.core.Formats;
import com.jozufozu.flywheel.core.materials.oriented.writer.UnsafeOrientedWriter; import com.jozufozu.flywheel.core.materials.oriented.writer.UnsafeOrientedWriter;
import com.jozufozu.flywheel.core.model.IModel;
public class OrientedType implements Writeable<OrientedData> { public class OrientedType implements Writeable<OrientedData>, Batched<OrientedData> {
@Override @Override
public OrientedData create() { public OrientedData create() {
@ -23,4 +26,9 @@ public class OrientedType implements Writeable<OrientedData> {
public StructWriter<OrientedData> getWriter(VecBuffer backing) { public StructWriter<OrientedData> getWriter(VecBuffer backing) {
return new UnsafeOrientedWriter(backing, this); return new UnsafeOrientedWriter(backing, this);
} }
@Override
public BatchingTransformer<OrientedData> getTransformer(IModel model) {
return null;
}
} }

View file

@ -82,13 +82,9 @@ public class RenderHooksMixin {
if (!Backend.getInstance() if (!Backend.getInstance()
.available()) return; .available()) return;
Matrix4f view = stack.last()
.pose();
Matrix4f viewProjection = view.copy();
viewProjection.multiplyBackward(RenderSystem.getProjectionMatrix());
Vec3 cameraPos = info.getPosition(); 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); if (!OptifineHandler.usingShaders()) GL20.glUseProgram(0);
} }