diff --git a/src/main/java/com/jozufozu/flywheel/api/MaterialManager.java b/src/main/java/com/jozufozu/flywheel/api/MaterialManager.java index 62047cbbc..64a483736 100644 --- a/src/main/java/com/jozufozu/flywheel/api/MaterialManager.java +++ b/src/main/java/com/jozufozu/flywheel/api/MaterialManager.java @@ -8,7 +8,7 @@ import net.minecraft.core.Vec3i; public interface MaterialManager { - InstancedMaterial material(StructType type); + Material material(StructType type); Vec3i getOriginCoordinate(); diff --git a/src/main/java/com/jozufozu/flywheel/api/RenderLayer.java b/src/main/java/com/jozufozu/flywheel/api/RenderLayer.java deleted file mode 100644 index fbdede5c5..000000000 --- a/src/main/java/com/jozufozu/flywheel/api/RenderLayer.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.jozufozu.flywheel.api; - -import javax.annotation.Nullable; - -import net.minecraft.client.renderer.RenderType; - -/** - * The 3 discrete stages the world is rendered in. - */ -public enum RenderLayer { - /** - * Solid layer:
- * - * All polygons will entirely occlude everything behind them. - * - *

- * e.g. stone, dirt, solid blocks - */ - SOLID, - /** - * Cutout layer:
- * - * Fragments will either occlude or not occlude depending on the texture/material. - * - *

- * e.g. leaves, cobwebs, tall grass, saplings, glass - */ - CUTOUT, - /** - * Transparent layer:
- * - * Nothing is guaranteed to occlude and fragments blend their color with what's behind them. - * - *

- * e.g. stained glass, water - */ - TRANSPARENT, - ; - - @Nullable - public static RenderLayer getPrimaryLayer(RenderType type) { - if (type == RenderType.solid()) { - return SOLID; - } else if (type == RenderType.cutoutMipped()) { - return CUTOUT; - } else if (type == RenderType.translucent()) { - return TRANSPARENT; - } - - return null; - } - - @Nullable - public static RenderLayer getLayer(RenderType type) { - if (type == RenderType.solid()) { - return SOLID; - } else if (type == RenderType.cutoutMipped() || type == RenderType.cutout()) { - return CUTOUT; - } else if (type == RenderType.translucent()) { - return TRANSPARENT; - } - - return null; - } -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/GlVertexArray.java b/src/main/java/com/jozufozu/flywheel/backend/gl/GlVertexArray.java index d757cfbb8..8f511b9cb 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/GlVertexArray.java +++ b/src/main/java/com/jozufozu/flywheel/backend/gl/GlVertexArray.java @@ -1,12 +1,16 @@ package com.jozufozu.flywheel.backend.gl; import org.lwjgl.opengl.GL20; +import org.lwjgl.opengl.GL32; import com.jozufozu.flywheel.core.layout.BufferLayout; import com.jozufozu.flywheel.core.layout.LayoutItem; import com.mojang.blaze3d.platform.GlStateManager; public class GlVertexArray extends GlObject { + + private final boolean[] arrays = new boolean[GL32.glGetInteger(GL32.GL_MAX_VERTEX_ATTRIBS)]; + public GlVertexArray() { setHandle(GlStateManager._glGenVertexArrays()); } @@ -25,13 +29,27 @@ public class GlVertexArray extends GlObject { public void enableArrays(int count) { for (int i = 0; i < count; i++) { - GL20.glEnableVertexAttribArray(i); + enable(i); } } public void disableArrays(int count) { for (int i = 0; i < count; i++) { + disable(i); + } + } + + private void enable(int i) { + if (!arrays[i]) { + GL20.glEnableVertexAttribArray(i); + arrays[i] = true; + } + } + + private void disable(int i) { + if (arrays[i]) { GL20.glDisableVertexAttribArray(i); + arrays[i] = false; } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/AbstractInstancer.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/AbstractInstancer.java index 72692a955..5389ca60e 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/AbstractInstancer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/AbstractInstancer.java @@ -59,7 +59,7 @@ public abstract class AbstractInstancer implements Insta } public int getModelVertexCount() { - return 0; + return modelData.getVertexCount(); } public int getInstanceCount() { 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 c3ee1a1f6..d26c8a66e 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceWorld.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceWorld.java @@ -8,13 +8,16 @@ import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstanceM import com.jozufozu.flywheel.backend.instancing.entity.EntityInstanceManager; import com.jozufozu.flywheel.backend.instancing.instancing.InstancingEngine; import com.jozufozu.flywheel.core.Contexts; +import com.jozufozu.flywheel.core.RenderContext; import com.jozufozu.flywheel.core.shader.WorldProgram; import com.jozufozu.flywheel.event.BeginFrameEvent; -import com.jozufozu.flywheel.event.RenderLayerEvent; import com.jozufozu.flywheel.util.ClientLevelExtension; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Matrix4f; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.renderer.RenderType; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.entity.BlockEntity; @@ -35,8 +38,7 @@ public class InstanceWorld { public static InstanceWorld create(LevelAccessor level) { return switch (Backend.getBackendType()) { case INSTANCING -> { - InstancingEngine manager = InstancingEngine.builder(Contexts.WORLD) - .build(); + InstancingEngine manager = new InstancingEngine<>(Contexts.WORLD); var entityInstanceManager = new EntityInstanceManager(manager); var blockEntityInstanceManager = new BlockEntityInstanceManager(manager); @@ -116,12 +118,12 @@ public class InstanceWorld { /** * Draw the given layer. */ - public void renderLayer(RenderLayerEvent event) { + public void renderLayer(RenderContext context) { taskEngine.syncPoint(); - event.stack.pushPose(); - event.stack.translate(-event.camX, -event.camY, -event.camZ); - engine.render(taskEngine, event); - event.stack.popPose(); + context.pushPose(); + context.translateBack(context.camX(), context.camY(), context.camZ()); + engine.render(taskEngine, context); + context.popPose(); } /** diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java index 6f8f77e3d..84c13fdd0 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java @@ -98,12 +98,10 @@ public class InstancedRenderDispatcher { @SubscribeEvent public static void renderLayer(RenderLayerEvent event) { - if (event.layer == null) return; - ClientLevel world = event.getWorld(); if (!Backend.canUseInstancing(world)) return; - instanceWorlds.get(world).renderLayer(event); + instanceWorlds.get(world).renderLayer(event.context); } @SubscribeEvent diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/RenderDispatcher.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/RenderDispatcher.java index 4d5cf8372..47f1353ba 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/RenderDispatcher.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/RenderDispatcher.java @@ -1,17 +1,18 @@ package com.jozufozu.flywheel.backend.instancing; -import com.jozufozu.flywheel.event.RenderLayerEvent; +import com.jozufozu.flywheel.core.RenderContext; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Matrix4f; import net.minecraft.client.Camera; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.renderer.RenderType; public interface RenderDispatcher { /** * Render every model for every material. - * - * @param taskEngine - * @param event Context for rendering. */ - void render(TaskEngine taskEngine, RenderLayerEvent event); + void render(TaskEngine taskEngine, RenderContext context); /** * Maintain the integer origin coordinate to be within a certain distance from the camera in all directions. diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchingEngine.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchingEngine.java index ef5d42b67..06a85573e 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchingEngine.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchingEngine.java @@ -1,42 +1,36 @@ package com.jozufozu.flywheel.backend.instancing.batching; -import java.util.EnumMap; import java.util.HashMap; import java.util.List; import java.util.Map; import com.jozufozu.flywheel.api.InstanceData; -import com.jozufozu.flywheel.api.RenderLayer; +import com.jozufozu.flywheel.api.struct.Batched; import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.backend.instancing.BatchDrawingTracker; import com.jozufozu.flywheel.backend.instancing.Engine; import com.jozufozu.flywheel.backend.instancing.TaskEngine; -import com.jozufozu.flywheel.backend.instancing.instancing.InstancedMaterial; -import com.jozufozu.flywheel.event.RenderLayerEvent; -import com.jozufozu.flywheel.util.FlwUtil; +import com.jozufozu.flywheel.core.RenderContext; import com.mojang.blaze3d.platform.Lighting; import com.mojang.math.Matrix4f; import net.minecraft.client.Camera; -import net.minecraft.client.renderer.RenderType; import net.minecraft.core.BlockPos; import net.minecraft.core.Vec3i; public class BatchingEngine implements Engine { - private final Map> layers; + private final Map, BatchedMaterial> materials = new HashMap<>(); private final BatchDrawingTracker batchTracker = new BatchDrawingTracker(); - public BatchingEngine() { - this.layers = new EnumMap<>(RenderLayer.class); - for (RenderLayer value : RenderLayer.values()) { - layers.put(value, new HashMap<>()); - } - } - + @SuppressWarnings("unchecked") @Override - public InstancedMaterial material(StructType type) { - return null; + public BatchedMaterial material(StructType type) { + if (type instanceof Batched batched) { + return (BatchedMaterial) materials.computeIfAbsent(batched, BatchedMaterial::new); + } else { + throw new ClassCastException("Cannot use type '" + type + "' with batching."); + } } @Override @@ -45,16 +39,34 @@ public class BatchingEngine implements Engine { } @Override - public void render(TaskEngine taskEngine, RenderLayerEvent event) { - Map groups = layers.get(event.getLayer()); - for (BatchedMaterialGroup group : groups.values()) { - group.render(event.stack, batchTracker, taskEngine); - } + public void render(TaskEngine taskEngine, RenderContext context) { + +// vertexCount = 0; +// instanceCount = 0; +// for (BatchedMaterial material : materials.values()) { +// for (CPUInstancer instancer : material.models.values()) { +// instancer.setup(); +// vertexCount += instancer.getVertexCount(); +// instanceCount += instancer.getInstanceCount(); +// } +// } +// +// DirectVertexConsumer consumer = batchTracker.getDirectConsumer(state, vertexCount); +// +// // avoids rendering garbage, but doesn't fix the issue of some instances not being buffered +// consumer.memSetZero(); +// +// for (BatchedMaterial material : materials.values()) { +// for (CPUInstancer instancer : material.models.values()) { +// instancer.sbb.context.outputColorDiffuse = !consumer.hasOverlay() && !OptifineHandler.isUsingShaders(); +// instancer.submitTasks(stack, pool, consumer); +// } +// } // FIXME: this probably breaks some vanilla stuff but it works much better for flywheel Matrix4f mat = new Matrix4f(); mat.setIdentity(); - if (event.getWorld().effects().constantAmbientLight()) { + if (context.level().effects().constantAmbientLight()) { Lighting.setupNetherLevel(mat); } else { Lighting.setupLevel(mat); @@ -76,15 +88,7 @@ public class BatchingEngine implements Engine { @Override public void addDebugInfo(List info) { info.add("Batching"); - info.add("Instances: " + layers.values() - .stream() - .flatMap(FlwUtil::mapValues) - .mapToInt(BatchedMaterialGroup::getInstanceCount) - .sum()); - info.add("Vertices: " + layers.values() - .stream() - .flatMap(FlwUtil::mapValues) - .mapToInt(BatchedMaterialGroup::getVertexCount) - .sum()); + info.add("Instances: " + 0); + info.add("Vertices: " + 0); } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/blockentity/BlockEntityInstance.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/blockentity/BlockEntityInstance.java index be4f65a71..85390c42e 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/blockentity/BlockEntityInstance.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/blockentity/BlockEntityInstance.java @@ -2,7 +2,6 @@ package com.jozufozu.flywheel.backend.instancing.blockentity; import com.jozufozu.flywheel.api.Material; import com.jozufozu.flywheel.api.MaterialManager; -import com.jozufozu.flywheel.api.RenderLayer; import com.jozufozu.flywheel.api.instance.DynamicInstance; import com.jozufozu.flywheel.api.instance.TickableInstance; import com.jozufozu.flywheel.backend.instancing.AbstractInstance; @@ -12,7 +11,6 @@ import com.jozufozu.flywheel.core.materials.oriented.OrientedData; import com.jozufozu.flywheel.util.box.GridAlignedBB; import com.jozufozu.flywheel.util.box.ImmutableBox; -import net.minecraft.client.renderer.RenderType; import net.minecraft.core.BlockPos; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/GPUInstancer.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/GPUInstancer.java index faff7aff6..99b9290cc 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/GPUInstancer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/GPUInstancer.java @@ -9,6 +9,7 @@ import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.api.InstanceData; import com.jozufozu.flywheel.api.struct.Instanced; import com.jozufozu.flywheel.api.struct.StructWriter; +import com.jozufozu.flywheel.backend.gl.GlStateTracker; import com.jozufozu.flywheel.backend.gl.GlVertexArray; import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer; import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType; @@ -67,8 +68,16 @@ public class GPUInstancer extends AbstractInstancer { return deleted || model == null; } - public Map init(ModelAllocator modelAllocator) { - if (isInitialized()) return ImmutableMap.of(); + public boolean shouldRenderIn(RenderType renderType) { + return modelData.getRenderType() == renderType; + } + + public void renderIn(RenderType renderType) { + render(); + } + + public void init(ModelAllocator modelAllocator) { + if (isInitialized()) return; initialized = true; @@ -77,16 +86,10 @@ public class GPUInstancer extends AbstractInstancer { vao = new GlVertexArray(); - model = modelAllocator.alloc(modelData.get(), arenaModel -> { - vao.bind(); - - arenaModel.setupState(vao); - }); + model = modelAllocator.alloc(modelData.get(), vao); vao.bind(); vao.enableArrays(model.getAttributeCount() + instanceFormat.getAttributeCount()); - - return ImmutableMap.of(modelData.getRenderType(), this::render); } public boolean isInitialized() { diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedMaterial.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedMaterial.java index ec3cb2d8a..4a1f2a8f6 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedMaterial.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedMaterial.java @@ -6,13 +6,10 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import javax.annotation.Nullable; - import com.jozufozu.flywheel.api.InstanceData; import com.jozufozu.flywheel.api.Instancer; import com.jozufozu.flywheel.api.Material; import com.jozufozu.flywheel.api.struct.Instanced; -import com.jozufozu.flywheel.backend.instancing.Renderable; import com.jozufozu.flywheel.backend.model.ModelAllocator; import com.jozufozu.flywheel.core.ModelSupplier; @@ -27,19 +24,12 @@ public class InstancedMaterial implements Material { protected final Map> models = new HashMap<>(); protected final Instanced type; - public final Map> renderables = new HashMap<>(); - protected final List> uninitialized = new ArrayList<>(); public InstancedMaterial(Instanced type) { this.type = type; } - @Nullable - public List getRenderables(RenderType type) { - return renderables.get(type); - } - @Override public Instancer model(ModelSupplier modelKey) { return models.computeIfAbsent(modelKey, k -> { @@ -80,17 +70,18 @@ public class InstancedMaterial implements Material { return models.values(); } - void init(ModelAllocator allocator) { + public void init(ModelAllocator allocator) { for (GPUInstancer instancer : uninitialized) { - - instancer.init(allocator) - .forEach(this::addRenderable); + instancer.init(allocator); } uninitialized.clear(); } - private void addRenderable(RenderType type, Renderable renderable) { - this.renderables.computeIfAbsent(type, k -> new ArrayList<>()) - .add(renderable); + public void renderIn(RenderType layer) { + for (GPUInstancer instancer : models.values()) { + if (instancer.shouldRenderIn(layer)) { + instancer.renderIn(layer); + } + } } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedMaterialGroup.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedMaterialGroup.java deleted file mode 100644 index c483ff678..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedMaterialGroup.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.jozufozu.flywheel.backend.instancing.instancing; - -import java.util.HashMap; -import java.util.Map; - -import com.jozufozu.flywheel.api.InstanceData; -import com.jozufozu.flywheel.api.MaterialGroup; -import com.jozufozu.flywheel.api.struct.Instanced; -import com.jozufozu.flywheel.api.struct.StructType; -import com.jozufozu.flywheel.api.RenderLayer; -import com.jozufozu.flywheel.backend.gl.versioned.GlCompat; -import com.jozufozu.flywheel.backend.model.FallbackAllocator; -import com.jozufozu.flywheel.backend.model.ModelAllocator; -import com.jozufozu.flywheel.backend.model.ModelPool; -import com.jozufozu.flywheel.core.Formats; -import com.jozufozu.flywheel.core.compile.ProgramContext; -import com.jozufozu.flywheel.core.shader.WorldProgram; -import com.jozufozu.flywheel.util.Textures; -import com.mojang.math.Matrix4f; - -import net.minecraft.client.renderer.RenderType; - -/** - * A group of materials all rendered with the same GL state. - * - * 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 InstancedMaterialGroup

{ - - protected final InstancingEngine

owner; - protected final RenderType type; - - public InstancedMaterialGroup(InstancingEngine

owner, RenderType type) { - this.owner = owner; - this.type = type; - } - - public void render(Matrix4f viewProjection, double camX, double camY, double camZ, RenderLayer layer) { - type.setupRenderState(); - Textures.bindActiveTextures(); - //renderAll(viewProjection, camX, camY, camZ, layer); - type.clearRenderState(); - } - - protected void setup(P program) { - - } -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancingEngine.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancingEngine.java index 134bd93b4..4e0d42a62 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancingEngine.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancingEngine.java @@ -11,16 +11,16 @@ import com.jozufozu.flywheel.api.struct.Instanced; import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.backend.gl.versioned.GlCompat; import com.jozufozu.flywheel.backend.instancing.Engine; -import com.jozufozu.flywheel.backend.instancing.Renderable; import com.jozufozu.flywheel.backend.instancing.TaskEngine; import com.jozufozu.flywheel.backend.model.FallbackAllocator; import com.jozufozu.flywheel.backend.model.ModelAllocator; import com.jozufozu.flywheel.backend.model.ModelPool; import com.jozufozu.flywheel.core.Formats; +import com.jozufozu.flywheel.core.RenderContext; +import com.jozufozu.flywheel.core.RenderTypeRegistry; import com.jozufozu.flywheel.core.compile.ProgramCompiler; import com.jozufozu.flywheel.core.compile.ProgramContext; import com.jozufozu.flywheel.core.shader.WorldProgram; -import com.jozufozu.flywheel.event.RenderLayerEvent; import com.jozufozu.flywheel.util.Textures; import com.jozufozu.flywheel.util.WeakHashSet; import com.mojang.math.Matrix4f; @@ -29,6 +29,7 @@ import net.minecraft.client.Camera; 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 InstancingEngine

implements Engine { @@ -38,26 +39,18 @@ public class InstancingEngine

implements Engine { protected BlockPos originCoordinate = BlockPos.ZERO; protected final ProgramCompiler

context; - protected final GroupFactory

groupFactory; - protected final boolean ignoreOriginCoordinate; private ModelAllocator allocator; - private final Map, InstancedMaterial> materials = new HashMap<>(); + protected final Map, InstancedMaterial> materials = new HashMap<>(); private final WeakHashSet listeners; private int vertexCount; private int instanceCount; - public static

Builder

builder(ProgramCompiler

context) { - return new Builder<>(context); - } - - public InstancingEngine(ProgramCompiler

context, GroupFactory

groupFactory, boolean ignoreOriginCoordinate) { + public InstancingEngine(ProgramCompiler

context) { this.context = context; - this.ignoreOriginCoordinate = ignoreOriginCoordinate; this.listeners = new WeakHashSet<>(); - this.groupFactory = groupFactory; } @SuppressWarnings("unchecked") @@ -72,28 +65,20 @@ public class InstancingEngine

implements Engine { } @Override - public void render(TaskEngine taskEngine, RenderLayerEvent event) { + public void render(TaskEngine taskEngine, RenderContext context) { - RenderType type = event.getType(); + var camX = context.camX() - originCoordinate.getX(); + var camY = context.camY() - originCoordinate.getY(); + var camZ = context.camZ() - originCoordinate.getZ(); - double camX; - double camY; - double camZ; - Matrix4f viewProjection; - if (!ignoreOriginCoordinate) { - camX = event.camX - originCoordinate.getX(); - camY = event.camY - originCoordinate.getY(); - camZ = event.camZ - originCoordinate.getZ(); + // don't want to mutate viewProjection + var vp = context.viewProjection().copy(); + vp.multiply(Matrix4f.createTranslateMatrix((float) -camX, (float) -camY, (float) -camZ)); - viewProjection = Matrix4f.createTranslateMatrix((float) -camX, (float) -camY, (float) -camZ); - viewProjection.multiplyBackward(event.viewProjection); - } else { - camX = event.camX; - camY = event.camY; - camZ = event.camZ; - viewProjection = event.viewProjection; - } + render(context.type(), camX, camY, camZ, vp); + } + protected void render(RenderType type, double camX, double camY, double camZ, Matrix4f viewProjection) { vertexCount = 0; instanceCount = 0; @@ -101,29 +86,30 @@ public class InstancingEngine

implements Engine { Textures.bindActiveTextures(); for (Map.Entry, InstancedMaterial> entry : materials.entrySet()) { - List renderables = entry.getValue() - .getRenderables(type); + InstancedMaterial material = entry.getValue(); + Instanced instanceType = entry.getKey(); - if (renderables == null || renderables.isEmpty()) { - continue; - } + setup(type, camX, camY, camZ, viewProjection, instanceType.getProgramSpec()); - P program = context.getProgram(ProgramContext.create(entry.getKey() - .getProgramSpec(), Formats.POS_TEX_NORMAL, event.layer)); + instanceCount += material.getInstanceCount(); + vertexCount += material.getVertexCount(); - program.bind(); - program.uploadViewProjection(viewProjection); - program.uploadCameraPos(camX, camY, camZ); - - //setup(program); - for (Renderable renderable : renderables) { - renderable.draw(); - } + material.renderIn(type); } type.clearRenderState(); } + protected P setup(RenderType layer, double camX, double camY, double camZ, Matrix4f viewProjection, ResourceLocation programSpec) { + P program = context.getProgram(ProgramContext.create(programSpec, Formats.POS_TEX_NORMAL, RenderTypeRegistry.getAlphaDiscard(layer))); + + program.bind(); + program.uploadViewProjection(viewProjection); + program.uploadCameraPos(camX, camY, camZ); + + return program; + } + public void clearAll() { materials.values().forEach(InstancedMaterial::clear); } @@ -152,22 +138,7 @@ public class InstancingEngine

implements Engine { */ @Override public void beginFrame(Camera info) { - int cX = Mth.floor(info.getPosition().x); - int cY = Mth.floor(info.getPosition().y); - int cZ = Mth.floor(info.getPosition().z); - - int dX = cX - originCoordinate.getX(); - int dY = cY - originCoordinate.getY(); - int dZ = cZ - originCoordinate.getZ(); - - if (Math.abs(dX) > MAX_ORIGIN_DISTANCE || Math.abs(dY) > MAX_ORIGIN_DISTANCE || Math.abs(dZ) > MAX_ORIGIN_DISTANCE) { - - originCoordinate = new BlockPos(cX, cY, cZ); - - materials.values().forEach(InstancedMaterial::clear); - - listeners.forEach(OriginShiftListener::onOriginShift); - } + checkOriginDistance(info); ModelAllocator allocator = getModelAllocator(); @@ -182,6 +153,29 @@ public class InstancingEngine

implements Engine { } + private void checkOriginDistance(Camera info) { + int cX = Mth.floor(info.getPosition().x); + int cY = Mth.floor(info.getPosition().y); + int cZ = Mth.floor(info.getPosition().z); + + int dX = cX - originCoordinate.getX(); + int dY = cY - originCoordinate.getY(); + int dZ = cZ - originCoordinate.getZ(); + + if (Math.abs(dX) > MAX_ORIGIN_DISTANCE || Math.abs(dY) > MAX_ORIGIN_DISTANCE || Math.abs(dZ) > MAX_ORIGIN_DISTANCE) { + + shiftListeners(cX, cY, cZ); + } + } + + private void shiftListeners(int cX, int cY, int cZ) { + originCoordinate = new BlockPos(cX, cY, cZ); + + materials.values().forEach(InstancedMaterial::clear); + + listeners.forEach(OriginShiftListener::onOriginShift); + } + @Override public void addDebugInfo(List info) { info.add("GL33 Instanced Arrays"); @@ -210,33 +204,4 @@ public class InstancingEngine

implements Engine { public interface OriginShiftListener { void onOriginShift(); } - - @FunctionalInterface - public interface GroupFactory

{ - InstancedMaterialGroup

create(InstancingEngine

engine, RenderType type); - } - - public static class Builder

{ - protected final ProgramCompiler

context; - protected GroupFactory

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

context) { - this.context = context; - } - - public Builder

setGroupFactory(GroupFactory

groupFactory) { - this.groupFactory = groupFactory; - return this; - } - - public Builder

setIgnoreOriginCoordinate(boolean ignoreOriginCoordinate) { - this.ignoreOriginCoordinate = ignoreOriginCoordinate; - return this; - } - - public InstancingEngine

build() { - return new InstancingEngine<>(context, groupFactory, ignoreOriginCoordinate); - } - } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/model/FallbackAllocator.java b/src/main/java/com/jozufozu/flywheel/backend/model/FallbackAllocator.java index 7520afff2..a06593ed3 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/model/FallbackAllocator.java +++ b/src/main/java/com/jozufozu/flywheel/backend/model/FallbackAllocator.java @@ -1,14 +1,16 @@ package com.jozufozu.flywheel.backend.model; +import com.jozufozu.flywheel.backend.gl.GlVertexArray; import com.jozufozu.flywheel.core.model.Model; public enum FallbackAllocator implements ModelAllocator { INSTANCE; @Override - public BufferedModel alloc(Model model, Callback allocationCallback) { + public BufferedModel alloc(Model model, GlVertexArray vao) { IndexedModel out = new IndexedModel(model); - allocationCallback.onAlloc(out); + vao.bind(); + out.setupState(vao); return out; } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/model/IndexedModel.java b/src/main/java/com/jozufozu/flywheel/backend/model/IndexedModel.java index 7a372b0c8..2add47260 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/model/IndexedModel.java +++ b/src/main/java/com/jozufozu/flywheel/backend/model/IndexedModel.java @@ -64,8 +64,8 @@ public class IndexedModel implements BufferedModel { } /** - * Draws many instances of this model, assuming the appropriate state is already bound. - */ + * Draws many instances of this model, assuming the appropriate state is already bound. + */ @Override public void drawInstances(int instanceCount) { if (!valid()) return; diff --git a/src/main/java/com/jozufozu/flywheel/backend/model/ModelAllocator.java b/src/main/java/com/jozufozu/flywheel/backend/model/ModelAllocator.java index 2b5424ffe..ee3ca81b8 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/model/ModelAllocator.java +++ b/src/main/java/com/jozufozu/flywheel/backend/model/ModelAllocator.java @@ -1,5 +1,6 @@ package com.jozufozu.flywheel.backend.model; +import com.jozufozu.flywheel.backend.gl.GlVertexArray; import com.jozufozu.flywheel.core.model.Model; public interface ModelAllocator { @@ -7,9 +8,10 @@ public interface ModelAllocator { * Allocate a model. * * @param model The model to allocate. + * @param vao The vertex array object to attach the model to. * @return A handle to the allocated model. */ - BufferedModel alloc(Model model, Callback allocationCallback); + BufferedModel alloc(Model model, GlVertexArray vao); @FunctionalInterface interface Callback { diff --git a/src/main/java/com/jozufozu/flywheel/backend/model/ModelPool.java b/src/main/java/com/jozufozu/flywheel/backend/model/ModelPool.java index c3b9ed6a4..223ccc034 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/model/ModelPool.java +++ b/src/main/java/com/jozufozu/flywheel/backend/model/ModelPool.java @@ -4,7 +4,6 @@ import java.util.ArrayList; import java.util.List; import org.lwjgl.opengl.GL32; -import org.lwjgl.opengl.GL43; import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.api.vertex.VertexType; @@ -51,12 +50,12 @@ public class ModelPool implements ModelAllocator { * Allocate a model in the arena. * * @param model The model to allocate. + * @param vao The vertex array object to attach the model to. * @return A handle to the allocated model. */ @Override - public PooledModel alloc(Model model, Callback callback) { - PooledModel bufferedModel = new PooledModel(model, vertices); - bufferedModel.callback = callback; + public PooledModel alloc(Model model, GlVertexArray vao) { + PooledModel bufferedModel = new PooledModel(vao, model, vertices); vertices += model.vertexCount(); models.add(bufferedModel); pendingUpload.add(bufferedModel); @@ -119,7 +118,7 @@ public class ModelPool implements ModelAllocator { for (PooledModel model : models) { model.first = vertices; - buffer(writer, model); + model.buffer(writer); vertices += model.getVertexCount(); } @@ -133,7 +132,7 @@ public class ModelPool implements ModelAllocator { try (MappedBuffer buffer = vbo.getBuffer()) { VertexWriter writer = vertexType.createWriter(buffer.unwrap()); for (PooledModel model : pendingUpload) { - buffer(writer, model); + model.buffer(writer); } pendingUpload.clear(); } catch (Exception e) { @@ -141,12 +140,6 @@ public class ModelPool implements ModelAllocator { } } - private void buffer(VertexWriter writer, PooledModel model) { - writer.seekToVertex(model.first); - writer.writeVertexList(model.model.getReader()); - if (model.callback != null) model.callback.onAlloc(model); - } - private void setDirty() { dirty = true; } @@ -158,14 +151,15 @@ public class ModelPool implements ModelAllocator { public class PooledModel implements BufferedModel { private final ElementBuffer ebo; - private Callback callback; + private final GlVertexArray vao; private final Model model; private int first; - private boolean remove; + private boolean deleted; - public PooledModel(Model model, int first) { + public PooledModel(GlVertexArray vao, Model model, int first) { + this.vao = vao; this.model = model; this.first = first; ebo = model.createEBO(); @@ -183,7 +177,7 @@ public class ModelPool implements ModelAllocator { @Override public void setupState(GlVertexArray vao) { - vbo.bind(); + vao.bind(); vao.enableArrays(getAttributeCount()); vao.bindAttributes(0, vertexType.getLayout()); } @@ -206,14 +200,22 @@ public class ModelPool implements ModelAllocator { @Override public boolean isDeleted() { - return false; + return deleted; } @Override public void delete() { setDirty(); anyToRemove = true; - remove = true; + deleted = true; + } + + private void buffer(VertexWriter writer) { + writer.seekToVertex(first); + writer.writeVertexList(model.getReader()); + + vao.bind(); + setupState(vao); } } diff --git a/src/main/java/com/jozufozu/flywheel/core/ModelSupplier.java b/src/main/java/com/jozufozu/flywheel/core/ModelSupplier.java index 98b59260b..9fb787a4b 100644 --- a/src/main/java/com/jozufozu/flywheel/core/ModelSupplier.java +++ b/src/main/java/com/jozufozu/flywheel/core/ModelSupplier.java @@ -8,9 +8,7 @@ import com.jozufozu.flywheel.util.NonNullSupplier; import net.minecraft.client.renderer.RenderType; -public class ModelSupplier { - - private final Lazy supplier; +public class ModelSupplier extends Lazy { private RenderType renderType; @@ -19,7 +17,7 @@ public class ModelSupplier { } public ModelSupplier(NonNullSupplier supplier, RenderType renderType) { - this.supplier = Lazy.of(supplier); + super(supplier); this.renderType = renderType; } @@ -32,13 +30,17 @@ public class ModelSupplier { return this; } - @Nonnull - public Model get() { - return supplier.get(); - } - @Nonnull public RenderType getRenderType() { return renderType; } + + public int getVertexCount() { + return map(Model::vertexCount).orElse(0); + } + + @Override + public String toString() { + return "ModelSupplier{" + map(Model::name).orElse("Uninitialized") + '}'; + } } diff --git a/src/main/java/com/jozufozu/flywheel/core/Models.java b/src/main/java/com/jozufozu/flywheel/core/Models.java index e83da4a89..da92ba1f7 100644 --- a/src/main/java/com/jozufozu/flywheel/core/Models.java +++ b/src/main/java/com/jozufozu/flywheel/core/Models.java @@ -23,7 +23,7 @@ public class Models { } public static ModelSupplier partial(PartialModel partial) { - return PARTIAL.computeIfAbsent(partial, it -> new ModelSupplier(() -> new BlockModel(it.get(), Blocks.AIR.defaultBlockState()))); + return PARTIAL.computeIfAbsent(partial, it -> new ModelSupplier(() -> new BlockModel(it))); } public static ModelSupplier partial(PartialModel partial, Direction dir) { @@ -31,7 +31,7 @@ public class Models { } public static ModelSupplier partial(PartialModel partial, Direction dir, Supplier modelTransform) { - return PARTIAL_DIR.computeIfAbsent(Pair.of(dir, partial), $ -> new ModelSupplier(() -> new BlockModel(partial.get(), Blocks.AIR.defaultBlockState(), modelTransform.get()))); + return PARTIAL_DIR.computeIfAbsent(Pair.of(dir, partial), $ -> new ModelSupplier(() -> new BlockModel(partial, modelTransform.get()))); } public static void onReload(ReloadRenderersEvent ignored) { diff --git a/src/main/java/com/jozufozu/flywheel/core/RenderContext.java b/src/main/java/com/jozufozu/flywheel/core/RenderContext.java new file mode 100644 index 000000000..5ea6a6620 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/RenderContext.java @@ -0,0 +1,52 @@ +package com.jozufozu.flywheel.core; + +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Matrix3f; +import com.mojang.math.Matrix4f; +import com.mojang.math.Quaternion; + +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.renderer.RenderBuffers; +import net.minecraft.client.renderer.RenderType; + +public record RenderContext(ClientLevel level, RenderType type, PoseStack stack, Matrix4f viewProjection, RenderBuffers buffers, + double camX, double camY, double camZ) implements TransformStack { + + @Override + public TransformStack multiply(Quaternion quaternion) { + return TransformStack.cast(stack).multiply(quaternion); + } + + @Override + public TransformStack scale(float factorX, float factorY, float factorZ) { + return TransformStack.cast(stack).scale(factorX, factorY, factorZ); + } + + @Override + public TransformStack pushPose() { + stack.pushPose(); + return TransformStack.cast(stack); + } + + @Override + public TransformStack popPose() { + stack.popPose(); + return TransformStack.cast(stack); + } + + @Override + public TransformStack mulPose(Matrix4f pose) { + return TransformStack.cast(stack).mulPose(pose); + } + + @Override + public TransformStack mulNormal(Matrix3f normal) { + return TransformStack.cast(stack).mulNormal(normal); + } + + @Override + public TransformStack translate(double x, double y, double z) { + return TransformStack.cast(stack).translate(x, y, z); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/core/RenderTypeRegistry.java b/src/main/java/com/jozufozu/flywheel/core/RenderTypeRegistry.java new file mode 100644 index 000000000..06e706641 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/RenderTypeRegistry.java @@ -0,0 +1,19 @@ +package com.jozufozu.flywheel.core; + +import javax.annotation.Nullable; + +import net.minecraft.client.renderer.RenderType; + +public class RenderTypeRegistry { + + + /** + * Gets the alpha discard threshold for the given render layer. + * + * @param layer The render layer to get the alpha discard threshold for. + * @return The alpha discard threshold. + */ + public static float getAlphaDiscard(@Nullable RenderType layer) { + return layer == RenderType.cutoutMipped() ? 0.1f : 0f; + } +} diff --git a/src/main/java/com/jozufozu/flywheel/core/compile/ProgramContext.java b/src/main/java/com/jozufozu/flywheel/core/compile/ProgramContext.java index 3a1c72a79..e5f08ba99 100644 --- a/src/main/java/com/jozufozu/flywheel/core/compile/ProgramContext.java +++ b/src/main/java/com/jozufozu/flywheel/core/compile/ProgramContext.java @@ -2,11 +2,8 @@ package com.jozufozu.flywheel.core.compile; import java.util.Objects; -import javax.annotation.Nullable; - import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.backend.Backend; -import com.jozufozu.flywheel.api.RenderLayer; import com.jozufozu.flywheel.core.GameStateRegistry; import com.jozufozu.flywheel.core.shader.ProgramSpec; import com.jozufozu.flywheel.core.shader.StateSnapshot; @@ -20,29 +17,19 @@ public final class ProgramContext { /** * Creates a compilation context for the given program, vertex type and render layer. * - * @param programName The name of the program to use. - * @param vertexType The vertex type to use. - * @param layer If cutout, the alpha discard threshold is 0.1, otherwise 0. + * @param programName The name of the program to use. + * @param vertexType The vertex type to use. + * @param alphaDiscard The alpha threshold below which pixels are discarded. * @return A compilation context. */ - public static ProgramContext create(ResourceLocation programName, VertexType vertexType, @Nullable RenderLayer layer) { + public static ProgramContext create(ResourceLocation programName, VertexType vertexType, float alphaDiscard) { ProgramSpec spec = Backend.getSpec(programName); if (spec == null) { throw new NullPointerException("Cannot compile shader because '" + programName + "' is not recognized."); } - return new ProgramContext(spec, getAlphaDiscard(layer), vertexType, GameStateRegistry.takeSnapshot()); - } - - /** - * Gets the alpha discard threshold for the given render layer. - * - * @param layer The render layer to get the alpha discard threshold for. - * @return The alpha discard threshold. - */ - public static float getAlphaDiscard(@Nullable RenderLayer layer) { - return layer == RenderLayer.CUTOUT ? 0.1f : 0f; + return new ProgramContext(spec, alphaDiscard, vertexType, GameStateRegistry.takeSnapshot()); } public final ProgramSpec spec; diff --git a/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingGroup.java b/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingGroup.java deleted file mode 100644 index 3bf580899..000000000 --- a/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingGroup.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.jozufozu.flywheel.core.crumbling; - -import com.jozufozu.flywheel.api.RenderLayer; -import com.jozufozu.flywheel.backend.instancing.instancing.InstancedMaterialGroup; -import com.jozufozu.flywheel.backend.instancing.instancing.InstancingEngine; -import com.jozufozu.flywheel.util.Textures; -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.math.Matrix4f; - -import net.minecraft.client.renderer.RenderType; - -public class CrumblingGroup

extends InstancedMaterialGroup

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

owner, RenderType type) { - super(owner, type); - } - - @Override - public void render(Matrix4f viewProjection, double camX, double camY, double camZ, RenderLayer layer) { - type.setupRenderState(); - - int renderTex = RenderSystem.getShaderTexture(0); - - updateAtlasSize(); - - type.clearRenderState(); - - CrumblingRenderer._currentLayer.setupRenderState(); - - int breakingTex = RenderSystem.getShaderTexture(0); - - RenderSystem.setShaderTexture(0, renderTex); - RenderSystem.setShaderTexture(4, breakingTex); - - Textures.bindActiveTextures(); - //renderAll(viewProjection, camX, camY, camZ, layer); - - CrumblingRenderer._currentLayer.clearRenderState(); - } - - private void updateAtlasSize() { - - AtlasInfo.SheetSize sheetSize = AtlasInfo.getSheetSize(Textures.getShaderTexture(0)); - - if (sheetSize != null) { - width = sheetSize.width(); - height = sheetSize.height(); - } else { - width = height = 256; - } - } - - @Override - protected void setup(P p) { - p.setAtlasSize(width, height); - } -} 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 0364a5c74..240ebf1d8 100644 --- a/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingRenderer.java +++ b/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingRenderer.java @@ -2,20 +2,26 @@ package com.jozufozu.flywheel.core.crumbling; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.SortedSet; +import com.jozufozu.flywheel.api.InstanceData; +import com.jozufozu.flywheel.api.struct.Instanced; import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.gl.GlTextureUnit; import com.jozufozu.flywheel.backend.instancing.InstanceManager; import com.jozufozu.flywheel.backend.instancing.SerialTaskEngine; +import com.jozufozu.flywheel.backend.instancing.instancing.InstancedMaterial; import com.jozufozu.flywheel.backend.instancing.instancing.InstancingEngine; import com.jozufozu.flywheel.core.Contexts; +import com.jozufozu.flywheel.core.RenderContext; 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.jozufozu.flywheel.util.Textures; import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Matrix4f; import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; @@ -50,16 +56,17 @@ public class CrumblingRenderer { _init(); } - public static void renderBreaking(RenderLayerEvent event) { - if (!Backend.canUseInstancing(event.getWorld())) return; + public static void renderBreaking(ClientLevel level, PoseStack stack, double x, double y, double z, Matrix4f viewProjection) { - Int2ObjectMap> activeStages = getActiveStageBlockEntities(event.getWorld()); + if (!Backend.canUseInstancing(level)) return; + + Int2ObjectMap> activeStages = getActiveStageBlockEntities(level); if (activeStages.isEmpty()) return; State state = STATE.get(); - InstanceManager instanceManager = state.instanceManager; - InstancingEngine materials = state.materialManager; + var instanceManager = state.instanceManager; + var materials = state.materialManager; TextureManager textureManager = Minecraft.getInstance().getTextureManager(); Camera info = Minecraft.getInstance().gameRenderer.getMainCamera(); @@ -72,8 +79,11 @@ public class CrumblingRenderer { stage.getValue().forEach(instanceManager::add); instanceManager.beginFrame(SerialTaskEngine.INSTANCE, info); + materials.beginFrame(info); - materials.render(SerialTaskEngine.INSTANCE, event); + var ctx = new RenderContext(level, _currentLayer, stack, viewProjection, null, x, y, z); + + materials.render(SerialTaskEngine.INSTANCE, ctx); instanceManager.invalidate(); } @@ -131,13 +141,11 @@ public class CrumblingRenderer { } private static class State { - private final InstancingEngine materialManager; + private final CrumblingEngine materialManager; private final InstanceManager instanceManager; private State() { - materialManager = InstancingEngine.builder(Contexts.CRUMBLING) - .setGroupFactory(CrumblingGroup::new) - .build(); + materialManager = new CrumblingEngine(); instanceManager = new CrumblingInstanceManager(materialManager); materialManager.addListener(instanceManager); } @@ -147,4 +155,51 @@ public class CrumblingRenderer { instanceManager.invalidate(); } } + + private static class CrumblingEngine extends InstancingEngine { + + public CrumblingEngine() { + super(Contexts.CRUMBLING); + } + + @Override + protected void render(RenderType type, double camX, double camY, double camZ, Matrix4f viewProjection) { + type.setupRenderState(); + + int renderTex = RenderSystem.getShaderTexture(0); + + AtlasInfo.SheetSize sheetSize = AtlasInfo.getSheetSize(Textures.getShaderTexture(0)); + + int width; + int height; + if (sheetSize != null) { + width = sheetSize.width(); + height = sheetSize.height(); + } else { + width = height = 256; + } + + type.clearRenderState(); + + CrumblingRenderer._currentLayer.setupRenderState(); + + int breakingTex = RenderSystem.getShaderTexture(0); + + RenderSystem.setShaderTexture(0, renderTex); + RenderSystem.setShaderTexture(4, breakingTex); + + Textures.bindActiveTextures(); + + for (Map.Entry, InstancedMaterial> entry : materials.entrySet()) { + CrumblingProgram program = setup(type, camX, camY, camZ, viewProjection, entry.getKey() + .getProgramSpec()); + + program.setAtlasSize(width, height); + + //entry.getValue().getAllRenderables().forEach(Renderable::draw); + } + + CrumblingRenderer._currentLayer.clearRenderState(); + } + } } diff --git a/src/main/java/com/jozufozu/flywheel/core/model/BlockModel.java b/src/main/java/com/jozufozu/flywheel/core/model/BlockModel.java index 8c527bea6..41563166e 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/BlockModel.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/BlockModel.java @@ -2,10 +2,12 @@ package com.jozufozu.flywheel.core.model; import com.jozufozu.flywheel.api.vertex.VertexList; import com.jozufozu.flywheel.core.Formats; +import com.jozufozu.flywheel.core.PartialModel; import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.client.Minecraft; import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; /** @@ -28,9 +30,21 @@ public class BlockModel implements Model { this(model, referenceState, IDENTITY); } + public BlockModel(PartialModel model) { + this(model, IDENTITY); + } + + public BlockModel(PartialModel model, PoseStack ms) { + this(Formats.BLOCK.createReader(ModelUtil.getBufferBuilder(model.get(), Blocks.AIR.defaultBlockState(), ms)), model.getLocation().toString()); + } + public BlockModel(BakedModel model, BlockState referenceState, PoseStack ms) { - reader = Formats.BLOCK.createReader(ModelUtil.getBufferBuilder(model, referenceState, ms)); - name = referenceState.toString(); + this(Formats.BLOCK.createReader(ModelUtil.getBufferBuilder(model, referenceState, ms)), referenceState.toString()); + } + + public BlockModel(VertexList reader, String name) { + this.reader = reader; + this.name = name; } @Override diff --git a/src/main/java/com/jozufozu/flywheel/event/RenderLayerEvent.java b/src/main/java/com/jozufozu/flywheel/event/RenderLayerEvent.java index c2d321798..45ba469ce 100644 --- a/src/main/java/com/jozufozu/flywheel/event/RenderLayerEvent.java +++ b/src/main/java/com/jozufozu/flywheel/event/RenderLayerEvent.java @@ -1,8 +1,6 @@ package com.jozufozu.flywheel.event; -import javax.annotation.Nullable; - -import com.jozufozu.flywheel.api.RenderLayer; +import com.jozufozu.flywheel.core.RenderContext; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Matrix4f; @@ -13,65 +11,51 @@ import net.minecraft.client.renderer.RenderType; import net.minecraftforge.eventbus.api.Event; public class RenderLayerEvent extends Event { - private final ClientLevel world; - public final RenderType type; - public final PoseStack stack; - public final Matrix4f viewProjection; - public final RenderBuffers buffers; - public final double camX; - public final double camY; - public final double camZ; - public final RenderLayer layer; + public final RenderContext context; public RenderLayerEvent(ClientLevel world, RenderType type, PoseStack stack, RenderBuffers buffers, double camX, double camY, double camZ) { - this.world = world; - this.type = type; - this.stack = stack; - - viewProjection = stack.last() + var viewProjection = stack.last() .pose() .copy(); viewProjection.multiplyBackward(RenderSystem.getProjectionMatrix()); - this.buffers = buffers; - this.camX = camX; - this.camY = camY; - this.camZ = camZ; - - this.layer = RenderLayer.getPrimaryLayer(type); - } - - @Nullable - public RenderLayer getLayer() { - return layer; - } - - public ClientLevel getWorld() { - return world; - } - - public RenderType getType() { - return type; - } - - public Matrix4f getViewProjection() { - return viewProjection; - } - - public double getCamX() { - return camX; - } - - public double getCamY() { - return camY; - } - - public double getCamZ() { - return camZ; + context = new RenderContext(world, type, stack, viewProjection, buffers, camX, camY, camZ); } @Override public String toString() { - return "RenderLayerEvent[" + layer + "][" + "world=" + world + ", type=" + type + ", stack=" + stack + ", viewProjection=" + viewProjection + ", buffers=" + buffers + ", camX=" + camX + ", camY=" + camY + ", camZ=" + camZ + ']'; + return "RenderLayerEvent{" + context + "}"; + } + + public ClientLevel getWorld() { + return context.level(); + } + + public RenderType getType() { + return context.type(); + } + + public PoseStack getStack() { + return context.stack(); + } + + public Matrix4f getViewProjection() { + return context.viewProjection(); + } + + public RenderBuffers getBuffers() { + return context.buffers(); + } + + public double getCamX() { + return context.camX(); + } + + public double getCamY() { + return context.camY(); + } + + public double getCamZ() { + return context.camZ(); } } diff --git a/src/main/java/com/jozufozu/flywheel/mixin/FrustumMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/FrustumMixin.java index c0edf6bf0..ab9eaabbb 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/FrustumMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/FrustumMixin.java @@ -6,6 +6,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import com.jozufozu.flywheel.backend.OptifineHandler; +import com.jozufozu.flywheel.backend.gl.GlStateTracker; import com.jozufozu.flywheel.core.LastActiveCamera; import com.jozufozu.flywheel.event.BeginFrameEvent; @@ -19,7 +20,9 @@ public class FrustumMixin { @Inject(method = "prepare", at = @At("TAIL")) private void onPrepare(double x, double y, double z, CallbackInfo ci) { if (OptifineHandler.isShadowPass()) { + GlStateTracker.State restoreState = GlStateTracker.getRestoreState(); MinecraftForge.EVENT_BUS.post(new BeginFrameEvent(Minecraft.getInstance().level, LastActiveCamera.getActiveCamera(), (Frustum) (Object) this)); + restoreState.restore(); } } } diff --git a/src/main/java/com/jozufozu/flywheel/mixin/LevelRendererMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/LevelRendererMixin.java index 497a81ee5..2622282e7 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/LevelRendererMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/LevelRendererMixin.java @@ -16,6 +16,7 @@ import com.jozufozu.flywheel.core.crumbling.CrumblingRenderer; import com.jozufozu.flywheel.event.BeginFrameEvent; import com.jozufozu.flywheel.event.ReloadRenderersEvent; import com.jozufozu.flywheel.event.RenderLayerEvent; +import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.BufferUploader; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Matrix4f; @@ -48,7 +49,9 @@ public class LevelRendererMixin { @Inject(at = @At("HEAD"), method = "setupRender") private void setupRender(Camera camera, Frustum frustum, boolean queue, boolean isSpectator, CallbackInfo ci) { + GlStateTracker.State restoreState = GlStateTracker.getRestoreState(); MinecraftForge.EVENT_BUS.post(new BeginFrameEvent(level, camera, frustum)); + restoreState.restore(); } @Unique @@ -103,8 +106,13 @@ public class LevelRendererMixin { Vec3 cameraPos = info.getPosition(); + Matrix4f viewProjection = stack.last() + .pose() + .copy(); + viewProjection.multiplyBackward(RenderSystem.getProjectionMatrix()); + GlStateTracker.State restoreState = GlStateTracker.getRestoreState(); - CrumblingRenderer.renderBreaking(new RenderLayerEvent(level, null, stack, null, cameraPos.x, cameraPos.y, cameraPos.z)); + CrumblingRenderer.renderBreaking(level, stack, cameraPos.x, cameraPos.y, cameraPos.z, viewProjection); restoreState.restore(); } diff --git a/src/main/java/com/jozufozu/flywheel/util/Lazy.java b/src/main/java/com/jozufozu/flywheel/util/Lazy.java index 1913beca0..9b35bf323 100644 --- a/src/main/java/com/jozufozu/flywheel/util/Lazy.java +++ b/src/main/java/com/jozufozu/flywheel/util/Lazy.java @@ -1,5 +1,6 @@ package com.jozufozu.flywheel.util; +import java.util.Optional; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; @@ -25,7 +26,7 @@ public class Lazy implements Supplier { return value; } - public Lazy map(Function func) { + public Lazy lazyMap(Function func) { return new Lazy<>(() -> func.apply(get())); } @@ -38,4 +39,18 @@ public class Lazy implements Supplier { func.accept(value); } } + + /** + * If initialized, maps the stored value based on the function, otherwise returns the None. + * @param func The function to map the value with. + * @param The type of the mapped value. + * @return The mapped value, or None if not initialized. + */ + public Optional map(Function func) { + if (value != null) { + return Optional.of(func.apply(value)); + } else { + return Optional.empty(); + } + } }