diff --git a/src/main/java/com/jozufozu/flywheel/api/backend/Engine.java b/src/main/java/com/jozufozu/flywheel/api/backend/Engine.java index a4ddc163c..ed14b4dbb 100644 --- a/src/main/java/com/jozufozu/flywheel/api/backend/Engine.java +++ b/src/main/java/com/jozufozu/flywheel/api/backend/Engine.java @@ -6,13 +6,9 @@ import com.jozufozu.flywheel.api.BackendImplemented; import com.jozufozu.flywheel.api.event.RenderContext; import com.jozufozu.flywheel.api.event.RenderStage; import com.jozufozu.flywheel.api.instance.Instance; -import com.jozufozu.flywheel.api.instance.InstanceType; -import com.jozufozu.flywheel.api.instance.Instancer; -import com.jozufozu.flywheel.api.instance.InstancerProvider; -import com.jozufozu.flywheel.api.model.Model; import com.jozufozu.flywheel.api.task.Plan; import com.jozufozu.flywheel.api.task.TaskExecutor; -import com.jozufozu.flywheel.api.visualization.VisualEmbedding; +import com.jozufozu.flywheel.api.visualization.VisualizationContext; import net.minecraft.client.Camera; import net.minecraft.core.BlockPos; @@ -21,20 +17,12 @@ import net.minecraft.core.Vec3i; @BackendImplemented public interface Engine { /** - * Get an instancer for the given instance type, model, and render stage. + * Create a visualization context that will render to the given stage. * - *

Calling this method twice with the same arguments will return the same instancer.

- * - *

If you are writing a visual you should probably be using - * {@link InstancerProvider#instancer(InstanceType, Model)}, which will decide the {@code RenderStage} - * based on what type of visual is getting the instancer.

- * - * @return An instancer for the given instance type, model, and render stage. - * @see InstancerProvider + * @param stage The stage to render to. + * @return A new visualization context. */ - Instancer instancer(InstanceType type, Model model, RenderStage stage); - - Instancer instancer(VisualEmbedding world, InstanceType type, Model model, RenderStage stage); + VisualizationContext createVisualizationContext(RenderStage stage); /** * Create a plan that will be executed every frame. diff --git a/src/main/java/com/jozufozu/flywheel/api/instance/InstancerProvider.java b/src/main/java/com/jozufozu/flywheel/api/instance/InstancerProvider.java index 4c4ddf92b..07d641c92 100644 --- a/src/main/java/com/jozufozu/flywheel/api/instance/InstancerProvider.java +++ b/src/main/java/com/jozufozu/flywheel/api/instance/InstancerProvider.java @@ -1,10 +1,9 @@ package com.jozufozu.flywheel.api.instance; -import org.jetbrains.annotations.ApiStatus; - +import com.jozufozu.flywheel.api.BackendImplemented; import com.jozufozu.flywheel.api.model.Model; -@ApiStatus.NonExtendable +@BackendImplemented public interface InstancerProvider { /** * Get an instancer for the given instance type rendering the given model. diff --git a/src/main/java/com/jozufozu/flywheel/api/visualization/VisualEmbedding.java b/src/main/java/com/jozufozu/flywheel/api/visualization/VisualEmbedding.java index c308a8003..fe75a0d43 100644 --- a/src/main/java/com/jozufozu/flywheel/api/visualization/VisualEmbedding.java +++ b/src/main/java/com/jozufozu/flywheel/api/visualization/VisualEmbedding.java @@ -3,12 +3,15 @@ package com.jozufozu.flywheel.api.visualization; import org.joml.Matrix3fc; import org.joml.Matrix4fc; -import net.minecraft.world.phys.AABB; +import com.jozufozu.flywheel.api.BackendImplemented; -public interface VisualEmbedding { - Matrix4fc pose(); - - Matrix3fc normal(); - - AABB boundingBox(); +@BackendImplemented +public interface VisualEmbedding extends VisualizationContext { + /** + * Set the transformation matrices for the embedding. + * + * @param pose The model matrix. + * @param normal The normal matrix. + */ + void transforms(Matrix4fc pose, Matrix3fc normal); } diff --git a/src/main/java/com/jozufozu/flywheel/api/visualization/VisualizationContext.java b/src/main/java/com/jozufozu/flywheel/api/visualization/VisualizationContext.java index f8a74775c..88935dd13 100644 --- a/src/main/java/com/jozufozu/flywheel/api/visualization/VisualizationContext.java +++ b/src/main/java/com/jozufozu/flywheel/api/visualization/VisualizationContext.java @@ -2,6 +2,7 @@ package com.jozufozu.flywheel.api.visualization; import org.jetbrains.annotations.ApiStatus; +import com.jozufozu.flywheel.api.BackendImplemented; import com.jozufozu.flywheel.api.instance.InstancerProvider; import net.minecraft.core.Vec3i; @@ -9,7 +10,7 @@ import net.minecraft.core.Vec3i; /** * A context object passed on visual creation. */ -@ApiStatus.NonExtendable +@BackendImplemented public interface VisualizationContext { /** * @return The {@link InstancerProvider} that the visual can use to get instancers to render models. @@ -24,5 +25,5 @@ public interface VisualizationContext { Vec3i renderOrigin(); @ApiStatus.Experimental - VisualizationContext embed(VisualEmbedding world); + VisualEmbedding createEmbedding(); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/AbstractEngine.java b/src/main/java/com/jozufozu/flywheel/backend/engine/AbstractEngine.java index e8e31a641..219b52f56 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/AbstractEngine.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/AbstractEngine.java @@ -5,8 +5,10 @@ import com.jozufozu.flywheel.api.event.RenderStage; import com.jozufozu.flywheel.api.instance.Instance; import com.jozufozu.flywheel.api.instance.InstanceType; import com.jozufozu.flywheel.api.instance.Instancer; +import com.jozufozu.flywheel.api.instance.InstancerProvider; import com.jozufozu.flywheel.api.model.Model; import com.jozufozu.flywheel.api.visualization.VisualEmbedding; +import com.jozufozu.flywheel.api.visualization.VisualizationContext; import net.minecraft.client.Camera; import net.minecraft.core.BlockPos; @@ -21,14 +23,13 @@ public abstract class AbstractEngine implements Engine { sqrMaxOriginDistance = maxOriginDistance * maxOriginDistance; } - @Override - public Instancer instancer(InstanceType type, Model model, RenderStage stage) { - return getStorage().getInstancer(null, type, model, stage); + public Instancer instancer(Environment environment, InstanceType type, Model model, RenderStage stage) { + return getStorage().getInstancer(environment, type, model, stage); } @Override - public Instancer instancer(VisualEmbedding world, InstanceType type, Model model, RenderStage stage) { - return getStorage().getInstancer(world, type, model, stage); + public VisualizationContext createVisualizationContext(RenderStage stage) { + return new VisualizationContextImpl(stage); } @Override @@ -54,4 +55,29 @@ public abstract class AbstractEngine implements Engine { } protected abstract InstancerStorage> getStorage(); + + private class VisualizationContextImpl implements VisualizationContext { + private final InstancerProviderImpl instancerProvider; + private final RenderStage stage; + + public VisualizationContextImpl(RenderStage stage) { + instancerProvider = new InstancerProviderImpl(AbstractEngine.this, stage); + this.stage = stage; + } + + @Override + public InstancerProvider instancerProvider() { + return instancerProvider; + } + + @Override + public Vec3i renderOrigin() { + return AbstractEngine.this.renderOrigin(); + } + + @Override + public VisualEmbedding createEmbedding() { + return new EmbeddedEnvironment(AbstractEngine.this, stage); + } + } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/AbstractInstancer.java b/src/main/java/com/jozufozu/flywheel/backend/engine/AbstractInstancer.java index 6e81b6e26..ad0c6ac1f 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/AbstractInstancer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/AbstractInstancer.java @@ -7,13 +7,11 @@ import org.jetbrains.annotations.Nullable; import com.jozufozu.flywheel.api.instance.Instance; import com.jozufozu.flywheel.api.instance.InstanceType; import com.jozufozu.flywheel.api.instance.Instancer; -import com.jozufozu.flywheel.api.visualization.VisualEmbedding; import com.jozufozu.flywheel.lib.util.AtomicBitset; public abstract class AbstractInstancer implements Instancer { public final InstanceType type; - @Nullable - public final VisualEmbedding embedding; + public final Environment environment; // Lock for all instances, only needs to be used in methods that may run on the TaskExecutor. protected final Object lock = new Object(); @@ -23,9 +21,9 @@ public abstract class AbstractInstancer implements Instancer protected final AtomicBitset changed = new AtomicBitset(); protected final AtomicBitset deleted = new AtomicBitset(); - protected AbstractInstancer(InstanceType type, @Nullable VisualEmbedding embedding) { + protected AbstractInstancer(InstanceType type, Environment environment) { this.type = type; - this.embedding = embedding; + this.environment = environment; } @Override diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/EmbeddedEnvironment.java b/src/main/java/com/jozufozu/flywheel/backend/engine/EmbeddedEnvironment.java new file mode 100644 index 000000000..9256dd0ab --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/EmbeddedEnvironment.java @@ -0,0 +1,81 @@ +package com.jozufozu.flywheel.backend.engine; + +import org.joml.Matrix3f; +import org.joml.Matrix3fc; +import org.joml.Matrix4f; +import org.joml.Matrix4fc; + +import com.jozufozu.flywheel.api.event.RenderStage; +import com.jozufozu.flywheel.api.instance.Instance; +import com.jozufozu.flywheel.api.instance.InstanceType; +import com.jozufozu.flywheel.api.instance.Instancer; +import com.jozufozu.flywheel.api.instance.InstancerProvider; +import com.jozufozu.flywheel.api.model.Model; +import com.jozufozu.flywheel.api.visualization.VisualEmbedding; +import com.jozufozu.flywheel.backend.compile.ContextShader; +import com.jozufozu.flywheel.backend.compile.ContextShaders; +import com.jozufozu.flywheel.backend.gl.shader.GlProgram; + +import net.minecraft.core.Vec3i; + +public class EmbeddedEnvironment implements Environment, VisualEmbedding { + private final Matrix4f pose = new Matrix4f(); + private final Matrix3f normal = new Matrix3f(); + + private final InstancerProvider instancerProvider; + private final AbstractEngine engine; + private final RenderStage renderStage; + + public EmbeddedEnvironment(AbstractEngine engine, RenderStage renderStage) { + this.engine = engine; + this.renderStage = renderStage; + + instancerProvider = new InstancerProvider() { + @Override + public Instancer instancer(InstanceType type, Model model) { + // Kinda cursed usage of anonymous classes here, but it does the job. + return engine.instancer(EmbeddedEnvironment.this, type, model, renderStage); + } + }; + } + + @Override + public void transforms(Matrix4fc pose, Matrix3fc normal) { + this.pose.set(pose); + this.normal.set(normal); + } + + @Override + public ContextShader contextShader() { + return ContextShaders.EMBEDDED; + } + + @Override + public void setupDraw(GlProgram drawProgram) { + drawProgram.setVec3("_flw_oneOverLightBoxSize", 1, 1, 1); + drawProgram.setVec3("_flw_lightVolumeMin", 0, 0, 0); + drawProgram.setMat4("_flw_model", pose); + drawProgram.setMat3("_flw_normal", normal); + } + + @Override + public void setupCull(GlProgram cullProgram) { + cullProgram.setBool("_flw_useEmbeddedModel", true); + cullProgram.setMat4("_flw_embeddedModel", pose); + } + + @Override + public InstancerProvider instancerProvider() { + return instancerProvider; + } + + @Override + public Vec3i renderOrigin() { + return Vec3i.ZERO; + } + + @Override + public VisualEmbedding createEmbedding() { + return new EmbeddedEnvironment(engine, renderStage); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/Environment.java b/src/main/java/com/jozufozu/flywheel/backend/engine/Environment.java new file mode 100644 index 000000000..6b3614e6e --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/Environment.java @@ -0,0 +1,12 @@ +package com.jozufozu.flywheel.backend.engine; + +import com.jozufozu.flywheel.backend.compile.ContextShader; +import com.jozufozu.flywheel.backend.gl.shader.GlProgram; + +public interface Environment { + ContextShader contextShader(); + + void setupDraw(GlProgram drawProgram); + + void setupCull(GlProgram cullProgram); +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/GlobalEnvironment.java b/src/main/java/com/jozufozu/flywheel/backend/engine/GlobalEnvironment.java new file mode 100644 index 000000000..f1c909bcd --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/GlobalEnvironment.java @@ -0,0 +1,27 @@ +package com.jozufozu.flywheel.backend.engine; + +import com.jozufozu.flywheel.backend.compile.ContextShader; +import com.jozufozu.flywheel.backend.compile.ContextShaders; +import com.jozufozu.flywheel.backend.gl.shader.GlProgram; + +public class GlobalEnvironment implements Environment { + public static final GlobalEnvironment INSTANCE = new GlobalEnvironment(); + + private GlobalEnvironment() { + } + + @Override + public ContextShader contextShader() { + return ContextShaders.DEFAULT; + } + + @Override + public void setupDraw(GlProgram drawProgram) { + + } + + @Override + public void setupCull(GlProgram cullProgram) { + cullProgram.setBool("_flw_useEmbeddedModel", false); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/InstancerKey.java b/src/main/java/com/jozufozu/flywheel/backend/engine/InstancerKey.java index 3bb410c63..ecb240dce 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/InstancerKey.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/InstancerKey.java @@ -1,13 +1,10 @@ package com.jozufozu.flywheel.backend.engine; -import org.jetbrains.annotations.Nullable; - import com.jozufozu.flywheel.api.event.RenderStage; import com.jozufozu.flywheel.api.instance.Instance; import com.jozufozu.flywheel.api.instance.InstanceType; import com.jozufozu.flywheel.api.model.Model; -import com.jozufozu.flywheel.api.visualization.VisualEmbedding; -public record InstancerKey(@Nullable VisualEmbedding embedding, InstanceType type, Model model, +public record InstancerKey(Environment environment, InstanceType type, Model model, RenderStage stage) { } diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/InstancerProviderImpl.java b/src/main/java/com/jozufozu/flywheel/backend/engine/InstancerProviderImpl.java new file mode 100644 index 000000000..e3894d308 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/InstancerProviderImpl.java @@ -0,0 +1,15 @@ +package com.jozufozu.flywheel.backend.engine; + +import com.jozufozu.flywheel.api.event.RenderStage; +import com.jozufozu.flywheel.api.instance.Instance; +import com.jozufozu.flywheel.api.instance.InstanceType; +import com.jozufozu.flywheel.api.instance.Instancer; +import com.jozufozu.flywheel.api.instance.InstancerProvider; +import com.jozufozu.flywheel.api.model.Model; + +public record InstancerProviderImpl(AbstractEngine engine, RenderStage renderStage) implements InstancerProvider { + @Override + public Instancer instancer(InstanceType type, Model model) { + return engine.instancer(GlobalEnvironment.INSTANCE, type, model, renderStage); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/InstancerStorage.java b/src/main/java/com/jozufozu/flywheel/backend/engine/InstancerStorage.java index f969df8e2..939cc42b5 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/InstancerStorage.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/InstancerStorage.java @@ -5,15 +5,12 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import org.jetbrains.annotations.Nullable; - import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.api.event.RenderStage; import com.jozufozu.flywheel.api.instance.Instance; import com.jozufozu.flywheel.api.instance.InstanceType; import com.jozufozu.flywheel.api.instance.Instancer; import com.jozufozu.flywheel.api.model.Model; -import com.jozufozu.flywheel.api.visualization.VisualEmbedding; public abstract class InstancerStorage> { /** @@ -30,8 +27,8 @@ public abstract class InstancerStorage> { protected final List> initializationQueue = new ArrayList<>(); @SuppressWarnings("unchecked") - public Instancer getInstancer(@Nullable VisualEmbedding level, InstanceType type, Model model, RenderStage stage) { - return (Instancer) instancers.computeIfAbsent(new InstancerKey<>(level, type, model, stage), this::createAndDeferInit); + public Instancer getInstancer(Environment environment, InstanceType type, Model model, RenderStage stage) { + return (Instancer) instancers.computeIfAbsent(new InstancerKey<>(environment, type, model, stage), this::createAndDeferInit); } public void delete() { diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectCullingGroup.java b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectCullingGroup.java index 5acefaeac..5d08a189e 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectCullingGroup.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectCullingGroup.java @@ -16,17 +16,14 @@ import java.util.EnumMap; import java.util.List; import java.util.Map; -import org.jetbrains.annotations.Nullable; - import com.jozufozu.flywheel.api.event.RenderStage; import com.jozufozu.flywheel.api.instance.Instance; import com.jozufozu.flywheel.api.instance.InstanceType; import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.model.Model; -import com.jozufozu.flywheel.api.visualization.VisualEmbedding; import com.jozufozu.flywheel.backend.compile.ContextShader; -import com.jozufozu.flywheel.backend.compile.ContextShaders; import com.jozufozu.flywheel.backend.compile.IndirectPrograms; +import com.jozufozu.flywheel.backend.engine.Environment; import com.jozufozu.flywheel.backend.engine.MaterialRenderState; import com.jozufozu.flywheel.backend.engine.MeshPool; import com.jozufozu.flywheel.backend.engine.uniform.Uniforms; @@ -41,8 +38,7 @@ public class IndirectCullingGroup { private static final int DRAW_BARRIER_BITS = GL_SHADER_STORAGE_BARRIER_BIT | GL_COMMAND_BARRIER_BIT; private final InstanceType instanceType; - @Nullable - private final VisualEmbedding embedding; + private final Environment environment; private final long objectStride; private final IndirectBuffers buffers; private final List> instancers = new ArrayList<>(); @@ -58,9 +54,9 @@ public class IndirectCullingGroup { private boolean needsDrawSort; private int instanceCountThisFrame; - IndirectCullingGroup(InstanceType instanceType, @Nullable VisualEmbedding embedding, IndirectPrograms programs) { + IndirectCullingGroup(InstanceType instanceType, Environment environment, IndirectPrograms programs) { this.instanceType = instanceType; - this.embedding = embedding; + this.environment = environment; objectStride = instanceType.layout() .byteSize() + IndirectBuffers.INT_SIZE; buffers = new IndirectBuffers(objectStride); @@ -68,7 +64,7 @@ public class IndirectCullingGroup { this.programs = programs; cullProgram = programs.getCullingProgram(instanceType); applyProgram = programs.getApplyProgram(); - drawProgram = programs.getIndirectProgram(instanceType, ContextShaders.forEmbedding(embedding)); + drawProgram = programs.getIndirectProgram(instanceType, environment.contextShader()); } public void flushInstancers() { @@ -130,12 +126,7 @@ public class IndirectCullingGroup { Uniforms.bindFrame(); cullProgram.bind(); - if (embedding != null) { - cullProgram.setBool("_flw_useEmbeddedModel", true); - cullProgram.setMat4("_flw_embeddedModel", embedding.pose()); - } else { - cullProgram.setBool("_flw_useEmbeddedModel", false); - } + environment.setupCull(cullProgram); buffers.bindForCompute(); glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); @@ -208,12 +199,7 @@ public class IndirectCullingGroup { drawProgram.bind(); buffers.bindForDraw(); - if (embedding != null) { - drawProgram.setVec3("_flw_oneOverLightBoxSize", 1, 1, 1); - drawProgram.setVec3("_flw_lightVolumeMin", 0, 0, 0); - drawProgram.setMat4("_flw_model", embedding.pose()); - drawProgram.setMat3("_flw_normal", embedding.normal()); - } + environment.setupDraw(drawProgram); drawBarrier(); diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectDrawManager.java b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectDrawManager.java index 1866f817b..c507ef39e 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectDrawManager.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectDrawManager.java @@ -11,16 +11,14 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.jetbrains.annotations.Nullable; - import com.jozufozu.flywheel.api.backend.Engine; import com.jozufozu.flywheel.api.event.RenderStage; import com.jozufozu.flywheel.api.instance.Instance; import com.jozufozu.flywheel.api.instance.InstanceType; -import com.jozufozu.flywheel.api.visualization.VisualEmbedding; import com.jozufozu.flywheel.backend.compile.ContextShaders; import com.jozufozu.flywheel.backend.compile.IndirectPrograms; import com.jozufozu.flywheel.backend.engine.CommonCrumbling; +import com.jozufozu.flywheel.backend.engine.Environment; import com.jozufozu.flywheel.backend.engine.InstanceHandleImpl; import com.jozufozu.flywheel.backend.engine.InstancerKey; import com.jozufozu.flywheel.backend.engine.InstancerStorage; @@ -62,14 +60,14 @@ public class IndirectDrawManager extends InstancerStorage> @Override protected IndirectInstancer create(InstancerKey key) { - return new IndirectInstancer<>(key.type(), key.embedding(), key.model()); + return new IndirectInstancer<>(key.type(), key.environment(), key.model()); } @SuppressWarnings("unchecked") @Override protected void initialize(InstancerKey key, IndirectInstancer instancer) { - var groupKey = new GroupKey<>(key.type(), key.embedding()); - var group = (IndirectCullingGroup) cullingGroups.computeIfAbsent(groupKey, t -> new IndirectCullingGroup<>(t.type, t.context, programs)); + var groupKey = new GroupKey<>(key.type(), key.environment()); + var group = (IndirectCullingGroup) cullingGroups.computeIfAbsent(groupKey, t -> new IndirectCullingGroup<>(t.type, t.environment, programs)); group.add((IndirectInstancer) instancer, key.model(), key.stage(), meshPool); } @@ -224,7 +222,7 @@ public class IndirectDrawManager extends InstancerStorage> continue; } - byType.computeIfAbsent(new GroupKey<>(instancer.type, instancer.embedding), $ -> new Int2ObjectArrayMap<>()) + byType.computeIfAbsent(new GroupKey<>(instancer.type, instancer.environment), $ -> new Int2ObjectArrayMap<>()) .computeIfAbsent(progress, $ -> new ArrayList<>()) .add(Pair.of(instancer, impl)); } @@ -232,6 +230,6 @@ public class IndirectDrawManager extends InstancerStorage> return byType; } - public record GroupKey(InstanceType type, @Nullable VisualEmbedding context) { + public record GroupKey(InstanceType type, Environment environment) { } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectInstancer.java b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectInstancer.java index 22ed21e5e..88362d85e 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectInstancer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectInstancer.java @@ -3,7 +3,6 @@ package com.jozufozu.flywheel.backend.engine.indirect; import java.util.ArrayList; import java.util.List; -import org.jetbrains.annotations.Nullable; import org.joml.Vector4fc; import org.lwjgl.system.MemoryUtil; @@ -11,8 +10,8 @@ import com.jozufozu.flywheel.api.instance.Instance; import com.jozufozu.flywheel.api.instance.InstanceType; import com.jozufozu.flywheel.api.instance.InstanceWriter; import com.jozufozu.flywheel.api.model.Model; -import com.jozufozu.flywheel.api.visualization.VisualEmbedding; import com.jozufozu.flywheel.backend.engine.AbstractInstancer; +import com.jozufozu.flywheel.backend.engine.Environment; public class IndirectInstancer extends AbstractInstancer { private final long objectStride; @@ -26,8 +25,8 @@ public class IndirectInstancer extends AbstractInstancer private int lastModelIndex = -1; private long lastStartPos = -1; - public IndirectInstancer(InstanceType type, @Nullable VisualEmbedding context, Model model) { - super(type, context); + public IndirectInstancer(InstanceType type, Environment environment, Model model) { + super(type, environment); this.objectStride = type.layout() .byteSize() + IndirectBuffers.INT_SIZE; writer = this.type.writer(); diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedDrawManager.java b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedDrawManager.java index be8600e31..3f0192921 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedDrawManager.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedDrawManager.java @@ -130,12 +130,14 @@ public class InstancedDrawManager extends InstancerStorage continue; } - var embedding = shader.embedding(); + var environment = shader.environment(); var material = shader.material(); - var program = programs.get(shader.instanceType(), ContextShaders.forEmbedding(embedding)); + var program = programs.get(shader.instanceType(), environment.contextShader()); program.bind(); + environment.setupDraw(program); + uploadMaterialUniform(program, material); MaterialRenderState.setup(material); @@ -153,7 +155,7 @@ public class InstancedDrawManager extends InstancerStorage @Override protected InstancedInstancer create(InstancerKey key) { - return new InstancedInstancer<>(key.type(), key.embedding()); + return new InstancedInstancer<>(key.type(), key.environment()); } @Override @@ -167,7 +169,7 @@ public class InstancedDrawManager extends InstancerStorage for (var entry : meshes) { var mesh = meshPool.alloc(entry.mesh()); - ShaderState shaderState = new ShaderState(entry.material(), key.type(), key.embedding()); + ShaderState shaderState = new ShaderState(entry.material(), key.type(), key.environment()); DrawCall drawCall = new DrawCall(instancer, mesh, shaderState); drawSet.put(shaderState, drawCall); diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedInstancer.java b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedInstancer.java index 1682a7011..85684ed92 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedInstancer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedInstancer.java @@ -8,8 +8,8 @@ import org.jetbrains.annotations.Nullable; import com.jozufozu.flywheel.api.instance.Instance; import com.jozufozu.flywheel.api.instance.InstanceType; import com.jozufozu.flywheel.api.instance.InstanceWriter; -import com.jozufozu.flywheel.api.visualization.VisualEmbedding; import com.jozufozu.flywheel.backend.engine.AbstractInstancer; +import com.jozufozu.flywheel.backend.engine.Environment; import com.jozufozu.flywheel.backend.gl.TextureBuffer; import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer; import com.jozufozu.flywheel.backend.gl.buffer.GlBufferUsage; @@ -25,8 +25,8 @@ public class InstancedInstancer extends AbstractInstancer private final List drawCalls = new ArrayList<>(); - public InstancedInstancer(InstanceType type, @Nullable VisualEmbedding context) { - super(type, context); + public InstancedInstancer(InstanceType type, Environment environment) { + super(type, environment); var layout = type.layout(); // Align to one texel in the texture buffer instanceStride = MoreMath.align16(layout.byteSize()); diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/ShaderState.java b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/ShaderState.java index e70b6fb28..420fb7005 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/ShaderState.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/ShaderState.java @@ -1,10 +1,8 @@ package com.jozufozu.flywheel.backend.engine.instancing; -import org.jetbrains.annotations.Nullable; - import com.jozufozu.flywheel.api.instance.InstanceType; import com.jozufozu.flywheel.api.material.Material; -import com.jozufozu.flywheel.api.visualization.VisualEmbedding; +import com.jozufozu.flywheel.backend.engine.Environment; -public record ShaderState(Material material, InstanceType instanceType, @Nullable VisualEmbedding embedding) { +public record ShaderState(Material material, InstanceType instanceType, Environment environment) { } diff --git a/src/main/java/com/jozufozu/flywheel/impl/visualization/InstancerProviderImpl.java b/src/main/java/com/jozufozu/flywheel/impl/visualization/InstancerProviderImpl.java deleted file mode 100644 index 2addd894d..000000000 --- a/src/main/java/com/jozufozu/flywheel/impl/visualization/InstancerProviderImpl.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.jozufozu.flywheel.impl.visualization; - -import java.util.function.Supplier; - -import com.jozufozu.flywheel.api.backend.Engine; -import com.jozufozu.flywheel.api.event.RenderStage; -import com.jozufozu.flywheel.api.instance.Instance; -import com.jozufozu.flywheel.api.instance.InstanceType; -import com.jozufozu.flywheel.api.instance.Instancer; -import com.jozufozu.flywheel.api.instance.InstancerProvider; -import com.jozufozu.flywheel.api.model.Model; -import com.jozufozu.flywheel.api.visualization.VisualEmbedding; -import com.jozufozu.flywheel.api.visualization.VisualizationContext; - -public class InstancerProviderImpl implements InstancerProvider, Supplier { - protected final Engine engine; - protected final RenderStage renderStage; - - public InstancerProviderImpl(Engine engine, RenderStage renderStage) { - this.engine = engine; - this.renderStage = renderStage; - } - - @Override - public Instancer instancer(InstanceType type, Model model) { - return engine.instancer(type, model, renderStage); - } - - @Override - public VisualizationContext get() { - return new VisualizationContextImpl(this, engine.renderOrigin()); - } - - public Embedded embed(VisualEmbedding world) { - return new Embedded(engine, world, renderStage); - } - - @Override - public String toString() { - return "InstancerProviderImpl[" + "engine=" + engine + ", " + "renderStage=" + renderStage + ']'; - } - - public static final class Embedded extends InstancerProviderImpl { - private final VisualEmbedding world; - - public Embedded(Engine engine, VisualEmbedding world, RenderStage renderStage) { - super(engine, renderStage); - this.world = world; - } - - @Override - public Instancer instancer(InstanceType type, Model model) { - return engine.instancer(world, type, model, renderStage); - } - - public VisualEmbedding world() { - return world; - } - - @Override - public String toString() { - return "InstancerProviderImpl.EmbeddedImpl[" + "world=" + world + ", " + "engine=" + engine + ", " + "renderStage=" + renderStage + ']'; - } - } -} diff --git a/src/main/java/com/jozufozu/flywheel/impl/visualization/VisualizationContextImpl.java b/src/main/java/com/jozufozu/flywheel/impl/visualization/VisualizationContextImpl.java deleted file mode 100644 index d2a202212..000000000 --- a/src/main/java/com/jozufozu/flywheel/impl/visualization/VisualizationContextImpl.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.jozufozu.flywheel.impl.visualization; - -import com.jozufozu.flywheel.api.instance.InstancerProvider; -import com.jozufozu.flywheel.api.visualization.VisualEmbedding; -import com.jozufozu.flywheel.api.visualization.VisualizationContext; - -import net.minecraft.core.Vec3i; - -/** - * A context object passed on visual creation. - * - * @param instancerProvider The {@link InstancerProvider} that the visual can use to get instancers to render models. - * @param renderOrigin The origin of the renderer as a world position. - * All models render as if this position is (0, 0, 0). - */ -public record VisualizationContextImpl(InstancerProviderImpl instancerProvider, Vec3i renderOrigin) implements VisualizationContext { - @Override - public VisualizationContext embed(VisualEmbedding world) { - return new VisualizationContextImpl(instancerProvider.embed(world), renderOrigin); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/impl/visualization/VisualizationManagerImpl.java b/src/main/java/com/jozufozu/flywheel/impl/visualization/VisualizationManagerImpl.java index e06ec0f8f..c90389c6d 100644 --- a/src/main/java/com/jozufozu/flywheel/impl/visualization/VisualizationManagerImpl.java +++ b/src/main/java/com/jozufozu/flywheel/impl/visualization/VisualizationManagerImpl.java @@ -3,6 +3,7 @@ package com.jozufozu.flywheel.impl.visualization; import java.util.ArrayList; import java.util.List; import java.util.SortedSet; +import java.util.function.Supplier; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.Nullable; @@ -22,6 +23,7 @@ import com.jozufozu.flywheel.api.visual.TickableVisual; import com.jozufozu.flywheel.api.visual.VisualFrameContext; import com.jozufozu.flywheel.api.visual.VisualTickContext; import com.jozufozu.flywheel.api.visualization.VisualManager; +import com.jozufozu.flywheel.api.visualization.VisualizationContext; import com.jozufozu.flywheel.api.visualization.VisualizationLevel; import com.jozufozu.flywheel.api.visualization.VisualizationManager; import com.jozufozu.flywheel.config.FlwConfig; @@ -84,9 +86,9 @@ public class VisualizationManagerImpl implements VisualizationManager { .createEngine(level); taskExecutor = FlwTaskExecutor.get(); - var blockEntitiesStorage = new BlockEntityStorage(new InstancerProviderImpl(engine, RenderStage.AFTER_BLOCK_ENTITIES)); - var entitiesStorage = new EntityStorage(new InstancerProviderImpl(engine, RenderStage.AFTER_ENTITIES)); - var effectsStorage = new EffectStorage(new InstancerProviderImpl(engine, RenderStage.AFTER_PARTICLES)); + var blockEntitiesStorage = new BlockEntityStorage(provider(engine, RenderStage.AFTER_BLOCK_ENTITIES)); + var entitiesStorage = new EntityStorage(provider(engine, RenderStage.AFTER_ENTITIES)); + var effectsStorage = new EffectStorage(provider(engine, RenderStage.AFTER_PARTICLES)); blockEntities = new VisualManagerImpl<>(blockEntitiesStorage); entities = new VisualManagerImpl<>(entitiesStorage); @@ -118,6 +120,11 @@ public class VisualizationManagerImpl implements VisualizationManager { } } + public static Supplier provider(Engine engine, RenderStage stage) { + var context = engine.createVisualizationContext(stage); + return () -> context; + } + private VisualFrameContext createVisualFrameContext(RenderContext ctx) { Vec3i renderOrigin = engine.renderOrigin(); var cameraPos = ctx.camera()