diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/LightLut.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/LightLut.java index 987ae674b..7494bc666 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/LightLut.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/LightLut.java @@ -11,46 +11,55 @@ // Massive kudos to RogueLogix for figuring out this LUT scheme. // First layer is Y, then X, then Z. public final class LightLut { - public final Layer> indices = new Layer<>(); + public final Layer>> indices = new Layer<>(); - public void add(long position, int index) { + public void add(int scene, long position, int index) { final var x = SectionPos.x(position); final var y = SectionPos.y(position); final var z = SectionPos.z(position); - indices.computeIfAbsent(y, Layer::new) + indices.computeIfAbsent(scene, Layer::new) + .computeIfAbsent(y, Layer::new) .computeIfAbsent(x, IntLayer::new) .set(z, index + 1); } public void prune() { // Maybe this could be done better incrementally? - indices.prune((middle) -> middle.prune(IntLayer::prune)); + indices.prune((scene) -> scene.prune((middle) -> middle.prune(IntLayer::prune))); } - public void remove(long section) { + public void remove(int scene, long section) { final var x = SectionPos.x(section); final var y = SectionPos.y(section); final var z = SectionPos.z(section); - var first = indices.get(y); + var first = indices.get(scene); if (first == null) { return; } - var second = first.get(x); + var second = first.get(y); if (second == null) { return; } - second.clear(z); + var third = second.get(x); + + if (third == null) { + return; + } + + third.clear(z); } public IntArrayList flatten() { final var out = new IntArrayList(); - indices.fillLut(out, (yIndices, lut) -> yIndices.fillLut(lut, IntLayer::fillLut)); + this.indices.fillLut(out, (sceneIndices, lut1) -> sceneIndices.fillLut(lut1, + (yIndices, lut2) -> yIndices.fillLut(lut2, IntLayer::fillLut) + )); return out; } diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/LightStorage.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/LightStorage.java index db248009b..defd91787 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/LightStorage.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/LightStorage.java @@ -195,12 +195,12 @@ private void removeUnusedSections() { } private void beginTrackingSection(long section, int index) { - lut.add(section, index); + lut.add(0, section, index); needsLutRebuild = true; } private void endTrackingSection(long section) { - lut.remove(section); + lut.remove(0, section); needsLutRebuild = true; } diff --git a/common/src/backend/resources/assets/flywheel/flywheel/internal/api_impl.glsl b/common/src/backend/resources/assets/flywheel/flywheel/internal/api_impl.glsl index 1738c38e6..eea26f0c9 100644 --- a/common/src/backend/resources/assets/flywheel/flywheel/internal/api_impl.glsl +++ b/common/src/backend/resources/assets/flywheel/flywheel/internal/api_impl.glsl @@ -3,10 +3,10 @@ struct FlwLightAo { float ao; }; -/// Get the light at the given world position relative to flw_renderOrigin from the given normal. +/// Get the light at the given scene and world position relative to flw_renderOrigin from the given normal. /// This may be interpolated for smooth lighting. -bool flw_light(vec3 worldPos, vec3 normal, out FlwLightAo light); +bool flw_light(uint scene, vec3 worldPos, vec3 normal, out FlwLightAo light); -/// Fetches the light value at the given block position. +/// Fetches the light value at the given scene and block position. /// Returns false if the light for the given block is not available. -bool flw_lightFetch(ivec3 blockPos, out vec2 light); +bool flw_lightFetch(uint scene, ivec3 blockPos, out vec2 light); diff --git a/common/src/backend/resources/assets/flywheel/flywheel/internal/light_lut.glsl b/common/src/backend/resources/assets/flywheel/flywheel/internal/light_lut.glsl index 3c2a7e796..08befbdd1 100644 --- a/common/src/backend/resources/assets/flywheel/flywheel/internal/light_lut.glsl +++ b/common/src/backend/resources/assets/flywheel/flywheel/internal/light_lut.glsl @@ -44,9 +44,14 @@ bool _flw_nextLut(uint base, int coord, out uint next) { return false; } -bool _flw_chunkCoordToSectionIndex(ivec3 sectionPos, out uint index) { +bool _flw_chunkCoordToSectionIndex(uint sceneId, ivec3 sectionPos, out uint index) { + uint scene; + if (_flw_nextLut(0u, int(sceneId), scene) || scene == 0u) { + return true; + } + uint first; - if (_flw_nextLut(0u, sectionPos.y, first) || first == 0u) { + if (_flw_nextLut(scene, sectionPos.y, first) || first == 0u) { return true; } @@ -90,9 +95,9 @@ bool _flw_isSolid(uint sectionOffset, uvec3 blockInSectionPos) { return (word & (1u << bitInWordOffset)) != 0u; } -bool flw_lightFetch(ivec3 blockPos, out vec2 lightCoord) { +bool flw_lightFetch(uint scene, ivec3 blockPos, out vec2 lightCoord) { uint lightSectionIndex; - if (_flw_chunkCoordToSectionIndex(blockPos >> 4, lightSectionIndex)) { + if (_flw_chunkCoordToSectionIndex(scene, blockPos >> 4, lightSectionIndex)) { return false; } // The offset of the section in the light buffer. @@ -307,14 +312,14 @@ vec3 _flw_lightForDirection(uint[27] lights, vec3 interpolant, uint c00, uint c0 return light; } -bool flw_light(vec3 worldPos, vec3 normal, out FlwLightAo light) { +bool flw_light(uint scene, vec3 worldPos, vec3 normal, out FlwLightAo light) { // Always use the section of the block we are contained in to ensure accuracy. // We don't want to interpolate between sections, but also we might not be able // to rely on the existence neighboring sections, so don't do any extra rounding here. ivec3 blockPos = ivec3(floor(worldPos)) + flw_renderOrigin; uint lightSectionIndex; - if (_flw_chunkCoordToSectionIndex(blockPos >> 4, lightSectionIndex)) { + if (_flw_chunkCoordToSectionIndex(scene, blockPos >> 4, lightSectionIndex)) { return false; } // The offset of the section in the light buffer. diff --git a/common/src/lib/resources/assets/flywheel/flywheel/light/flat.glsl b/common/src/lib/resources/assets/flywheel/flywheel/light/flat.glsl index 017929019..e1a465a56 100644 --- a/common/src/lib/resources/assets/flywheel/flywheel/light/flat.glsl +++ b/common/src/lib/resources/assets/flywheel/flywheel/light/flat.glsl @@ -1,6 +1,6 @@ void flw_shaderLight() { vec2 embeddedLight; - if (flw_lightFetch(ivec3(floor(flw_vertexPos.xyz)) + flw_renderOrigin, embeddedLight)) { + if (flw_lightFetch(0, ivec3(floor(flw_vertexPos.xyz)) + flw_renderOrigin, embeddedLight)) { flw_fragLight = max(flw_fragLight, embeddedLight); } } diff --git a/common/src/lib/resources/assets/flywheel/flywheel/light/smooth.glsl b/common/src/lib/resources/assets/flywheel/flywheel/light/smooth.glsl index 4844308d9..915069c9d 100644 --- a/common/src/lib/resources/assets/flywheel/flywheel/light/smooth.glsl +++ b/common/src/lib/resources/assets/flywheel/flywheel/light/smooth.glsl @@ -1,6 +1,6 @@ void flw_shaderLight() { FlwLightAo light; - if (flw_light(flw_vertexPos.xyz, flw_vertexNormal, light)) { + if (flw_light(0, flw_vertexPos.xyz, flw_vertexNormal, light)) { flw_fragLight = max(flw_fragLight, light.light); flw_fragColor.rgb *= light.ao; diff --git a/common/src/lib/resources/assets/flywheel/flywheel/light/smooth_when_embedded.glsl b/common/src/lib/resources/assets/flywheel/flywheel/light/smooth_when_embedded.glsl index 035c6e9ad..fb7bc2870 100644 --- a/common/src/lib/resources/assets/flywheel/flywheel/light/smooth_when_embedded.glsl +++ b/common/src/lib/resources/assets/flywheel/flywheel/light/smooth_when_embedded.glsl @@ -1,7 +1,7 @@ void flw_shaderLight() { #ifdef FLW_EMBEDDED FlwLightAo light; - if (flw_light(flw_vertexPos.xyz, flw_vertexNormal, light)) { + if (flw_light(0, flw_vertexPos.xyz, flw_vertexNormal, light)) { flw_fragLight = max(flw_fragLight, light.light); flw_fragColor.rgb *= light.ao; diff --git a/docs/shader-api/common.glsl b/docs/shader-api/common.glsl index 4b073f1db..6916e7482 100644 --- a/docs/shader-api/common.glsl +++ b/docs/shader-api/common.glsl @@ -3,10 +3,10 @@ struct FlwLightAo { float ao; }; -/// Get the light at the given world position. +/// Get the light at the given scene and world position. /// This may be interpolated for smooth lighting. -bool flw_light(vec3 worldPos, vec3 normal, out FlwLightAo light); +bool flw_light(uint scene, vec3 worldPos, vec3 normal, out FlwLightAo light); -/// Fetches the light value at the given block position. +/// Fetches the light value at the given scene and block position. /// Returns false if the light for the given block is not available. -bool flw_lightFetch(ivec3 blockPos, out vec2 light); +bool flw_lightFetch(uint scene, ivec3 blockPos, out vec2 light);