diff --git a/common/src/api/java/dev/engine_room/flywheel/api/backend/Engine.java b/common/src/api/java/dev/engine_room/flywheel/api/backend/Engine.java
index ab7d41ee9..64e960240 100644
--- a/common/src/api/java/dev/engine_room/flywheel/api/backend/Engine.java
+++ b/common/src/api/java/dev/engine_room/flywheel/api/backend/Engine.java
@@ -9,6 +9,7 @@
import dev.engine_room.flywheel.api.task.Plan;
import dev.engine_room.flywheel.api.task.TaskExecutor;
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
+import it.unimi.dsi.fastutil.longs.LongSet;
import net.minecraft.client.Camera;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Vec3i;
@@ -68,6 +69,13 @@ public interface Engine {
*/
void delete();
+ /**
+ * Assign the set of sections that visuals have requested GPU light for.
+ *
+ * @param sections The set of sections.
+ */
+ void lightSections(LongSet sections);
+
/**
* A block to be rendered as a crumbling overlay.
* @param progress The progress of the crumbling animation in the range [0, 10).
diff --git a/common/src/api/java/dev/engine_room/flywheel/api/visual/LitVisual.java b/common/src/api/java/dev/engine_room/flywheel/api/visual/LitVisual.java
index 4f05e7687..9891962ea 100644
--- a/common/src/api/java/dev/engine_room/flywheel/api/visual/LitVisual.java
+++ b/common/src/api/java/dev/engine_room/flywheel/api/visual/LitVisual.java
@@ -2,6 +2,8 @@
import java.util.function.LongConsumer;
+import org.jetbrains.annotations.ApiStatus;
+
import net.minecraft.core.SectionPos;
/**
@@ -51,6 +53,7 @@ public interface LitVisual extends Visual {
* A notifier object that can be used to indicate to the impl
* that the sections a visual is contained in have changed.
*/
+ @ApiStatus.NonExtendable
interface Notifier {
/**
* Invoke this to indicate to the impl that your visual has moved to a different set of sections.
diff --git a/common/src/api/java/dev/engine_room/flywheel/api/visual/SmoothLitVisual.java b/common/src/api/java/dev/engine_room/flywheel/api/visual/SmoothLitVisual.java
new file mode 100644
index 000000000..43daf3757
--- /dev/null
+++ b/common/src/api/java/dev/engine_room/flywheel/api/visual/SmoothLitVisual.java
@@ -0,0 +1,24 @@
+package dev.engine_room.flywheel.api.visual;
+
+import org.jetbrains.annotations.ApiStatus;
+
+import it.unimi.dsi.fastutil.longs.LongSet;
+
+public interface SmoothLitVisual extends Visual {
+ /**
+ * Set the section property object.
+ *
+ *
This method is only called once, upon visual creation,
+ *
+ * @param property The property.
+ */
+ void setSectionProperty(SectionProperty property);
+
+ @ApiStatus.NonExtendable
+ interface SectionProperty {
+ /**
+ * Invoke this to indicate to the impl that your visual has moved to a different set of sections.
+ */
+ void lightSections(LongSet sections);
+ }
+}
diff --git a/common/src/api/java/dev/engine_room/flywheel/api/visualization/VisualEmbedding.java b/common/src/api/java/dev/engine_room/flywheel/api/visualization/VisualEmbedding.java
index e0b6d4f81..baf35844c 100644
--- a/common/src/api/java/dev/engine_room/flywheel/api/visualization/VisualEmbedding.java
+++ b/common/src/api/java/dev/engine_room/flywheel/api/visualization/VisualEmbedding.java
@@ -4,7 +4,6 @@
import org.joml.Matrix4fc;
import dev.engine_room.flywheel.api.BackendImplemented;
-import it.unimi.dsi.fastutil.longs.LongSet;
@BackendImplemented
public interface VisualEmbedding extends VisualizationContext {
@@ -16,8 +15,6 @@ public interface VisualEmbedding extends VisualizationContext {
*/
void transforms(Matrix4fc pose, Matrix3fc normal);
- void lightChunks(LongSet chunks);
-
/**
* Delete this embedding.
*
diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/EngineImpl.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/EngineImpl.java
index 1912bbf23..fa36cd21f 100644
--- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/EngineImpl.java
+++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/EngineImpl.java
@@ -22,6 +22,7 @@
import dev.engine_room.flywheel.lib.task.Flag;
import dev.engine_room.flywheel.lib.task.NamedFlag;
import dev.engine_room.flywheel.lib.task.SyncedPlan;
+import it.unimi.dsi.fastutil.longs.LongSet;
import net.minecraft.client.Camera;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Vec3i;
@@ -41,7 +42,7 @@ public EngineImpl(LevelAccessor level, DrawManager extends AbstractInstancer
this.drawManager = drawManager;
sqrMaxOriginDistance = maxOriginDistance * maxOriginDistance;
environmentStorage = new EnvironmentStorage();
- lightStorage = new LightStorage(level, environmentStorage);
+ lightStorage = new LightStorage(level);
}
@Override
@@ -101,6 +102,11 @@ public void delete() {
lightStorage.delete();
}
+ @Override
+ public void lightSections(LongSet sections) {
+ lightStorage.sections(sections);
+ }
+
public Instancer instancer(Environment environment, InstanceType type, Model model, RenderStage stage) {
return drawManager.getInstancer(environment, type, model, stage);
}
diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/EnvironmentStorage.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/EnvironmentStorage.java
index 66e3a9dd5..e68ea5250 100644
--- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/EnvironmentStorage.java
+++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/EnvironmentStorage.java
@@ -1,8 +1,6 @@
package dev.engine_room.flywheel.backend.engine;
import dev.engine_room.flywheel.backend.engine.embed.AbstractEmbeddedEnvironment;
-import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
-import it.unimi.dsi.fastutil.longs.LongSet;
import it.unimi.dsi.fastutil.objects.ReferenceLinkedOpenHashSet;
import it.unimi.dsi.fastutil.objects.ReferenceSet;
import it.unimi.dsi.fastutil.objects.ReferenceSets;
@@ -18,10 +16,4 @@ public void flush() {
environments.removeIf(AbstractEmbeddedEnvironment::isDeleted);
environments.forEach(AbstractEmbeddedEnvironment::flush);
}
-
- public LongSet allLightSections() {
- var out = new LongOpenHashSet();
- environments.forEach(e -> e.addLightSections(out));
- return out;
- }
}
diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/AbstractEmbeddedEnvironment.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/AbstractEmbeddedEnvironment.java
index 2861dee83..6bf89450c 100644
--- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/AbstractEmbeddedEnvironment.java
+++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/AbstractEmbeddedEnvironment.java
@@ -15,7 +15,6 @@
import dev.engine_room.flywheel.backend.compile.ContextShader;
import dev.engine_room.flywheel.backend.engine.EngineImpl;
import dev.engine_room.flywheel.backend.gl.shader.GlProgram;
-import it.unimi.dsi.fastutil.longs.LongSet;
import net.minecraft.core.Vec3i;
public abstract class AbstractEmbeddedEnvironment implements Environment, VisualEmbedding {
@@ -95,10 +94,6 @@ public boolean isDeleted() {
return deleted;
}
- public void addLightSections(LongSet out) {
-
- }
-
/**
* Called by visuals
*/
diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/LightStorage.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/LightStorage.java
index 02cd179e8..c9dd9b179 100644
--- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/LightStorage.java
+++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/LightStorage.java
@@ -2,11 +2,11 @@
import java.util.BitSet;
+import org.jetbrains.annotations.Nullable;
import org.lwjgl.system.MemoryUtil;
import dev.engine_room.flywheel.api.event.RenderContext;
import dev.engine_room.flywheel.api.task.Plan;
-import dev.engine_room.flywheel.backend.engine.EnvironmentStorage;
import dev.engine_room.flywheel.backend.engine.indirect.StagingBuffer;
import dev.engine_room.flywheel.backend.gl.buffer.GlBuffer;
import dev.engine_room.flywheel.lib.task.SimplePlan;
@@ -40,7 +40,6 @@ public class LightStorage {
private static final int INVALID_SECTION = -1;
private final LevelAccessor level;
- private final EnvironmentStorage environmentStorage;
private final Arena arena;
private final Long2IntMap section2ArenaIndex = new Long2IntOpenHashMap();
@@ -51,18 +50,26 @@ public class LightStorage {
private final BitSet changed = new BitSet();
private boolean needsLutRebuild = false;
- public LightStorage(LevelAccessor level, EnvironmentStorage environmentStorage) {
+ @Nullable
+ private LongSet requestedSections;
+
+ public LightStorage(LevelAccessor level) {
this.level = level;
- this.environmentStorage = environmentStorage;
arena = new Arena(SECTION_SIZE_BYTES, DEFAULT_ARENA_CAPACITY_SECTIONS);
}
+ public void sections(LongSet sections) {
+ requestedSections = sections;
+ }
+
public Plan createFramePlan() {
return SimplePlan.of(() -> {
- var allLightSections = environmentStorage.allLightSections();
+ if (requestedSections == null) {
+ return;
+ }
- removeUnusedSections(allLightSections);
+ removeUnusedSections(requestedSections);
var knownSections = section2ArenaIndex.keySet();
@@ -70,7 +77,7 @@ public Plan createFramePlan() {
.getUpdatedSections();
// Only add the new sections.
- allLightSections.removeAll(knownSections);
+ requestedSections.removeAll(knownSections);
for (long updatedSection : updatedSections) {
for (int x = -1; x <= 1; x++) {
@@ -78,14 +85,14 @@ public Plan createFramePlan() {
for (int z = -1; z <= 1; z++) {
long section = SectionPos.offset(updatedSection, x, y, z);
if (knownSections.contains(section)) {
- allLightSections.add(section);
+ requestedSections.add(section);
}
}
}
}
}
- for (long section : allLightSections) {
+ for (long section : requestedSections) {
addSection(section);
}
});
diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/NestedEmbeddedEnvironment.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/NestedEmbeddedEnvironment.java
index 516d1f358..fb4bfbb49 100644
--- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/NestedEmbeddedEnvironment.java
+++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/NestedEmbeddedEnvironment.java
@@ -5,7 +5,6 @@
import dev.engine_room.flywheel.api.event.RenderStage;
import dev.engine_room.flywheel.backend.engine.EngineImpl;
-import it.unimi.dsi.fastutil.longs.LongSet;
public class NestedEmbeddedEnvironment extends AbstractEmbeddedEnvironment {
private final AbstractEmbeddedEnvironment parent;
@@ -15,11 +14,6 @@ public NestedEmbeddedEnvironment(AbstractEmbeddedEnvironment parent, EngineImpl
this.parent = parent;
}
- @Override
- public void lightChunks(LongSet chunks) {
- // noop
- }
-
@Override
public void composeMatrices(Matrix4f pose, Matrix3f normal) {
parent.composeMatrices(pose, normal);
diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/TopLevelEmbeddedEnvironment.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/TopLevelEmbeddedEnvironment.java
index 4c58a8660..297c3dd6b 100644
--- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/TopLevelEmbeddedEnvironment.java
+++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/TopLevelEmbeddedEnvironment.java
@@ -5,27 +5,12 @@
import dev.engine_room.flywheel.api.event.RenderStage;
import dev.engine_room.flywheel.backend.engine.EngineImpl;
-import it.unimi.dsi.fastutil.longs.LongArraySet;
-import it.unimi.dsi.fastutil.longs.LongSet;
public class TopLevelEmbeddedEnvironment extends AbstractEmbeddedEnvironment {
- private final LongSet lightSections = new LongArraySet();
-
public TopLevelEmbeddedEnvironment(EngineImpl engine, RenderStage renderStage) {
super(engine, renderStage);
}
- @Override
- public void lightChunks(LongSet chunks) {
- lightSections.clear();
- lightSections.addAll(chunks);
- }
-
- @Override
- public void addLightSections(LongSet out) {
- out.addAll(lightSections);
- }
-
@Override
public void composeMatrices(Matrix4f pose, Matrix3f normal) {
pose.set(this.pose);
diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/visualization/VisualizationManagerImpl.java b/common/src/main/java/dev/engine_room/flywheel/impl/visualization/VisualizationManagerImpl.java
index e0accaf2d..7b2f9920e 100644
--- a/common/src/main/java/dev/engine_room/flywheel/impl/visualization/VisualizationManagerImpl.java
+++ b/common/src/main/java/dev/engine_room/flywheel/impl/visualization/VisualizationManagerImpl.java
@@ -45,6 +45,7 @@
import dev.engine_room.flywheel.lib.task.SimplePlan;
import dev.engine_room.flywheel.lib.util.LevelAttached;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
+import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
import net.minecraft.client.Minecraft;
import net.minecraft.core.Vec3i;
import net.minecraft.server.level.BlockDestructionProgress;
@@ -104,6 +105,14 @@ private VisualizationManagerImpl(LevelAccessor level) {
.ifTrue(recreate)
.ifFalse(update)
.plan()
+ .then(SimplePlan.of(() -> {
+ // TODO: Lazily re-evaluate the union'd set
+ var out = new LongOpenHashSet();
+ out.addAll(blockEntities.lightSections());
+ out.addAll(entities.lightSections());
+ out.addAll(effects.lightSections());
+ engine.lightSections(out);
+ }))
.then(RaisePlan.raise(frameVisualsFlag))
.then(engine.createFramePlan())
.then(RaisePlan.raise(frameFlag));
diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/visualization/manager/VisualManagerImpl.java b/common/src/main/java/dev/engine_room/flywheel/impl/visualization/manager/VisualManagerImpl.java
index 3abc3c7ac..213b9b436 100644
--- a/common/src/main/java/dev/engine_room/flywheel/impl/visualization/manager/VisualManagerImpl.java
+++ b/common/src/main/java/dev/engine_room/flywheel/impl/visualization/manager/VisualManagerImpl.java
@@ -10,6 +10,7 @@
import dev.engine_room.flywheel.impl.visualization.storage.Storage;
import dev.engine_room.flywheel.impl.visualization.storage.Transaction;
import dev.engine_room.flywheel.lib.task.SimplePlan;
+import it.unimi.dsi.fastutil.longs.LongSet;
public class VisualManagerImpl> implements VisualManager {
private final Queue> queue = new ConcurrentLinkedQueue<>();
@@ -74,4 +75,8 @@ public Plan tickPlan() {
return SimplePlan.of(context -> processQueue(1))
.then(storage.tickPlan());
}
+
+ public LongSet lightSections() {
+ return getStorage().lightSections();
+ }
}
diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/visualization/storage/SmoothLitVisualStorage.java b/common/src/main/java/dev/engine_room/flywheel/impl/visualization/storage/SmoothLitVisualStorage.java
new file mode 100644
index 000000000..2dbe51d3b
--- /dev/null
+++ b/common/src/main/java/dev/engine_room/flywheel/impl/visualization/storage/SmoothLitVisualStorage.java
@@ -0,0 +1,45 @@
+package dev.engine_room.flywheel.impl.visualization.storage;
+
+import java.util.Map;
+
+import dev.engine_room.flywheel.api.visual.SmoothLitVisual;
+import it.unimi.dsi.fastutil.longs.LongArraySet;
+import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
+import it.unimi.dsi.fastutil.longs.LongSet;
+import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
+
+public class SmoothLitVisualStorage {
+ private final Map visuals = new Reference2ObjectOpenHashMap<>();
+
+ public LongSet sections() {
+ var out = new LongOpenHashSet();
+ for (SectionProperty value : visuals.values()) {
+ out.addAll(value.sections);
+ }
+ return out;
+ }
+
+ public void remove(SmoothLitVisual smoothLit) {
+ visuals.remove(smoothLit);
+ }
+
+ public void add(SmoothLitVisual smoothLit) {
+ var sections = new SectionProperty();
+ visuals.put(smoothLit, sections);
+ smoothLit.setSectionProperty(sections);
+ }
+
+ public void clear() {
+ visuals.clear();
+ }
+
+ private static final class SectionProperty implements SmoothLitVisual.SectionProperty {
+ private final LongSet sections = new LongArraySet();
+
+ @Override
+ public void lightSections(LongSet sections) {
+ this.sections.clear();
+ this.sections.addAll(sections);
+ }
+ }
+}
diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/visualization/storage/Storage.java b/common/src/main/java/dev/engine_room/flywheel/impl/visualization/storage/Storage.java
index b599dc26e..e2445ddd9 100644
--- a/common/src/main/java/dev/engine_room/flywheel/impl/visualization/storage/Storage.java
+++ b/common/src/main/java/dev/engine_room/flywheel/impl/visualization/storage/Storage.java
@@ -11,6 +11,7 @@
import dev.engine_room.flywheel.api.task.Plan;
import dev.engine_room.flywheel.api.visual.DynamicVisual;
import dev.engine_room.flywheel.api.visual.LitVisual;
+import dev.engine_room.flywheel.api.visual.SmoothLitVisual;
import dev.engine_room.flywheel.api.visual.TickableVisual;
import dev.engine_room.flywheel.api.visual.Visual;
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
@@ -19,6 +20,7 @@
import dev.engine_room.flywheel.lib.task.PlanMap;
import dev.engine_room.flywheel.lib.visual.SimpleDynamicVisual;
import dev.engine_room.flywheel.lib.visual.SimpleTickableVisual;
+import it.unimi.dsi.fastutil.longs.LongSet;
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
public abstract class Storage {
@@ -28,6 +30,7 @@ public abstract class Storage {
protected final List simpleDynamicVisuals = new ArrayList<>();
protected final List simpleTickableVisuals = new ArrayList<>();
protected final LitVisualStorage litVisuals = new LitVisualStorage();
+ protected final SmoothLitVisualStorage smoothLitVisuals = new SmoothLitVisualStorage();
private final Map visuals = new Reference2ObjectOpenHashMap<>();
@@ -71,6 +74,9 @@ public void remove(T obj) {
if (visual instanceof LitVisual lit) {
litVisuals.remove(lit);
}
+ if (visual instanceof SmoothLitVisual smoothLit) {
+ smoothLitVisuals.remove(smoothLit);
+ }
visual.delete();
}
@@ -90,6 +96,7 @@ public void recreateAll(float partialTick) {
simpleTickableVisuals.clear();
simpleDynamicVisuals.clear();
litVisuals.clear();
+ smoothLitVisuals.clear();
visuals.replaceAll((obj, visual) -> {
visual.delete();
@@ -156,6 +163,10 @@ private void setup(Visual visual) {
if (visual instanceof LitVisual lit) {
litVisuals.setNotifierAndAdd(lit);
}
+
+ if (visual instanceof SmoothLitVisual smoothLit) {
+ smoothLitVisuals.add(smoothLit);
+ }
}
/**
@@ -164,4 +175,8 @@ private void setup(Visual visual) {
* @return true if the object is currently capable of being visualized.
*/
public abstract boolean willAccept(T obj);
+
+ public LongSet lightSections() {
+ return smoothLitVisuals.sections();
+ }
}