From 31eebe55a220c5817186941dcc2be9fa893a1537 Mon Sep 17 00:00:00 2001 From: douira Date: Thu, 14 Nov 2024 21:50:03 +0100 Subject: [PATCH 1/9] fix to work with current sodium use maven local sodium make the local dependency refresh automatically --- common/build.gradle.kts | 5 ++++- .../iris/vertices/sodium/terrain/XHFPTerrainVertex.java | 1 - fabric/build.gradle.kts | 5 ++++- neoforge/build.gradle.kts | 5 ++++- settings.gradle.kts | 2 +- 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/common/build.gradle.kts b/common/build.gradle.kts index 2b324314c2..a864c9cc0e 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -59,7 +59,10 @@ dependencies { modCompileOnly("net.fabricmc.fabric-api:fabric-renderer-api-v1:3.2.9+1172e897d7") - modImplementation("maven.modrinth", "sodium", "mc1.21.3-0.6.0-fabric") + // modImplementation("maven.modrinth", "sodium", "mc1.21-0.6.0-beta.2-fabric") + modImplementation("net.caffeinemc", "fabric", "0.6.0-snapshot+mc1.21.3-local") { + isChanging = true + } modCompileOnly("org.antlr:antlr4-runtime:4.13.1") modCompileOnly("io.github.douira:glsl-transformer:2.0.1") modCompileOnly("org.anarres:jcpp:1.4.14") diff --git a/common/src/main/java/net/irisshaders/iris/vertices/sodium/terrain/XHFPTerrainVertex.java b/common/src/main/java/net/irisshaders/iris/vertices/sodium/terrain/XHFPTerrainVertex.java index 2328b30d21..541cd3ee50 100644 --- a/common/src/main/java/net/irisshaders/iris/vertices/sodium/terrain/XHFPTerrainVertex.java +++ b/common/src/main/java/net/irisshaders/iris/vertices/sodium/terrain/XHFPTerrainVertex.java @@ -3,7 +3,6 @@ import net.caffeinemc.mods.sodium.api.util.ColorABGR; import net.caffeinemc.mods.sodium.api.util.ColorARGB; import net.caffeinemc.mods.sodium.client.render.chunk.vertex.format.ChunkVertexEncoder; -import net.caffeinemc.mods.sodium.client.render.frapi.helper.ColorHelper; import net.irisshaders.iris.shaderpack.materialmap.WorldRenderingSettings; import net.irisshaders.iris.vertices.ExtendedDataHelper; import net.irisshaders.iris.vertices.NormI8; diff --git a/fabric/build.gradle.kts b/fabric/build.gradle.kts index 26992bef78..7099ed2e6e 100644 --- a/fabric/build.gradle.kts +++ b/fabric/build.gradle.kts @@ -64,7 +64,10 @@ dependencies { addRuntimeFabricModule("fabric-rendering-fluids-v1") addRuntimeFabricModule("fabric-resource-loader-v0") - modImplementation("maven.modrinth", "sodium", "mc1.21.3-0.6.0-fabric") + // modImplementation("maven.modrinth", "sodium", "mc1.21-0.6.0-beta.2-fabric") + modImplementation("net.caffeinemc", "fabric", "0.6.0-snapshot+mc1.21.3-local") { + isChanging = true + } implementAndInclude("org.antlr:antlr4-runtime:4.13.1") implementAndInclude("io.github.douira:glsl-transformer:2.0.1") implementAndInclude("org.anarres:jcpp:1.4.14") diff --git a/neoforge/build.gradle.kts b/neoforge/build.gradle.kts index 78590119f5..7fce54c7be 100644 --- a/neoforge/build.gradle.kts +++ b/neoforge/build.gradle.kts @@ -126,7 +126,10 @@ dependencies { runtimeOnly("org.sinytra.forgified-fabric-api:fabric-rendering-data-attachment-v1:0.3.48+73761d2e19") runtimeOnly("org.sinytra.forgified-fabric-api:fabric-block-view-api-v2:1.0.10+9afaaf8c19") - implementation("maven.modrinth", "sodium", "mc1.21.3-0.6.0-neoforge") + // implementation("maven.modrinth", "sodium", "mc1.21-0.6.0-beta.2-neoforge") + implementation("net.caffeinemc", "neoforge", "0.6.0-snapshot+mc1.21.3-local") { + isChanging = true + } includeAdditional("io.github.douira:glsl-transformer:2.0.1") includeAdditional("org.anarres:jcpp:1.4.14") includeAdditional("org.antlr:antlr4-runtime:4.13.1") diff --git a/settings.gradle.kts b/settings.gradle.kts index a48a25c429..98f74668e2 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -8,4 +8,4 @@ pluginManagement { } } -include("common", "fabric", "neoforge") +include("common", "fabric") From 2ab7eeb158a5029788f06868ffa28cae4f2406c4 Mon Sep 17 00:00:00 2001 From: IMS Date: Sun, 24 Nov 2024 03:54:37 +0100 Subject: [PATCH 2/9] fix CloudRenderer --- .../sodium/mixin/CloudRendererAccessor.java | 14 +++ .../sodium/mixin/MixinCloudRenderer.java | 98 +++++++++++++------ .../mixin/MixinShaderManager_Overrides.java | 5 +- .../resources/mixins.iris.compat.sodium.json | 1 + 4 files changed, 86 insertions(+), 32 deletions(-) create mode 100644 common/src/main/java/net/irisshaders/iris/compat/sodium/mixin/CloudRendererAccessor.java diff --git a/common/src/main/java/net/irisshaders/iris/compat/sodium/mixin/CloudRendererAccessor.java b/common/src/main/java/net/irisshaders/iris/compat/sodium/mixin/CloudRendererAccessor.java new file mode 100644 index 0000000000..a2a2156dbd --- /dev/null +++ b/common/src/main/java/net/irisshaders/iris/compat/sodium/mixin/CloudRendererAccessor.java @@ -0,0 +1,14 @@ +package net.irisshaders.iris.compat.sodium.mixin; + +import net.caffeinemc.mods.sodium.client.render.immediate.CloudRenderer; +import net.minecraft.client.renderer.ShaderProgram; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(CloudRenderer.class) +public interface CloudRendererAccessor { + @Accessor + static ShaderProgram getCLOUDS_SHADER() { + throw new IllegalStateException(); + } +} diff --git a/common/src/main/java/net/irisshaders/iris/compat/sodium/mixin/MixinCloudRenderer.java b/common/src/main/java/net/irisshaders/iris/compat/sodium/mixin/MixinCloudRenderer.java index 67200c77e7..716b735558 100644 --- a/common/src/main/java/net/irisshaders/iris/compat/sodium/mixin/MixinCloudRenderer.java +++ b/common/src/main/java/net/irisshaders/iris/compat/sodium/mixin/MixinCloudRenderer.java @@ -1,6 +1,7 @@ package net.irisshaders.iris.compat.sodium.mixin; -import com.llamalad7.mixinextras.sugar.Local; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.mojang.blaze3d.vertex.VertexFormat; import net.caffeinemc.mods.sodium.api.util.NormI8; import net.caffeinemc.mods.sodium.api.vertex.buffer.VertexBufferWriter; @@ -8,9 +9,6 @@ import net.caffeinemc.mods.sodium.client.render.immediate.CloudRenderer; import net.irisshaders.iris.Iris; import net.irisshaders.iris.api.v0.IrisApi; -import net.irisshaders.iris.pipeline.ShaderRenderingPipeline; -import net.irisshaders.iris.pipeline.WorldRenderingPipeline; -import net.irisshaders.iris.pipeline.programs.ShaderKey; import net.irisshaders.iris.vertices.IrisVertexFormats; import net.irisshaders.iris.vertices.sodium.CloudVertex; import org.jetbrains.annotations.Nullable; @@ -20,7 +18,6 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyArg; -import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @@ -41,10 +38,18 @@ public abstract class MixinCloudRenderer { @Shadow(remap = false) @Nullable - private CloudRenderer.@Nullable CloudGeometry cachedGeometry; + private CloudRenderer.@Nullable CloudGeometry builtGeometry; @Unique - private @Nullable CloudRenderer.CloudGeometry cachedGeometryIris; + private static boolean hadShadersOn = false; + + // Bitmasks for each cloud face + private static final int FACE_MASK_NEG_Y = 1 << 0; + private static final int FACE_MASK_POS_Y = 1 << 1; + private static final int FACE_MASK_NEG_X = 1 << 2; + private static final int FACE_MASK_POS_X = 1 << 3; + private static final int FACE_MASK_NEG_Z = 1 << 4; + private static final int FACE_MASK_POS_Z = 1 << 5; @Inject(method = "writeVertex", at = @At("HEAD"), cancellable = true, remap = false) private static void writeIrisVertex(long buffer, float x, float y, float z, int color, CallbackInfoReturnable cir) { @@ -54,27 +59,57 @@ private static void writeIrisVertex(long buffer, float x, float y, float z, int } } - @Inject(method = "emitCellGeometry2D", at = @At("HEAD"), remap = false) - private static void computeNormal2D(VertexBufferWriter writer, int faces, int color, float x, float z, CallbackInfo ci) { + @Inject(method = "emitCellGeometryFlat", at = @At("HEAD"), remap = false) + private static void computeNormal2D(VertexBufferWriter writer, int texel, int x, int z, CallbackInfo ci) { + computedNormal = NORMALS[0]; + } + + @Inject(method = "emitCellGeometryExterior", at = @At(value = "INVOKE", target = "Lnet/caffeinemc/mods/sodium/api/util/ColorABGR;mulRGB(II)I", ordinal = 0), remap = false) + private static void computeNormal3D(VertexBufferWriter writer, int cellFaces, int cellColor, int cellX, int cellZ, CallbackInfo ci) { computedNormal = NORMALS[0]; } - @Inject(method = "emitCellGeometry3D", at = @At(value = "INVOKE", target = "Lnet/caffeinemc/mods/sodium/client/render/immediate/CloudRenderer$CloudFace;ordinal()I"), remap = false) - private static void computeNormal3D(VertexBufferWriter writer, int visibleFaces, int baseColor, float posX, float posZ, boolean interior, CallbackInfo ci, @Local(ordinal = 4) int face) { - computedNormal = NORMALS[face]; + @Inject(method = "emitCellGeometryExterior", at = @At(value = "INVOKE", target = "Lnet/caffeinemc/mods/sodium/api/util/ColorABGR;mulRGB(II)I", ordinal = 1), remap = false) + private static void computeNormal3DUp(VertexBufferWriter writer, int cellFaces, int cellColor, int cellX, int cellZ, CallbackInfo ci) { + computedNormal = NORMALS[1]; + } + + @Inject(method = "emitCellGeometryExterior", at = @At(value = "INVOKE", target = "Lnet/caffeinemc/mods/sodium/client/render/immediate/CloudRenderer;writeVertex(JFFFI)J", ordinal = 8, remap = false), remap = false) + private static void computeNormal3DNegX(VertexBufferWriter writer, int cellFaces, int cellColor, int cellX, int cellZ, CallbackInfo ci) { + computedNormal = NORMALS[2]; + } + + @Inject(method = "emitCellGeometryExterior", at = @At(value = "INVOKE", target = "Lnet/caffeinemc/mods/sodium/client/render/immediate/CloudRenderer;writeVertex(JFFFI)J", ordinal = 12, remap = false)) + private static void computeNormal3DPosX(VertexBufferWriter writer, int cellFaces, int cellColor, int cellX, int cellZ, CallbackInfo ci) { + computedNormal = NORMALS[3]; } - @ModifyArg(remap = false, method = "emitCellGeometry3D", at = @At(value = "INVOKE", target = "Lorg/lwjgl/system/MemoryStack;nmalloc(I)J")) + @Inject(method = "emitCellGeometryExterior", at = @At(value = "INVOKE", target = "Lnet/caffeinemc/mods/sodium/client/render/immediate/CloudRenderer;writeVertex(JFFFI)J", ordinal = 16, remap = false)) + private static void computeNormal3DNegZ(VertexBufferWriter writer, int cellFaces, int cellColor, int cellX, int cellZ, CallbackInfo ci) { + computedNormal = NORMALS[4]; + } + + @Inject(method = "emitCellGeometryExterior", at = @At(value = "INVOKE", target = "Lnet/caffeinemc/mods/sodium/client/render/immediate/CloudRenderer;writeVertex(JFFFI)J", ordinal = 20, remap = false)) + private static void computeNormal3DPosZ(VertexBufferWriter writer, int cellFaces, int cellColor, int cellX, int cellZ, CallbackInfo ci) { + computedNormal = NORMALS[5]; + } + + @ModifyArg(remap = false, method = "emitCellGeometryExterior", at = @At(value = "INVOKE", target = "Lorg/lwjgl/system/MemoryStack;nmalloc(I)J")) private static int allocateNewSize(int size) { return IrisApi.getInstance().isShaderPackInUse() ? 480 : size; } + @ModifyArg(remap = false, method = "emitCellGeometryInterior", at = @At(value = "INVOKE", target = "Lorg/lwjgl/system/MemoryStack;nmalloc(I)J")) + private static int allocateNewSizeInt(int size) { + return IrisApi.getInstance().isShaderPackInUse() ? 480 : size; + } + @ModifyArg(method = "rebuildGeometry", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/Tesselator;begin(Lcom/mojang/blaze3d/vertex/VertexFormat$Mode;Lcom/mojang/blaze3d/vertex/VertexFormat;)Lcom/mojang/blaze3d/vertex/BufferBuilder;"), index = 1) private static VertexFormat rebuild(VertexFormat p_350837_) { return IrisApi.getInstance().isShaderPackInUse() ? IrisVertexFormats.CLOUDS : p_350837_; } - @ModifyArg(method = "emitCellGeometry3D", at = @At(value = "INVOKE", target = "Lnet/caffeinemc/mods/sodium/api/vertex/buffer/VertexBufferWriter;push(Lorg/lwjgl/system/MemoryStack;JILcom/mojang/blaze3d/vertex/VertexFormat;)V"), index = 3) + @ModifyArg(method = "emitCellGeometryExterior", at = @At(value = "INVOKE", target = "Lnet/caffeinemc/mods/sodium/api/vertex/buffer/VertexBufferWriter;push(Lorg/lwjgl/system/MemoryStack;JILcom/mojang/blaze3d/vertex/VertexFormat;)V"), index = 3) private static VertexFormat modifyArgIris(VertexFormat vertexFormatDescription) { if (IrisApi.getInstance().isShaderPackInUse()) { return IrisVertexFormats.CLOUDS; @@ -83,12 +118,21 @@ private static VertexFormat modifyArgIris(VertexFormat vertexFormatDescription) } } - @ModifyArg(remap = false, method = "emitCellGeometry2D", at = @At(value = "INVOKE", target = "Lorg/lwjgl/system/MemoryStack;nmalloc(I)J")) + @ModifyArg(method = "emitCellGeometryInterior", at = @At(value = "INVOKE", target = "Lnet/caffeinemc/mods/sodium/api/vertex/buffer/VertexBufferWriter;push(Lorg/lwjgl/system/MemoryStack;JILcom/mojang/blaze3d/vertex/VertexFormat;)V"), index = 3) + private static VertexFormat modifyArgIrisInt(VertexFormat vertexFormatDescription) { + if (IrisApi.getInstance().isShaderPackInUse()) { + return IrisVertexFormats.CLOUDS; + } else { + return ColorVertex.FORMAT; + } + } + + @ModifyArg(remap = false, method = "emitCellGeometryFlat", at = @At(value = "INVOKE", target = "Lorg/lwjgl/system/MemoryStack;nmalloc(I)J")) private static int allocateNewSize2D(int size) { return IrisApi.getInstance().isShaderPackInUse() ? 80 : size; } - @ModifyArg(method = "emitCellGeometry2D", at = @At(value = "INVOKE", target = "Lnet/caffeinemc/mods/sodium/api/vertex/buffer/VertexBufferWriter;push(Lorg/lwjgl/system/MemoryStack;JILcom/mojang/blaze3d/vertex/VertexFormat;)V"), index = 3) + @ModifyArg(method = "emitCellGeometryFlat", at = @At(value = "INVOKE", target = "Lnet/caffeinemc/mods/sodium/api/vertex/buffer/VertexBufferWriter;push(Lorg/lwjgl/system/MemoryStack;JILcom/mojang/blaze3d/vertex/VertexFormat;)V"), index = 3) private static VertexFormat modifyArgIris2D(VertexFormat vertexFormatDescription) { if (IrisApi.getInstance().isShaderPackInUse()) { return IrisVertexFormats.CLOUDS; @@ -97,21 +141,15 @@ private static VertexFormat modifyArgIris2D(VertexFormat vertexFormatDescription } } - @Redirect(method = "render", at = @At(remap = false, value = "FIELD", target = "Lnet/caffeinemc/mods/sodium/client/render/immediate/CloudRenderer;cachedGeometry:Lnet/caffeinemc/mods/sodium/client/render/immediate/CloudRenderer$CloudGeometry;", ordinal = 0)) - private CloudRenderer.@Nullable CloudGeometry changeGeometry(CloudRenderer instance) { - if (IrisApi.getInstance().isShaderPackInUse()) { - return cachedGeometryIris; - } else { - return cachedGeometry; - } + @WrapOperation(method = "render", at = @At(remap = false, value = "INVOKE", target = "Ljava/util/Objects;equals(Ljava/lang/Object;Ljava/lang/Object;)Z")) + private boolean changeGeometry(Object a, Object b, Operation original) { + return hadShadersOn == Iris.isPackInUseQuick() && original.call(a, b); } - @Redirect(method = "render", at = @At(remap = false, value = "FIELD", target = "Lnet/caffeinemc/mods/sodium/client/render/immediate/CloudRenderer;cachedGeometry:Lnet/caffeinemc/mods/sodium/client/render/immediate/CloudRenderer$CloudGeometry;", ordinal = 1)) - private void changeGeometry2(CloudRenderer instance, CloudRenderer.CloudGeometry value) { - if (IrisApi.getInstance().isShaderPackInUse()) { - cachedGeometryIris = value; - } else { - cachedGeometry = value; - } + @Inject(method = "rebuildGeometry", at = @At(remap = false, value = "HEAD")) + private static void changeGeometry2(CallbackInfoReturnable cir) { + hadShadersOn = IrisApi.getInstance().isShaderPackInUse(); } + + // TODO interiors } diff --git a/common/src/main/java/net/irisshaders/iris/mixin/MixinShaderManager_Overrides.java b/common/src/main/java/net/irisshaders/iris/mixin/MixinShaderManager_Overrides.java index 841da3b918..e10fea283b 100644 --- a/common/src/main/java/net/irisshaders/iris/mixin/MixinShaderManager_Overrides.java +++ b/common/src/main/java/net/irisshaders/iris/mixin/MixinShaderManager_Overrides.java @@ -4,6 +4,7 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap; import net.caffeinemc.mods.sodium.client.render.immediate.CloudRenderer; import net.irisshaders.iris.Iris; +import net.irisshaders.iris.compat.sodium.mixin.CloudRendererAccessor; import net.irisshaders.iris.pathways.HandRenderer; import net.irisshaders.iris.pipeline.IrisRenderingPipeline; import net.irisshaders.iris.pipeline.WorldRenderingPhase; @@ -91,7 +92,7 @@ public abstract class MixinShaderManager_Overrides { coreShaderMap.put(CoreShaders.RENDERTYPE_WATER_MASK, p -> ShaderKey.ENTITIES_SOLID); coreShaderMap.put(CoreShaders.RENDERTYPE_CLOUDS, p -> ShaderKey.CLOUDS); coreShaderMap.put(CoreShaders.RENDERTYPE_CRUMBLING, p -> ShaderKey.CRUMBLING); - coreShaderMap.put(CloudRenderer.CLOUDS, p -> ShaderKey.CLOUDS_SODIUM); + coreShaderMap.put(CloudRendererAccessor.getCLOUDS_SHADER(), p -> ShaderKey.CLOUDS_SODIUM); coreShaderMap.put(CoreShaders.RENDERTYPE_TRANSLUCENT_MOVING_BLOCK, p -> ShaderKey.MOVING_BLOCK); coreShaderMapShadow.put(CoreShaders.POSITION, p -> ShaderKey.SHADOW_BASIC); @@ -140,7 +141,7 @@ public abstract class MixinShaderManager_Overrides { coreShaderMapShadow.put(CoreShaders.RENDERTYPE_WATER_MASK, p -> ShaderKey.SHADOW_ENTITIES_CUTOUT); coreShaderMapShadow.put(CoreShaders.RENDERTYPE_CLOUDS, p -> ShaderKey.SHADOW_CLOUDS); coreShaderMapShadow.put(CoreShaders.RENDERTYPE_CRUMBLING, p -> ShaderKey.SHADOW_BASIC); - coreShaderMapShadow.put(CloudRenderer.CLOUDS, p -> ShaderKey.SHADOW_CLOUDS); + coreShaderMapShadow.put(CloudRendererAccessor.getCLOUDS_SHADER(), p -> ShaderKey.SHADOW_CLOUDS); coreShaderMapShadow.put(CoreShaders.RENDERTYPE_TRANSLUCENT_MOVING_BLOCK, p -> ShaderKey.SHADOW_TERRAIN_CUTOUT); // Check that all shaders are accounted for diff --git a/common/src/main/resources/mixins.iris.compat.sodium.json b/common/src/main/resources/mixins.iris.compat.sodium.json index 6e604a1ad2..85acabcdba 100644 --- a/common/src/main/resources/mixins.iris.compat.sodium.json +++ b/common/src/main/resources/mixins.iris.compat.sodium.json @@ -6,6 +6,7 @@ "plugin": "net.irisshaders.iris.mixin.IrisMixinPlugin", "compatibilityLevel": "JAVA_8", "client": [ + "CloudRendererAccessor", "MixinBlockRenderer", "MixinChunkBuildBuffers", "MixinChunkMeshBufferBuilder", From 5b451897960aa98c4f032b847c0dd62c6d7c0d3e Mon Sep 17 00:00:00 2001 From: douira Date: Thu, 14 Nov 2024 21:52:15 +0100 Subject: [PATCH 3/9] use async culling to render shadows, WIP many types of shadow frustum are stubbed and will be broken, works with Comp as far as I can tell --- .../sodium/mixin/MixinRenderRegion.java | 47 ++++ .../MixinRenderSectionManagerShadow.java | 170 ++++++++++----- .../mixin/MixinSodiumWorldRenderer.java | 34 ++- .../mixinterface/ShadowRenderRegion.java | 7 + .../iris/mixin/MixinRenderSection.java | 31 --- .../iris/shadows/ShadowRenderer.java | 3 +- .../iris/shadows/ShadowSectionTree.java | 200 ++++++++++++++++++ .../frustum/CullEverythingFrustum.java | 6 + .../AdvancedShadowCullingFrustum.java | 30 +-- .../ReversedAdvancedShadowCullingFrustum.java | 30 ++- .../frustum/fallback/BoxCullingFrustum.java | 6 + .../frustum/fallback/NonCullingFrustum.java | 5 + .../resources/mixins.iris.compat.sodium.json | 3 +- common/src/main/resources/mixins.iris.json | 1 - 14 files changed, 427 insertions(+), 146 deletions(-) create mode 100644 common/src/main/java/net/irisshaders/iris/compat/sodium/mixin/MixinRenderRegion.java create mode 100644 common/src/main/java/net/irisshaders/iris/compat/sodium/mixinterface/ShadowRenderRegion.java delete mode 100644 common/src/main/java/net/irisshaders/iris/mixin/MixinRenderSection.java create mode 100644 common/src/main/java/net/irisshaders/iris/shadows/ShadowSectionTree.java diff --git a/common/src/main/java/net/irisshaders/iris/compat/sodium/mixin/MixinRenderRegion.java b/common/src/main/java/net/irisshaders/iris/compat/sodium/mixin/MixinRenderRegion.java new file mode 100644 index 0000000000..2140c80b69 --- /dev/null +++ b/common/src/main/java/net/irisshaders/iris/compat/sodium/mixin/MixinRenderRegion.java @@ -0,0 +1,47 @@ +package net.irisshaders.iris.compat.sodium.mixin; + +import net.caffeinemc.mods.sodium.client.render.chunk.lists.ChunkRenderList; +import net.caffeinemc.mods.sodium.client.render.chunk.region.RenderRegion; +import net.irisshaders.iris.compat.sodium.mixinterface.ShadowRenderRegion; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Mutable; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; + +@Mixin(RenderRegion.class) +public class MixinRenderRegion implements ShadowRenderRegion { + @Final + @Shadow + @Mutable + private ChunkRenderList renderList; + + @Unique + ChunkRenderList regularRenderList; + + @Unique + ChunkRenderList shadowRenderList; + + @Unique + @Override + public void swapToShadowRenderList() { + this.regularRenderList = this.renderList; + this.renderList = this.shadowRenderList; + this.ensureRenderList(); + } + + @Unique + @Override + public void swapToRegularRenderList() { + this.shadowRenderList = this.renderList; + this.renderList = this.regularRenderList; + this.ensureRenderList(); + } + + @Unique + private void ensureRenderList() { + if (this.renderList == null) { + this.renderList = new ChunkRenderList((RenderRegion) (Object) this); + } + } +} diff --git a/common/src/main/java/net/irisshaders/iris/compat/sodium/mixin/MixinRenderSectionManagerShadow.java b/common/src/main/java/net/irisshaders/iris/compat/sodium/mixin/MixinRenderSectionManagerShadow.java index 64abada476..7863ed77ca 100644 --- a/common/src/main/java/net/irisshaders/iris/compat/sodium/mixin/MixinRenderSectionManagerShadow.java +++ b/common/src/main/java/net/irisshaders/iris/compat/sodium/mixin/MixinRenderSectionManagerShadow.java @@ -1,16 +1,21 @@ package net.irisshaders.iris.compat.sodium.mixin; -import net.caffeinemc.mods.sodium.client.gl.device.CommandList; -import net.caffeinemc.mods.sodium.client.render.chunk.ChunkUpdateType; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.caffeinemc.mods.sodium.client.render.chunk.RenderSection; +import net.caffeinemc.mods.sodium.client.render.chunk.RenderSectionFlags; import net.caffeinemc.mods.sodium.client.render.chunk.RenderSectionManager; +import net.caffeinemc.mods.sodium.client.render.chunk.data.BuiltSectionInfo; import net.caffeinemc.mods.sodium.client.render.chunk.lists.SortedRenderLists; +import net.caffeinemc.mods.sodium.client.render.chunk.lists.VisibleChunkCollectorAsync; +import net.caffeinemc.mods.sodium.client.render.chunk.region.RenderRegionManager; import net.caffeinemc.mods.sodium.client.render.viewport.Viewport; +import net.irisshaders.iris.compat.sodium.mixinterface.ShadowRenderRegion; import net.irisshaders.iris.shadows.ShadowRenderingState; +import net.irisshaders.iris.shadows.ShadowSectionTree; import net.minecraft.client.Camera; -import net.minecraft.client.multiplayer.ClientLevel; import org.jetbrains.annotations.NotNull; -import org.objectweb.asm.Opcodes; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; @@ -18,54 +23,117 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.util.ArrayDeque; -import java.util.EnumMap; -import java.util.Map; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(RenderSectionManager.class) -public class MixinRenderSectionManagerShadow { +public abstract class MixinRenderSectionManagerShadow { @Shadow(remap = false) private @NotNull SortedRenderLists renderLists; + @Shadow(remap = false) - private @NotNull Map> taskLists; + private boolean needsRenderListUpdate; + @Shadow - private int lastUpdatedFrame; + @Final + private RenderRegionManager regions; + @Shadow + private int frame; + @Unique private @NotNull SortedRenderLists shadowRenderLists = SortedRenderLists.empty(); + @Unique - private @NotNull Map> shadowTaskLists = new EnumMap<>(ChunkUpdateType.class); - private int lastUpdatedFrameShadow; - - @Inject(method = "", at = @At("TAIL")) - private void create(ClientLevel level, int renderDistance, CommandList commandList, CallbackInfo ci) { - for (int var6 = 0; var6 < ChunkUpdateType.values().length; ++var6) { - ChunkUpdateType type = ChunkUpdateType.values()[var6]; - shadowTaskLists.put(type, new ArrayDeque<>()); + private boolean shadowNeedsRenderListUpdate; + + @Unique + private ShadowSectionTree shadowSectionTree; + + @Unique + private boolean renderListStateIsShadow = false; + + @WrapOperation(method = "notifyChangedCamera", at = @At(value = "FIELD", target = "Lnet/caffeinemc/mods/sodium/client/render/chunk/RenderSectionManager;cameraChanged:Z")) + private void notifyChangedCamera(RenderSectionManager instance, boolean value, Operation original) { + if (!ShadowRenderingState.areShadowsCurrentlyBeingRendered()) { + original.call(instance, value); + return; } + + this.shadowNeedsRenderListUpdate = true; } - @Redirect(remap = false, method = "createTerrainRenderList", at = @At(value = "FIELD", target = "Lnet/caffeinemc/mods/sodium/client/render/chunk/RenderSectionManager;renderLists:Lnet/caffeinemc/mods/sodium/client/render/chunk/lists/SortedRenderLists;")) - private void useShadowRenderList(RenderSectionManager instance, SortedRenderLists value) { - if (ShadowRenderingState.areShadowsCurrentlyBeingRendered()) { - shadowRenderLists = value; - } else { - renderLists = value; + @Inject(method = "updateRenderLists", at = @At(target = "Lnet/caffeinemc/mods/sodium/client/render/chunk/occlusion/AsyncCameraTimingControl;getShouldRenderSync(Lnet/minecraft/client/Camera;)Z", value = "INVOKE")) + private void updateRenderLists(Camera camera, Viewport viewport, boolean spectator, boolean updateImmediately, CallbackInfo ci) { + this.shadowNeedsRenderListUpdate |= this.needsRenderListUpdate; + } + + @Shadow + protected abstract float getRenderDistance(); + + @Shadow + public abstract int getVisibleChunkCount(); + + @Shadow + public abstract int getTotalSections(); + + @Inject(method = "updateRenderLists", at = @At("HEAD"), cancellable = true) + private void updateShadowRenderLists(Camera camera, Viewport viewport, boolean spectator, boolean updateImmediately, CallbackInfo ci) { + this.ensureShadowSectionTree(); + + if (!ShadowRenderingState.areShadowsCurrentlyBeingRendered()) { + if (this.renderListStateIsShadow) { + for (var region : this.regions.getLoadedRegions()) { + ((ShadowRenderRegion) region).swapToRegularRenderList(); + } + this.renderListStateIsShadow = false; + } + return; } + + if (this.shadowNeedsRenderListUpdate) { + if (!this.renderListStateIsShadow) { + for (var region : this.regions.getLoadedRegions()) { + ((ShadowRenderRegion) region).swapToShadowRenderList(); + } + this.renderListStateIsShadow = true; + } + + var visibleCollector = new VisibleChunkCollectorAsync(this.regions, -this.frame); + this.shadowSectionTree.prepareTreesForTraversal(); + this.shadowSectionTree.traverseVisible(visibleCollector, viewport); + this.shadowRenderLists = visibleCollector.createRenderLists(); + } + + this.shadowNeedsRenderListUpdate = false; + ci.cancel(); } - @Redirect(remap = false, method = "createTerrainRenderList", at = @At(value = "FIELD", target = "Lnet/caffeinemc/mods/sodium/client/render/chunk/RenderSectionManager;taskLists:Ljava/util/Map;")) - private void useShadowTaskrList(RenderSectionManager instance, @NotNull Map> value) { - if (ShadowRenderingState.areShadowsCurrentlyBeingRendered()) { - shadowTaskLists = value; + @Unique + private void ensureShadowSectionTree() { + if (this.shadowSectionTree == null) { + this.shadowSectionTree = new ShadowSectionTree(this.getRenderDistance()); + } + } + + @Inject(method = "updateSectionInfo", at = @At("HEAD")) + private void updateSectionInfo(RenderSection render, BuiltSectionInfo info, CallbackInfo ci) { + this.ensureShadowSectionTree(); + + var x = render.getChunkX(); + var y = render.getChunkY(); + var z = render.getChunkZ(); + + if (info == null || (info.flags & RenderSectionFlags.MASK_NEEDS_RENDER) == 0) { + this.shadowSectionTree.removeSection(x, y, z); } else { - taskLists = value; + this.shadowSectionTree.addSection(x, y, z); } } - @Inject(method = "update", at = @At(value = "INVOKE", target = "Lnet/caffeinemc/mods/sodium/client/render/chunk/RenderSectionManager;createTerrainRenderList(Lnet/minecraft/client/Camera;Lnet/caffeinemc/mods/sodium/client/render/viewport/Viewport;IZ)V", shift = At.Shift.AFTER), cancellable = true) - private void cancelIfShadow(Camera camera, Viewport viewport, boolean spectator, CallbackInfo ci) { - if (ShadowRenderingState.areShadowsCurrentlyBeingRendered()) ci.cancel(); + @Inject(method = "onSectionRemoved", at = @At("HEAD")) + private void onSectionRemoved(int x, int y, int z, CallbackInfo ci) { + this.ensureShadowSectionTree(); + + this.shadowSectionTree.removeSection(x, y, z); } @Redirect(method = { @@ -73,33 +141,19 @@ private void cancelIfShadow(Camera camera, Viewport viewport, boolean spectator, "getVisibleChunkCount", "renderLayer" }, at = @At(value = "FIELD", target = "Lnet/caffeinemc/mods/sodium/client/render/chunk/RenderSectionManager;renderLists:Lnet/caffeinemc/mods/sodium/client/render/chunk/lists/SortedRenderLists;"), remap = false) - private SortedRenderLists useShadowRenderList2(RenderSectionManager instance) { - return ShadowRenderingState.areShadowsCurrentlyBeingRendered() ? shadowRenderLists : renderLists; - } - - @Inject(method = "updateChunks", at = @At("HEAD"), cancellable = true, remap = false) - private void doNotUpdateDuringShadow(boolean updateImmediately, CallbackInfo ci) { - if (ShadowRenderingState.areShadowsCurrentlyBeingRendered()) ci.cancel(); + private SortedRenderLists useShadowRenderList(RenderSectionManager instance) { + return ShadowRenderingState.areShadowsCurrentlyBeingRendered() ? this.shadowRenderLists : this.renderLists; } - @Inject(method = "uploadChunks", at = @At("HEAD"), cancellable = true, remap = false) - private void doNotUploadDuringShadow(CallbackInfo ci) { - if (ShadowRenderingState.areShadowsCurrentlyBeingRendered()) ci.cancel(); - } - @Redirect(method = { - "resetRenderLists", - "submitSectionTasks(Lnet/caffeinemc/mods/sodium/client/render/chunk/compile/executor/ChunkJobCollector;Lnet/caffeinemc/mods/sodium/client/render/chunk/compile/executor/ChunkJobCollector;Lnet/caffeinemc/mods/sodium/client/render/chunk/compile/executor/ChunkJobCollector;)V" - }, at = @At(value = "FIELD", target = "Lnet/caffeinemc/mods/sodium/client/render/chunk/RenderSectionManager;taskLists:Ljava/util/Map;"), remap = false) - private @NotNull Map> useShadowTaskList3(RenderSectionManager instance) { - return ShadowRenderingState.areShadowsCurrentlyBeingRendered() ? shadowTaskLists : taskLists; - } - - @Redirect(method = { - "resetRenderLists" - }, at = @At(value = "FIELD", target = "Lnet/caffeinemc/mods/sodium/client/render/chunk/RenderSectionManager;renderLists:Lnet/caffeinemc/mods/sodium/client/render/chunk/lists/SortedRenderLists;"), remap = false) - private void useShadowRenderList3(RenderSectionManager instance, SortedRenderLists value) { - if (ShadowRenderingState.areShadowsCurrentlyBeingRendered()) shadowRenderLists = value; - else renderLists = value; + @Inject(method = "getChunksDebugString", at = @At("HEAD"), cancellable = true) + private void getShadowChunksDebugString(CallbackInfoReturnable cir) { + if (ShadowRenderingState.areShadowsCurrentlyBeingRendered()) { + var renderLists = this.renderLists; + this.renderLists = this.shadowRenderLists; + cir.setReturnValue(String.format("C: %d/%d", this.getVisibleChunkCount(), this.getTotalSections())); + this.renderLists = renderLists; + cir.cancel(); + } } } diff --git a/common/src/main/java/net/irisshaders/iris/compat/sodium/mixin/MixinSodiumWorldRenderer.java b/common/src/main/java/net/irisshaders/iris/compat/sodium/mixin/MixinSodiumWorldRenderer.java index 6cf49595c2..24dc710116 100644 --- a/common/src/main/java/net/irisshaders/iris/compat/sodium/mixin/MixinSodiumWorldRenderer.java +++ b/common/src/main/java/net/irisshaders/iris/compat/sodium/mixin/MixinSodiumWorldRenderer.java @@ -5,9 +5,11 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import net.caffeinemc.mods.sodium.client.render.SodiumWorldRenderer; import net.caffeinemc.mods.sodium.client.render.chunk.RenderSectionManager; +import net.caffeinemc.mods.sodium.client.render.viewport.Viewport; import net.irisshaders.iris.mixin.LevelRendererAccessor; import net.irisshaders.iris.shadows.ShadowRenderingState; import net.irisshaders.iris.uniforms.CapturedRenderingState; +import net.minecraft.client.Camera; import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.renderer.MultiBufferSource; @@ -16,16 +18,18 @@ import net.minecraft.server.level.BlockDestructionProgress; import net.minecraft.world.level.block.entity.BlockEntity; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.util.SortedSet; @Mixin(SodiumWorldRenderer.class) public class MixinSodiumWorldRenderer { + @Shadow + private RenderSectionManager renderSectionManager; @Unique private static boolean renderLightsOnly = false; @Unique @@ -58,32 +62,18 @@ private static void checkRenderShadow(PoseStack matrices, RenderBuffers bufferBu } } - @Redirect(method = "setupTerrain", remap = false, - at = @At(value = "INVOKE", - target = "Lnet/caffeinemc/mods/sodium/client/render/chunk/RenderSectionManager;needsUpdate()Z", ordinal = 0, - remap = false)) - private boolean iris$forceChunkGraphRebuildInShadowPass(RenderSectionManager instance) { + @Inject(method = "setupTerrain", at = @At("HEAD"), cancellable = true) + private void setupShadowTerrain(Camera camera, Viewport viewport, boolean spectator, boolean updateChunksImmediately, CallbackInfo ci) { if (ShadowRenderingState.areShadowsCurrentlyBeingRendered()) { float sunAngle = Minecraft.getInstance().level.getSunAngle(CapturedRenderingState.INSTANCE.getTickDelta()); - if (lastSunAngle != sunAngle) { - lastSunAngle = sunAngle; - return true; + if (this.lastSunAngle != sunAngle) { + this.lastSunAngle = sunAngle; + this.renderSectionManager.notifyChangedCamera(); } - } - return instance.needsUpdate(); - } + this.renderSectionManager.updateRenderLists(camera, viewport, spectator, updateChunksImmediately); - @Redirect(method = "setupTerrain", remap = false, - at = @At(value = "INVOKE", - target = "Lnet/caffeinemc/mods/sodium/client/render/chunk/RenderSectionManager;needsUpdate()Z", ordinal = 1, - remap = false)) - private boolean iris$forceEndGraphRebuild(RenderSectionManager instance) { - if (ShadowRenderingState.areShadowsCurrentlyBeingRendered()) { - // TODO: Detect when the sun/moon isn't moving - return false; - } else { - return instance.needsUpdate(); + ci.cancel(); } } } diff --git a/common/src/main/java/net/irisshaders/iris/compat/sodium/mixinterface/ShadowRenderRegion.java b/common/src/main/java/net/irisshaders/iris/compat/sodium/mixinterface/ShadowRenderRegion.java new file mode 100644 index 0000000000..8ea0489cbd --- /dev/null +++ b/common/src/main/java/net/irisshaders/iris/compat/sodium/mixinterface/ShadowRenderRegion.java @@ -0,0 +1,7 @@ +package net.irisshaders.iris.compat.sodium.mixinterface; + +public interface ShadowRenderRegion { + void swapToShadowRenderList(); + + void swapToRegularRenderList(); +} diff --git a/common/src/main/java/net/irisshaders/iris/mixin/MixinRenderSection.java b/common/src/main/java/net/irisshaders/iris/mixin/MixinRenderSection.java deleted file mode 100644 index 9207fc91f1..0000000000 --- a/common/src/main/java/net/irisshaders/iris/mixin/MixinRenderSection.java +++ /dev/null @@ -1,31 +0,0 @@ -package net.irisshaders.iris.mixin; - -import net.caffeinemc.mods.sodium.client.render.chunk.RenderSection; -import net.irisshaders.iris.shadows.ShadowRenderingState; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -@Mixin(remap = false, value = RenderSection.class) -public class MixinRenderSection { - @Unique - private int lastVisibleFrameShadow; - - @Inject(method = "setLastVisibleFrame", at = @At("HEAD"), cancellable = true) - private void setLastVisibleFrameShadow(int i, CallbackInfo ci) { - if (ShadowRenderingState.areShadowsCurrentlyBeingRendered()) { - ci.cancel(); - lastVisibleFrameShadow = i; - } - } - - @Inject(method = "getLastVisibleFrame", at = @At("HEAD"), cancellable = true) - private void getLastVisibleFrameShadow(CallbackInfoReturnable cir) { - if (ShadowRenderingState.areShadowsCurrentlyBeingRendered()) { - cir.setReturnValue(lastVisibleFrameShadow); - } - } -} diff --git a/common/src/main/java/net/irisshaders/iris/shadows/ShadowRenderer.java b/common/src/main/java/net/irisshaders/iris/shadows/ShadowRenderer.java index 691cf1b3e9..653e741e1a 100644 --- a/common/src/main/java/net/irisshaders/iris/shadows/ShadowRenderer.java +++ b/common/src/main/java/net/irisshaders/iris/shadows/ShadowRenderer.java @@ -4,6 +4,7 @@ import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import net.caffeinemc.mods.sodium.client.render.SodiumWorldRenderer; import net.irisshaders.batchedentityrendering.impl.BatchingDebugMessageHelper; import net.irisshaders.batchedentityrendering.impl.DrawCallTrackingRenderBuffers; import net.irisshaders.batchedentityrendering.impl.FullyBufferedMultiBufferSource; @@ -560,7 +561,7 @@ public void renderShadows(LevelRendererAccessor levelRenderer, Camera playerCame IrisRenderSystem.restorePlayerProjection(); - debugStringTerrain = ((LevelRenderer) levelRenderer).getSectionStatistics(); + debugStringTerrain = SodiumWorldRenderer.instance().getChunksDebugString(); profiler.popPush("generate mipmaps"); diff --git a/common/src/main/java/net/irisshaders/iris/shadows/ShadowSectionTree.java b/common/src/main/java/net/irisshaders/iris/shadows/ShadowSectionTree.java new file mode 100644 index 0000000000..3e576b68d2 --- /dev/null +++ b/common/src/main/java/net/irisshaders/iris/shadows/ShadowSectionTree.java @@ -0,0 +1,200 @@ +package net.irisshaders.iris.shadows; + +import it.unimi.dsi.fastutil.longs.Long2ReferenceLinkedOpenHashMap; +import it.unimi.dsi.fastutil.longs.Long2ReferenceSortedMap; +import it.unimi.dsi.fastutil.objects.ReferenceArrayList; +import net.caffeinemc.mods.sodium.client.render.chunk.occlusion.SectionTree; +import net.caffeinemc.mods.sodium.client.render.chunk.tree.BaseMultiForest; +import net.caffeinemc.mods.sodium.client.render.chunk.tree.TraversableForest; +import net.caffeinemc.mods.sodium.client.render.chunk.tree.TraversableTree; +import net.caffeinemc.mods.sodium.client.render.chunk.tree.Tree; +import net.caffeinemc.mods.sodium.client.render.viewport.Viewport; +import net.minecraft.core.SectionPos; + +import java.util.Comparator; + +public class ShadowSectionTree { + private final RemovableMultiForest tree; + + public ShadowSectionTree(float buildDistance) { + this.tree = new RemovableMultiForest(buildDistance); + } + + private interface RemovableForest extends TraversableForest { + void remove(int x, int y, int z); + } + + private static class RemovableMultiForest { + private final Long2ReferenceSortedMap trees; + private final ReferenceArrayList treeSortList = new ReferenceArrayList<>(); + private RemovableTree lastTree; + + public RemovableMultiForest(float buildDistance) { + var forestDim = BaseMultiForest.forestDimFromBuildDistance(buildDistance) + 1; + this.trees = new Long2ReferenceLinkedOpenHashMap<>(forestDim * forestDim * forestDim); + } + + public void calculateReducedAndClean() { + for (var tree : this.trees.values()) { + tree.calculateReduced(); + if (tree.isEmpty()) { + this.trees.remove(tree.getTreeKey()); + if (this.lastTree == tree) { + this.lastTree = null; + } + } + } + } + + public void traverse(SectionTree.VisibleSectionVisitor visitor, Viewport viewport) { + var transform = viewport.getTransform(); + var cameraSectionX = transform.intX >> 4; + var cameraSectionY = transform.intY >> 4; + var cameraSectionZ = transform.intZ >> 4; + + // sort the trees by distance from the camera by sorting a packed index array. + this.treeSortList.clear(); + this.treeSortList.ensureCapacity(this.trees.size()); + this.treeSortList.addAll(this.trees.values()); + for (var tree : this.treeSortList) { + tree.calculateSortKey(cameraSectionX, cameraSectionY, cameraSectionZ); + } + + this.treeSortList.unstableSort(Comparator.comparingInt(RemovableTree::getSortKey)); + + // traverse in sorted front-to-back order for correct render order + for (var tree : this.treeSortList) { + // disable distance test in traversal because we don't use it here + tree.traverse(visitor, viewport, 0, 0); + } + } + + public void add(int x, int y, int z) { + if (this.lastTree != null && this.lastTree.add(x, y, z)) { + return; + } + + // get the tree coordinate by dividing by 64 + var treeX = x >> 6; + var treeY = y >> 6; + var treeZ = z >> 6; + + var treeKey = SectionPos.asLong(treeX, treeY, treeZ); + var tree = this.trees.get(treeKey); + + if (tree == null) { + var treeOffsetX = treeX << 6; + var treeOffsetY = treeY << 6; + var treeOffsetZ = treeZ << 6; + tree = new RemovableTree(treeOffsetX, treeOffsetY, treeOffsetZ); + this.trees.put(treeKey, tree); + } + + tree.add(x, y, z); + this.lastTree = tree; + } + + public void remove(int x, int y, int z) { + if (this.lastTree != null && this.lastTree.remove(x, y, z)) { + return; + } + + // get the tree coordinate by dividing by 64 + var treeX = x >> 6; + var treeY = y >> 6; + var treeZ = z >> 6; + + var treeKey = SectionPos.asLong(treeX, treeY, treeZ); + var tree = this.trees.get(treeKey); + + if (tree == null) { + return; + } + + tree.remove(x, y, z); + + this.lastTree = tree; + } + } + + private static class RemovableTree extends TraversableTree { + private boolean reducedIsValid = true; + private int sortKey; + + public RemovableTree(int offsetX, int offsetY, int offsetZ) { + super(offsetX, offsetY, offsetZ); + } + + public boolean remove(int x, int y, int z) { + x -= this.offsetX; + y -= this.offsetY; + z -= this.offsetZ; + if (Tree.isOutOfBounds(x, y, z)) { + return false; + } + + var bitIndex = Tree.interleave6x3(x, y, z); + this.tree[bitIndex >> 6] &= ~(1L << (bitIndex & 0b111111)); + + this.reducedIsValid = false; + + return true; + } + + @Override + public void calculateReduced() { + if (!this.reducedIsValid) { + super.calculateReduced(); + } + } + + @Override + public boolean add(int x, int y, int z) { + var result = super.add(x, y, z); + if (result) { + this.reducedIsValid = false; + } + return result; + } + + public boolean isEmpty() { + return this.treeDoubleReduced == 0; + } + + public long getTreeKey() { + return SectionPos.asLong(this.offsetX, this.offsetY, this.offsetZ); + } + + @Override + public int getPresence(int i, int i1, int i2) { + throw new UnsupportedOperationException("Not implemented"); + } + + public void calculateSortKey(int cameraSectionX, int cameraSectionY, int cameraSectionZ) { + var deltaX = Math.abs(this.offsetX + 32 - cameraSectionX); + var deltaY = Math.abs(this.offsetY + 32 - cameraSectionY); + var deltaZ = Math.abs(this.offsetZ + 32 - cameraSectionZ); + this.sortKey = deltaX + deltaY + deltaZ + 1; + } + + public int getSortKey() { + return this.sortKey; + } + } + + public void addSection(int x, int y, int z) { + this.tree.add(x, y, z); + } + + public void removeSection(int x, int y, int z) { + this.tree.remove(x, y, z); + } + + public void traverseVisible(SectionTree.VisibleSectionVisitor visitor, Viewport viewport) { + this.tree.traverse(visitor, viewport); + } + + public void prepareTreesForTraversal() { + this.tree.calculateReducedAndClean(); + } +} diff --git a/common/src/main/java/net/irisshaders/iris/shadows/frustum/CullEverythingFrustum.java b/common/src/main/java/net/irisshaders/iris/shadows/frustum/CullEverythingFrustum.java index ea3f589941..810a76f177 100644 --- a/common/src/main/java/net/irisshaders/iris/shadows/frustum/CullEverythingFrustum.java +++ b/common/src/main/java/net/irisshaders/iris/shadows/frustum/CullEverythingFrustum.java @@ -4,6 +4,7 @@ import net.caffeinemc.mods.sodium.client.render.viewport.ViewportProvider; import net.minecraft.client.renderer.culling.Frustum; import net.minecraft.world.phys.AABB; +import org.joml.FrustumIntersection; import org.joml.Matrix4f; import org.joml.Vector3d; @@ -38,4 +39,9 @@ public void prepare(double d, double e, double f) { public boolean testAab(float v, float v1, float v2, float v3, float v4, float v5) { return false; } + + @Override + public int intersectAab(float v, float v1, float v2, float v3, float v4, float v5) { + return FrustumIntersection.OUTSIDE; + } } diff --git a/common/src/main/java/net/irisshaders/iris/shadows/frustum/advanced/AdvancedShadowCullingFrustum.java b/common/src/main/java/net/irisshaders/iris/shadows/frustum/advanced/AdvancedShadowCullingFrustum.java index d810cd2919..35a5c891c5 100644 --- a/common/src/main/java/net/irisshaders/iris/shadows/frustum/advanced/AdvancedShadowCullingFrustum.java +++ b/common/src/main/java/net/irisshaders/iris/shadows/frustum/advanced/AdvancedShadowCullingFrustum.java @@ -7,6 +7,7 @@ import net.irisshaders.iris.shadows.frustum.BoxCuller; import net.minecraft.client.renderer.culling.Frustum; import net.minecraft.world.phys.AABB; +import org.joml.FrustumIntersection; import org.joml.Matrix4fc; import org.joml.Vector3d; import org.joml.Vector3f; @@ -295,16 +296,7 @@ public boolean isVisible(AABB aabb) { return false; } - return this.isVisible(aabb.minX, aabb.minY, aabb.minZ, aabb.maxX, aabb.maxY, aabb.maxZ) != 0; - } - - // For Sodium - public int fastAabbTest(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) { - if (boxCuller != null && boxCuller.isCulled(minX, minY, minZ, maxX, maxY, maxZ)) { - return 0; - } - - return isVisible(minX, minY, minZ, maxX, maxY, maxZ); + return this.isVisible(aabb.minX, aabb.minY, aabb.minZ, aabb.maxX, aabb.maxY, aabb.maxZ) != FrustumIntersection.OUTSIDE; } // For Immersive Portals @@ -351,7 +343,7 @@ private static float safeFMA(float a, float b, float c) { * @param maxX Maximum X value of the AABB. * @param maxY Maximum Y value of the AABB. * @param maxZ Maximum Z value of the AABB. - * @return 0 if nothing is visible, 1 if everything is visible, 2 if only some corners are visible. + * @return OUTSIDE if nothing is visible, INSIDE if everything is visible, INTERSECT if only some corners are visible. */ protected int checkCornerVisibility(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) { boolean inside = true; @@ -373,7 +365,7 @@ protected int checkCornerVisibility(float minX, float minY, float minZ, float ma Math.fma(plane[1], (plane[1] < 0 ? maxY : minY), Math.fma(plane[2], (plane[2] < 0 ? maxZ : minZ), plane[3]))) >= 0; } else { - return 0; + return FrustumIntersection.OUTSIDE; } } else { if (safeFMA(plane[0], outsideBoundX, safeFMA(plane[1], outsideBoundY, plane[2] * outsideBoundZ)) >= -plane[3]) { @@ -381,12 +373,12 @@ protected int checkCornerVisibility(float minX, float minY, float minZ, float ma safeFMA(plane[1], (plane[1] < 0 ? maxY : minY), safeFMA(plane[2], (plane[2] < 0 ? maxZ : minZ), plane[3]))) >= 0; } else { - return 0; + return FrustumIntersection.OUTSIDE; } } } - return inside ? 1 : 2; + return inside ? FrustumIntersection.INSIDE : FrustumIntersection.INTERSECT; } /** @@ -418,7 +410,15 @@ public boolean checkCornerVisibilityBool(float minX, float minY, float minZ, flo @Override public boolean testAab(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) { - return (boxCuller == null || !boxCuller.isCulledSodium(minX, minY, minZ, maxX, maxY, maxZ)) && this.checkCornerVisibility(minX, minY, minZ, maxX, maxY, maxZ) > 0; + return (boxCuller == null || !boxCuller.isCulledSodium(minX, minY, minZ, maxX, maxY, maxZ)) && this.checkCornerVisibilityBool(minX, minY, minZ, maxX, maxY, maxZ); + } + + @Override + public int intersectAab(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) { + if (boxCuller != null && boxCuller.isCulledSodium(minX, minY, minZ, maxX, maxY, maxZ)) { + return FrustumIntersection.OUTSIDE; + } + return this.checkCornerVisibility(minX, minY, minZ, maxX, maxY, maxZ); } @Override diff --git a/common/src/main/java/net/irisshaders/iris/shadows/frustum/advanced/ReversedAdvancedShadowCullingFrustum.java b/common/src/main/java/net/irisshaders/iris/shadows/frustum/advanced/ReversedAdvancedShadowCullingFrustum.java index 2b4907d362..22d3504489 100644 --- a/common/src/main/java/net/irisshaders/iris/shadows/frustum/advanced/ReversedAdvancedShadowCullingFrustum.java +++ b/common/src/main/java/net/irisshaders/iris/shadows/frustum/advanced/ReversedAdvancedShadowCullingFrustum.java @@ -1,12 +1,13 @@ package net.irisshaders.iris.shadows.frustum.advanced; -import net.caffeinemc.mods.sodium.client.render.viewport.frustum.Frustum; import net.irisshaders.iris.shadows.frustum.BoxCuller; import net.minecraft.world.phys.AABB; +import org.joml.FrustumIntersection; import org.joml.Matrix4fc; import org.joml.Vector3f; -public class ReversedAdvancedShadowCullingFrustum extends AdvancedShadowCullingFrustum implements Frustum { +// TODO: I don't know what this class does and I probably broke it by changing AdvancedShadowCullingFrustum +public class ReversedAdvancedShadowCullingFrustum extends AdvancedShadowCullingFrustum { private final BoxCuller distanceCuller; public ReversedAdvancedShadowCullingFrustum(Matrix4fc modelViewProjection, Matrix4fc shadowProjection, Vector3f shadowLightVectorFromOrigin, BoxCuller voxelCuller, BoxCuller distanceCuller) { @@ -32,20 +33,8 @@ public boolean isVisible(AABB aabb) { return true; } - return this.isVisible(aabb.minX, aabb.minY, aabb.minZ, aabb.maxX, aabb.maxY, aabb.maxZ) != 0; - } - - @Override - public int fastAabbTest(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) { - if (distanceCuller != null && distanceCuller.isCulled(minX, minY, minZ, maxX, maxY, maxZ)) { - return 0; - } - - if (boxCuller != null && !boxCuller.isCulled(minX, minY, minZ, maxX, maxY, maxZ)) { - return 2; - } - - return isVisible(minX, minY, minZ, maxX, maxY, maxZ); + // TODO: ? + return this.isVisible(aabb.minX, aabb.minY, aabb.minZ, aabb.maxX, aabb.maxY, aabb.maxZ) != FrustumIntersection.OUTSIDE; } @Override @@ -58,6 +47,13 @@ public boolean testAab(float minX, float minY, float minZ, float maxX, float max return true; } - return this.checkCornerVisibility(minX, minY, minZ, maxX, maxY, maxZ) > 0; + // TODO: ? + return this.checkCornerVisibility(minX, minY, minZ, maxX, maxY, maxZ) != FrustumIntersection.OUTSIDE; + } + + @Override + public int intersectAab(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) { + // TODO: placeholder + return FrustumIntersection.INSIDE; } } diff --git a/common/src/main/java/net/irisshaders/iris/shadows/frustum/fallback/BoxCullingFrustum.java b/common/src/main/java/net/irisshaders/iris/shadows/frustum/fallback/BoxCullingFrustum.java index dbd2039c0c..15160b6d3a 100644 --- a/common/src/main/java/net/irisshaders/iris/shadows/frustum/fallback/BoxCullingFrustum.java +++ b/common/src/main/java/net/irisshaders/iris/shadows/frustum/fallback/BoxCullingFrustum.java @@ -5,6 +5,7 @@ import net.irisshaders.iris.shadows.frustum.BoxCuller; import net.minecraft.client.renderer.culling.Frustum; import net.minecraft.world.phys.AABB; +import org.joml.FrustumIntersection; import org.joml.Matrix4f; import org.joml.Vector3d; @@ -44,4 +45,9 @@ public boolean isVisible(AABB box) { public boolean testAab(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) { return !boxCuller.isCulledSodium(minX, minY, minZ, maxX, maxY, maxZ); } + + @Override + public int intersectAab(float v, float v1, float v2, float v3, float v4, float v5) { + return this.boxCuller.isCulledSodium(v, v1, v2, v3, v4, v5) ? FrustumIntersection.OUTSIDE : FrustumIntersection.INTERSECT; + } } diff --git a/common/src/main/java/net/irisshaders/iris/shadows/frustum/fallback/NonCullingFrustum.java b/common/src/main/java/net/irisshaders/iris/shadows/frustum/fallback/NonCullingFrustum.java index 991a957f58..fe174866e3 100644 --- a/common/src/main/java/net/irisshaders/iris/shadows/frustum/fallback/NonCullingFrustum.java +++ b/common/src/main/java/net/irisshaders/iris/shadows/frustum/fallback/NonCullingFrustum.java @@ -62,4 +62,9 @@ public void prepare(double d, double e, double f) { public boolean testAab(float v, float v1, float v2, float v3, float v4, float v5) { return true; } + + @Override + public int intersectAab(float v, float v1, float v2, float v3, float v4, float v5) { + return FrustumIntersection.INSIDE; + } } diff --git a/common/src/main/resources/mixins.iris.compat.sodium.json b/common/src/main/resources/mixins.iris.compat.sodium.json index 85acabcdba..c2b29ab1e0 100644 --- a/common/src/main/resources/mixins.iris.compat.sodium.json +++ b/common/src/main/resources/mixins.iris.compat.sodium.json @@ -21,7 +21,8 @@ "MixinSodiumGameOptionPages", "MixinSodiumGameOptions", "MixinSodiumOptionsGUI", - "MixinSodiumWorldRenderer" + "MixinSodiumWorldRenderer", + "MixinRenderRegion" ], "injectors": { "defaultRequire": 1 diff --git a/common/src/main/resources/mixins.iris.json b/common/src/main/resources/mixins.iris.json index 1f9b4fb7d2..82549f1849 100644 --- a/common/src/main/resources/mixins.iris.json +++ b/common/src/main/resources/mixins.iris.json @@ -47,7 +47,6 @@ "MixinParticleEngine", "MixinShaderManager_Overrides", "MixinQuickPlayDev", - "MixinRenderSection", "MixinRenderSystem", "MixinRenderTarget", "MixinScreenEffectRenderer", From 572d708ba8cda054d594139484c3c269c4215212 Mon Sep 17 00:00:00 2001 From: douira Date: Fri, 15 Nov 2024 16:54:59 +0100 Subject: [PATCH 4/9] cleanup comments --- .../java/net/irisshaders/iris/shadows/ShadowRenderer.java | 5 ----- .../frustum/advanced/AdvancedShadowCullingFrustum.java | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/common/src/main/java/net/irisshaders/iris/shadows/ShadowRenderer.java b/common/src/main/java/net/irisshaders/iris/shadows/ShadowRenderer.java index 653e741e1a..b65cbdfe93 100644 --- a/common/src/main/java/net/irisshaders/iris/shadows/ShadowRenderer.java +++ b/common/src/main/java/net/irisshaders/iris/shadows/ShadowRenderer.java @@ -451,11 +451,6 @@ public void renderShadows(LevelRendererAccessor levelRenderer, Camera playerCame // Execute the vanilla terrain setup / culling routines using our shadow frustum. levelRenderer.invokeSetupRender(playerCamera, terrainFrustumHolder.getFrustum(), false, false); - // Don't forget to increment the frame counter! This variable is arbitrary and only used in terrain setup, - // and if it's not incremented, the vanilla culling code will get confused and think that it's already seen - // chunks during traversal, and break rendering in concerning ways. - //worldRenderer.setFrameId(worldRenderer.getFrameId() + 1); - client.smartCull = wasChunkCullingEnabled; profiler.popPush("terrain"); diff --git a/common/src/main/java/net/irisshaders/iris/shadows/frustum/advanced/AdvancedShadowCullingFrustum.java b/common/src/main/java/net/irisshaders/iris/shadows/frustum/advanced/AdvancedShadowCullingFrustum.java index 35a5c891c5..824ad3dd13 100644 --- a/common/src/main/java/net/irisshaders/iris/shadows/frustum/advanced/AdvancedShadowCullingFrustum.java +++ b/common/src/main/java/net/irisshaders/iris/shadows/frustum/advanced/AdvancedShadowCullingFrustum.java @@ -358,7 +358,6 @@ protected int checkCornerVisibility(float minX, float minY, float minZ, float ma float outsideBoundY = (plane[1] < 0) ? minY : maxY; float outsideBoundZ = (plane[2] < 0) ? minZ : maxZ; - // Use Math.fma for the dot product calculation to get vectorization (sorry old Intel users) if (FMA_SUPPORT) { if (Math.fma(plane[0], outsideBoundX, Math.fma(plane[1], outsideBoundY, plane[2] * outsideBoundZ)) >= -plane[3]) { inside &= Math.fma(plane[0], (plane[0] < 0 ? maxX : minX), @@ -400,6 +399,7 @@ public boolean checkCornerVisibilityBool(float minX, float minY, float minZ, flo float outsideBoundY = (plane[1] < 0) ? minY : maxY; float outsideBoundZ = (plane[2] < 0) ? minZ : maxZ; + // TODO: also implement with safeFMA if (Math.fma(plane[0], outsideBoundX, Math.fma(plane[1], outsideBoundY, plane[2] * outsideBoundZ)) < -plane[3]) { return false; } From beea3d97588961bbd7adeb0d5555dfadc40c51e7 Mon Sep 17 00:00:00 2001 From: douira Date: Sat, 16 Nov 2024 01:45:12 +0100 Subject: [PATCH 5/9] fix some tracking of necessary shadow render list updates --- .../compat/sodium/mixin/MixinRenderSectionManagerShadow.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/common/src/main/java/net/irisshaders/iris/compat/sodium/mixin/MixinRenderSectionManagerShadow.java b/common/src/main/java/net/irisshaders/iris/compat/sodium/mixin/MixinRenderSectionManagerShadow.java index 7863ed77ca..97cd0b94dc 100644 --- a/common/src/main/java/net/irisshaders/iris/compat/sodium/mixin/MixinRenderSectionManagerShadow.java +++ b/common/src/main/java/net/irisshaders/iris/compat/sodium/mixin/MixinRenderSectionManagerShadow.java @@ -43,7 +43,7 @@ public abstract class MixinRenderSectionManagerShadow { private @NotNull SortedRenderLists shadowRenderLists = SortedRenderLists.empty(); @Unique - private boolean shadowNeedsRenderListUpdate; + private boolean shadowNeedsRenderListUpdate = true; @Unique private ShadowSectionTree shadowSectionTree; @@ -127,6 +127,7 @@ private void updateSectionInfo(RenderSection render, BuiltSectionInfo info, Call } else { this.shadowSectionTree.addSection(x, y, z); } + this.shadowNeedsRenderListUpdate = true; } @Inject(method = "onSectionRemoved", at = @At("HEAD")) @@ -134,6 +135,7 @@ private void onSectionRemoved(int x, int y, int z, CallbackInfo ci) { this.ensureShadowSectionTree(); this.shadowSectionTree.removeSection(x, y, z); + this.shadowNeedsRenderListUpdate = true; } @Redirect(method = { @@ -145,7 +147,6 @@ private SortedRenderLists useShadowRenderList(RenderSectionManager instance) { return ShadowRenderingState.areShadowsCurrentlyBeingRendered() ? this.shadowRenderLists : this.renderLists; } - @Inject(method = "getChunksDebugString", at = @At("HEAD"), cancellable = true) private void getShadowChunksDebugString(CallbackInfoReturnable cir) { if (ShadowRenderingState.areShadowsCurrentlyBeingRendered()) { From be823556dfc7dec9acba39977f183f8d970e5c8d Mon Sep 17 00:00:00 2001 From: douira Date: Sat, 16 Nov 2024 02:50:18 +0100 Subject: [PATCH 6/9] fix logic error in shadow frustum --- .../MixinAdvancedShadowCullingFrustum.java | 4 +- .../MixinRenderSectionManagerShadow.java | 6 +- .../iris/shadows/frustum/BoxCuller.java | 23 +++++ .../AdvancedShadowCullingFrustum.java | 93 +++++++++++-------- .../ReversedAdvancedShadowCullingFrustum.java | 42 +++++---- .../frustum/fallback/BoxCullingFrustum.java | 14 +-- .../frustum/fallback/NonCullingFrustum.java | 10 +- 7 files changed, 122 insertions(+), 70 deletions(-) diff --git a/common/src/main/java/net/irisshaders/iris/compat/dh/mixin/MixinAdvancedShadowCullingFrustum.java b/common/src/main/java/net/irisshaders/iris/compat/dh/mixin/MixinAdvancedShadowCullingFrustum.java index 8d612f839b..a09df069e0 100644 --- a/common/src/main/java/net/irisshaders/iris/compat/dh/mixin/MixinAdvancedShadowCullingFrustum.java +++ b/common/src/main/java/net/irisshaders/iris/compat/dh/mixin/MixinAdvancedShadowCullingFrustum.java @@ -21,7 +21,7 @@ public MixinAdvancedShadowCullingFrustum(Matrix4f matrix4f, Matrix4f matrix4f2) } @Shadow(remap = false) - protected int isVisible(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) { + protected boolean isVisibleBool(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) { throw new IllegalStateException(); } @@ -33,6 +33,6 @@ public void update(int worldMinBlockY, int worldMaxBlockY, DhApiMat4f worldViewP @Override public boolean intersects(int lodBlockPosMinX, int lodBlockPosMinZ, int lodBlockWidth, int lodDetailLevel) { - return this.isVisible(lodBlockPosMinX, this.worldMinYDH, lodBlockPosMinZ, lodBlockPosMinX + lodBlockWidth, this.worldMaxYDH, lodBlockPosMinZ + lodBlockWidth) != 0; + return this.isVisibleBool(lodBlockPosMinX, this.worldMinYDH, lodBlockPosMinZ, lodBlockPosMinX + lodBlockWidth, this.worldMaxYDH, lodBlockPosMinZ + lodBlockWidth); } } diff --git a/common/src/main/java/net/irisshaders/iris/compat/sodium/mixin/MixinRenderSectionManagerShadow.java b/common/src/main/java/net/irisshaders/iris/compat/sodium/mixin/MixinRenderSectionManagerShadow.java index 97cd0b94dc..87ced798e0 100644 --- a/common/src/main/java/net/irisshaders/iris/compat/sodium/mixin/MixinRenderSectionManagerShadow.java +++ b/common/src/main/java/net/irisshaders/iris/compat/sodium/mixin/MixinRenderSectionManagerShadow.java @@ -66,13 +66,13 @@ private void updateRenderLists(Camera camera, Viewport viewport, boolean spectat this.shadowNeedsRenderListUpdate |= this.needsRenderListUpdate; } - @Shadow + @Shadow(remap = false) protected abstract float getRenderDistance(); - @Shadow + @Shadow(remap = false) public abstract int getVisibleChunkCount(); - @Shadow + @Shadow(remap = false) public abstract int getTotalSections(); @Inject(method = "updateRenderLists", at = @At("HEAD"), cancellable = true) diff --git a/common/src/main/java/net/irisshaders/iris/shadows/frustum/BoxCuller.java b/common/src/main/java/net/irisshaders/iris/shadows/frustum/BoxCuller.java index ae61ef5ad2..926bf12cef 100644 --- a/common/src/main/java/net/irisshaders/iris/shadows/frustum/BoxCuller.java +++ b/common/src/main/java/net/irisshaders/iris/shadows/frustum/BoxCuller.java @@ -1,6 +1,7 @@ package net.irisshaders.iris.shadows.frustum; import net.minecraft.world.phys.AABB; +import org.joml.FrustumIntersection; public class BoxCuller { private final double maxDistance; @@ -54,6 +55,28 @@ public boolean isCulledSodium(double minX, double minY, double minZ, double maxX return maxZ < -this.maxDistance || minZ > this.maxDistance; } + public int intersectAab(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) { + if (maxX < -this.maxDistance || minX > this.maxDistance) { + return FrustumIntersection.OUTSIDE; + } + + if (maxY < -this.maxDistance || minY > this.maxDistance) { + return FrustumIntersection.OUTSIDE; + } + + if (maxZ < -this.maxDistance || minZ > this.maxDistance) { + return FrustumIntersection.OUTSIDE; + } + + if (minX >= -this.maxDistance && maxX <= this.maxDistance && + minY >= -this.maxDistance && maxY <= this.maxDistance && + minZ >= -this.maxDistance && maxZ <= this.maxDistance) { + return FrustumIntersection.INSIDE; + } + + return FrustumIntersection.INTERSECT; + } + @Override public String toString() { return "Box Culling active; max distance " + maxDistance; diff --git a/common/src/main/java/net/irisshaders/iris/shadows/frustum/advanced/AdvancedShadowCullingFrustum.java b/common/src/main/java/net/irisshaders/iris/shadows/frustum/advanced/AdvancedShadowCullingFrustum.java index 824ad3dd13..c2f8e514c0 100644 --- a/common/src/main/java/net/irisshaders/iris/shadows/frustum/advanced/AdvancedShadowCullingFrustum.java +++ b/common/src/main/java/net/irisshaders/iris/shadows/frustum/advanced/AdvancedShadowCullingFrustum.java @@ -7,6 +7,7 @@ import net.irisshaders.iris.shadows.frustum.BoxCuller; import net.minecraft.client.renderer.culling.Frustum; import net.minecraft.world.phys.AABB; +import org.jetbrains.annotations.Nullable; import org.joml.FrustumIntersection; import org.joml.Matrix4fc; import org.joml.Vector3d; @@ -37,7 +38,7 @@ */ public class AdvancedShadowCullingFrustum extends Frustum implements net.caffeinemc.mods.sodium.client.render.viewport.frustum.Frustum, ViewportProvider { private static final int MAX_CLIPPING_PLANES = 13; - protected final BoxCuller boxCuller; + protected final @Nullable BoxCuller boxCuller; /** * We store each plane equation as a Vector4f. * @@ -76,7 +77,7 @@ public class AdvancedShadowCullingFrustum extends Frustum implements net.caffein private int planeCount = 0; public AdvancedShadowCullingFrustum(Matrix4fc modelViewProjection, Matrix4fc shadowProjection, Vector3f shadowLightVectorFromOrigin, - BoxCuller boxCuller) { + @Nullable BoxCuller boxCuller) { // We're overriding all of the methods, don't pass any matrices down. super(new org.joml.Matrix4f(), new org.joml.Matrix4f()); @@ -291,28 +292,8 @@ public void prepare(double cameraX, double cameraY, double cameraZ) { } @Override - public boolean isVisible(AABB aabb) { - if (boxCuller != null && boxCuller.isCulled(aabb)) { - return false; - } - - return this.isVisible(aabb.minX, aabb.minY, aabb.minZ, aabb.maxX, aabb.maxY, aabb.maxZ) != FrustumIntersection.OUTSIDE; - } - - // For Immersive Portals - // TODO: Figure out if IP culling can somehow be compatible with Iris culling. - public boolean canDetermineInvisible(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) { - return false; - } - - protected int isVisible(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) { - float f = (float) (minX - this.x); - float g = (float) (minY - this.y); - float h = (float) (minZ - this.z); - float i = (float) (maxX - this.x); - float j = (float) (maxY - this.y); - float k = (float) (maxZ - this.z); - return this.checkCornerVisibility(f, g, h, i, j, k); + public Viewport sodium$createViewport() { + return new Viewport(this, this.position.set(this.x, this.y, this.z)); } private static final boolean FMA_SUPPORT; @@ -348,7 +329,7 @@ private static float safeFMA(float a, float b, float c) { protected int checkCornerVisibility(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) { boolean inside = true; - for (int i = 0; i < planeCount; ++i) { + for (int i = 0; i < this.planeCount; ++i) { float[] plane = this.planes[i]; // Check if plane is inside or intersecting. @@ -392,37 +373,75 @@ protected int checkCornerVisibility(float minX, float minY, float minZ, float ma * @return true if visible, false if not. */ public boolean checkCornerVisibilityBool(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) { - for (int i = 0; i < planeCount; ++i) { - float[] plane = planes[i]; + for (int i = 0; i < this.planeCount; ++i) { + float[] plane = this.planes[i]; float outsideBoundX = (plane[0] < 0) ? minX : maxX; float outsideBoundY = (plane[1] < 0) ? minY : maxY; float outsideBoundZ = (plane[2] < 0) ? minZ : maxZ; - // TODO: also implement with safeFMA - if (Math.fma(plane[0], outsideBoundX, Math.fma(plane[1], outsideBoundY, plane[2] * outsideBoundZ)) < -plane[3]) { - return false; + if (FMA_SUPPORT) { + if (Math.fma(plane[0], outsideBoundX, Math.fma(plane[1], outsideBoundY, plane[2] * outsideBoundZ)) < -plane[3]) { + return false; + } + } else { + if (safeFMA(plane[0], outsideBoundX, safeFMA(plane[1], outsideBoundY, plane[2] * outsideBoundZ)) < -plane[3]) { + return false; + } } } return true; } + // For Immersive Portals + // TODO: Figure out if IP culling can somehow be compatible with Iris culling. + public boolean canDetermineInvisible(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) { + return false; + } + + protected boolean isVisibleBool(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) { + return this.checkCornerVisibilityBool( + (float) (minX - this.x), + (float) (minY - this.y), + (float) (minZ - this.z), + (float) (maxX - this.x), + (float) (maxY - this.y), + (float) (maxZ - this.z)); + } + + @Override + public boolean isVisible(AABB aabb) { + if (this.boxCuller != null && this.boxCuller.isCulled(aabb)) { + return false; + } + + return this.isVisibleBool(aabb.minX, aabb.minY, aabb.minZ, aabb.maxX, aabb.maxY, aabb.maxZ); + } + @Override public boolean testAab(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) { - return (boxCuller == null || !boxCuller.isCulledSodium(minX, minY, minZ, maxX, maxY, maxZ)) && this.checkCornerVisibilityBool(minX, minY, minZ, maxX, maxY, maxZ); + return (this.boxCuller == null || !this.boxCuller.isCulledSodium(minX, minY, minZ, maxX, maxY, maxZ)) && + this.checkCornerVisibilityBool(minX, minY, minZ, maxX, maxY, maxZ); } @Override public int intersectAab(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) { - if (boxCuller != null && boxCuller.isCulledSodium(minX, minY, minZ, maxX, maxY, maxZ)) { + if (this.boxCuller == null) { + return this.checkCornerVisibility(minX, minY, minZ, maxX, maxY, maxZ); + } + + var distanceResult = this.boxCuller.intersectAab(minX, minY, minZ, maxX, maxY, maxZ); + if (distanceResult == FrustumIntersection.OUTSIDE) { return FrustumIntersection.OUTSIDE; } - return this.checkCornerVisibility(minX, minY, minZ, maxX, maxY, maxZ); - } + if (distanceResult == FrustumIntersection.INSIDE) { + return this.checkCornerVisibility(minX, minY, minZ, maxX, maxY, maxZ); + } - @Override - public Viewport sodium$createViewport() { - return new Viewport(this, position.set(x, y, z)); + // distanceResult == FrustumIntersection.INTERSECT, so the final result is either OUTSIDE or INTERSECT. + // critically, it's not INSIDE, because the frustum test can't determine that alone. + var frustumResult = this.checkCornerVisibility(minX, minY, minZ, maxX, maxY, maxZ); + return frustumResult == FrustumIntersection.INSIDE ? FrustumIntersection.INTERSECT : frustumResult; } } diff --git a/common/src/main/java/net/irisshaders/iris/shadows/frustum/advanced/ReversedAdvancedShadowCullingFrustum.java b/common/src/main/java/net/irisshaders/iris/shadows/frustum/advanced/ReversedAdvancedShadowCullingFrustum.java index 22d3504489..d6593e298f 100644 --- a/common/src/main/java/net/irisshaders/iris/shadows/frustum/advanced/ReversedAdvancedShadowCullingFrustum.java +++ b/common/src/main/java/net/irisshaders/iris/shadows/frustum/advanced/ReversedAdvancedShadowCullingFrustum.java @@ -2,58 +2,68 @@ import net.irisshaders.iris.shadows.frustum.BoxCuller; import net.minecraft.world.phys.AABB; +import org.jetbrains.annotations.NotNull; import org.joml.FrustumIntersection; import org.joml.Matrix4fc; import org.joml.Vector3f; -// TODO: I don't know what this class does and I probably broke it by changing AdvancedShadowCullingFrustum +// nothing is rendered that falls outside the distanceCuller, and everything is rendered that falls within the boxCuller (voxel culler) public class ReversedAdvancedShadowCullingFrustum extends AdvancedShadowCullingFrustum { - private final BoxCuller distanceCuller; + private final @NotNull BoxCuller distanceCuller; - public ReversedAdvancedShadowCullingFrustum(Matrix4fc modelViewProjection, Matrix4fc shadowProjection, Vector3f shadowLightVectorFromOrigin, BoxCuller voxelCuller, BoxCuller distanceCuller) { + public ReversedAdvancedShadowCullingFrustum(Matrix4fc modelViewProjection, Matrix4fc shadowProjection, Vector3f shadowLightVectorFromOrigin, BoxCuller voxelCuller, @NotNull BoxCuller distanceCuller) { super(modelViewProjection, shadowProjection, shadowLightVectorFromOrigin, voxelCuller); this.distanceCuller = distanceCuller; } @Override public void prepare(double cameraX, double cameraY, double cameraZ) { - if (this.distanceCuller != null) { - this.distanceCuller.setPosition(cameraX, cameraY, cameraZ); - } + this.distanceCuller.setPosition(cameraX, cameraY, cameraZ); super.prepare(cameraX, cameraY, cameraZ); } @Override public boolean isVisible(AABB aabb) { - if (distanceCuller != null && distanceCuller.isCulled(aabb)) { + if (this.distanceCuller.isCulled(aabb)) { return false; } - if (boxCuller != null && !boxCuller.isCulled(aabb)) { + if (this.boxCuller != null && !this.boxCuller.isCulled(aabb)) { return true; } - // TODO: ? - return this.isVisible(aabb.minX, aabb.minY, aabb.minZ, aabb.maxX, aabb.maxY, aabb.maxZ) != FrustumIntersection.OUTSIDE; + return this.isVisibleBool(aabb.minX, aabb.minY, aabb.minZ, aabb.maxX, aabb.maxY, aabb.maxZ); } @Override public boolean testAab(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) { - if (distanceCuller != null && distanceCuller.isCulledSodium(minX, minY, minZ, maxX, maxY, maxZ)) { + if (this.distanceCuller.isCulledSodium(minX, minY, minZ, maxX, maxY, maxZ)) { return false; } - if (boxCuller != null && !boxCuller.isCulledSodium(minX, minY, minZ, maxX, maxY, maxZ)) { + if (this.boxCuller != null && !this.boxCuller.isCulledSodium(minX, minY, minZ, maxX, maxY, maxZ)) { return true; } - // TODO: ? - return this.checkCornerVisibility(minX, minY, minZ, maxX, maxY, maxZ) != FrustumIntersection.OUTSIDE; + return this.checkCornerVisibilityBool(minX, minY, minZ, maxX, maxY, maxZ); } @Override public int intersectAab(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) { - // TODO: placeholder - return FrustumIntersection.INSIDE; + var distanceResult = this.distanceCuller.intersectAab(minX, minY, minZ, maxX, maxY, maxZ); + if (distanceResult == FrustumIntersection.OUTSIDE) { + return FrustumIntersection.OUTSIDE; + } + + if (this.boxCuller != null && !this.boxCuller.isCulledSodium(minX, minY, minZ, maxX, maxY, maxZ)) { + return FrustumIntersection.INSIDE; + } + + if (distanceResult == FrustumIntersection.INSIDE) { + return this.checkCornerVisibility(minX, minY, minZ, maxX, maxY, maxZ); + } + + var frustumResult = this.checkCornerVisibility(minX, minY, minZ, maxX, maxY, maxZ); + return frustumResult == FrustumIntersection.INSIDE ? FrustumIntersection.INTERSECT : frustumResult; } } diff --git a/common/src/main/java/net/irisshaders/iris/shadows/frustum/fallback/BoxCullingFrustum.java b/common/src/main/java/net/irisshaders/iris/shadows/frustum/fallback/BoxCullingFrustum.java index 15160b6d3a..3da41a629f 100644 --- a/common/src/main/java/net/irisshaders/iris/shadows/frustum/fallback/BoxCullingFrustum.java +++ b/common/src/main/java/net/irisshaders/iris/shadows/frustum/fallback/BoxCullingFrustum.java @@ -32,22 +32,22 @@ public boolean canDetermineInvisible(double minX, double minY, double minZ, doub return false; } - public boolean isVisible(AABB box) { - return !boxCuller.isCulled(box); - } - @Override public Viewport sodium$createViewport() { - return new Viewport(this, position); + return new Viewport(this, this.position); + } + + public boolean isVisible(AABB box) { + return !this.boxCuller.isCulled(box); } @Override public boolean testAab(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) { - return !boxCuller.isCulledSodium(minX, minY, minZ, maxX, maxY, maxZ); + return !this.boxCuller.isCulledSodium(minX, minY, minZ, maxX, maxY, maxZ); } @Override public int intersectAab(float v, float v1, float v2, float v3, float v4, float v5) { - return this.boxCuller.isCulledSodium(v, v1, v2, v3, v4, v5) ? FrustumIntersection.OUTSIDE : FrustumIntersection.INTERSECT; + return this.boxCuller.intersectAab(v, v1, v2, v3, v4, v5); } } diff --git a/common/src/main/java/net/irisshaders/iris/shadows/frustum/fallback/NonCullingFrustum.java b/common/src/main/java/net/irisshaders/iris/shadows/frustum/fallback/NonCullingFrustum.java index fe174866e3..dadd62e148 100644 --- a/common/src/main/java/net/irisshaders/iris/shadows/frustum/fallback/NonCullingFrustum.java +++ b/common/src/main/java/net/irisshaders/iris/shadows/frustum/fallback/NonCullingFrustum.java @@ -24,10 +24,6 @@ public boolean canDetermineInvisible(double minX, double minY, double minZ, doub return false; } - public boolean isVisible(AABB box) { - return true; - } - @Override public int cubeInFrustum(BoundingBox boundingBox) { return FrustumIntersection.INSIDE; @@ -55,7 +51,11 @@ public void prepare(double d, double e, double f) { @Override public Viewport sodium$createViewport() { - return new Viewport(this, position); + return new Viewport(this, this.position); + } + + public boolean isVisible(AABB box) { + return true; } @Override From 267cca9ae99e797133d984f6b6614c6f2bfb094e Mon Sep 17 00:00:00 2001 From: douira Date: Sat, 16 Nov 2024 16:30:10 +0100 Subject: [PATCH 7/9] rename reversed shadow culling to safe zone, fixed shadow culling logic --- .../properties/ShaderProperties.java | 2 +- .../properties/ShadowCullState.java | 2 +- .../iris/shadows/ShadowRenderer.java | 18 ++++++------ .../AdvancedShadowCullingFrustum.java | 15 ++++++---- ...SafeZoneAdvancedShadowCullingFrustum.java} | 29 ++++++++++++++----- 5 files changed, 41 insertions(+), 25 deletions(-) rename common/src/main/java/net/irisshaders/iris/shadows/frustum/advanced/{ReversedAdvancedShadowCullingFrustum.java => SafeZoneAdvancedShadowCullingFrustum.java} (69%) diff --git a/common/src/main/java/net/irisshaders/iris/shaderpack/properties/ShaderProperties.java b/common/src/main/java/net/irisshaders/iris/shaderpack/properties/ShaderProperties.java index 2efec5d5e5..b63b1de3bd 100644 --- a/common/src/main/java/net/irisshaders/iris/shaderpack/properties/ShaderProperties.java +++ b/common/src/main/java/net/irisshaders/iris/shaderpack/properties/ShaderProperties.java @@ -178,7 +178,7 @@ public ShaderProperties(String contents, ShaderPackOptions shaderPackOptions, It switch (value) { case "false" -> shadowCulling = ShadowCullState.DISTANCE; case "true" -> shadowCulling = ShadowCullState.ADVANCED; - case "reversed" -> shadowCulling = ShadowCullState.REVERSED; + case "reversed", "safe_zone" -> shadowCulling = ShadowCullState.ADVANCED_SAFE_ZONE; case null, default -> Iris.logger.error("Unrecognized shadow culling setting: " + value); } } diff --git a/common/src/main/java/net/irisshaders/iris/shaderpack/properties/ShadowCullState.java b/common/src/main/java/net/irisshaders/iris/shaderpack/properties/ShadowCullState.java index 5870ea4169..ef55bbef1f 100644 --- a/common/src/main/java/net/irisshaders/iris/shaderpack/properties/ShadowCullState.java +++ b/common/src/main/java/net/irisshaders/iris/shaderpack/properties/ShadowCullState.java @@ -3,6 +3,6 @@ public enum ShadowCullState { DEFAULT, ADVANCED, - REVERSED, + ADVANCED_SAFE_ZONE, DISTANCE } diff --git a/common/src/main/java/net/irisshaders/iris/shadows/ShadowRenderer.java b/common/src/main/java/net/irisshaders/iris/shadows/ShadowRenderer.java index b65cbdfe93..2044a1b724 100644 --- a/common/src/main/java/net/irisshaders/iris/shadows/ShadowRenderer.java +++ b/common/src/main/java/net/irisshaders/iris/shadows/ShadowRenderer.java @@ -25,7 +25,7 @@ import net.irisshaders.iris.shadows.frustum.CullEverythingFrustum; import net.irisshaders.iris.shadows.frustum.FrustumHolder; import net.irisshaders.iris.shadows.frustum.advanced.AdvancedShadowCullingFrustum; -import net.irisshaders.iris.shadows.frustum.advanced.ReversedAdvancedShadowCullingFrustum; +import net.irisshaders.iris.shadows.frustum.advanced.SafeZoneAdvancedShadowCullingFrustum; import net.irisshaders.iris.shadows.frustum.fallback.BoxCullingFrustum; import net.irisshaders.iris.shadows.frustum.fallback.NonCullingFrustum; import net.irisshaders.iris.uniforms.CameraUniforms; @@ -305,12 +305,12 @@ private FrustumHolder createShadowFrustum(float renderMultiplier, FrustumHolder } else { BoxCuller boxCuller; - boolean isReversed = packCullingState == ShadowCullState.REVERSED; + boolean hasSafeZone = packCullingState == ShadowCullState.ADVANCED_SAFE_ZONE; // Assume render multiplier is meant to be 1 if reversed culling is on - if (isReversed && renderMultiplier < 0) renderMultiplier = 1.0f; + if (hasSafeZone && renderMultiplier < 0) renderMultiplier = 1.0f; - double distance = (isReversed ? voxelDistance : halfPlaneLength) * renderMultiplier; + double distance = (hasSafeZone ? voxelDistance : halfPlaneLength) * renderMultiplier; String setter = "(set by shader pack)"; if (renderMultiplier < 0) { @@ -318,7 +318,7 @@ private FrustumHolder createShadowFrustum(float renderMultiplier, FrustumHolder setter = "(set by user)"; } - if (distance >= Minecraft.getInstance().options.getEffectiveRenderDistance() * 16 && !isReversed) { + if (distance >= Minecraft.getInstance().options.getEffectiveRenderDistance() * 16 && !hasSafeZone) { distanceInfo = "render distance = " + Minecraft.getInstance().options.getEffectiveRenderDistance() * 16 + " blocks "; distanceInfo += Minecraft.getInstance().isLocalServer() ? "(capped by normal render distance)" : "(capped by normal/server render distance)"; @@ -326,7 +326,7 @@ private FrustumHolder createShadowFrustum(float renderMultiplier, FrustumHolder } else { distanceInfo = distance + " blocks " + setter; - if (distance == 0.0 && !isReversed) { + if (distance == 0.0 && !hasSafeZone) { cullingInfo = "no shadows rendered"; holder.setInfo(new CullEverythingFrustum(), distanceInfo, cullingInfo); } @@ -334,7 +334,7 @@ private FrustumHolder createShadowFrustum(float renderMultiplier, FrustumHolder boxCuller = new BoxCuller(distance); } - cullingInfo = (isReversed ? "Reversed" : "Advanced") + " Frustum Culling enabled"; + cullingInfo = (hasSafeZone ? "Reversed" : "Advanced") + " Frustum Culling enabled"; Vector4f shadowLightPosition = new CelestialUniforms(sunPathRotation).getShadowLightPositionInWorldSpace(); @@ -346,8 +346,8 @@ private FrustumHolder createShadowFrustum(float renderMultiplier, FrustumHolder Matrix4f projView = ((shouldRenderDH && DHCompat.hasRenderingEnabled()) ? DHCompat.getProjection() : CapturedRenderingState.INSTANCE.getGbufferProjection()) .mul(CapturedRenderingState.INSTANCE.getGbufferModelView(), new Matrix4f()); - if (isReversed) { - return holder.setInfo(new ReversedAdvancedShadowCullingFrustum(projView, PROJECTION, shadowLightVectorFromOrigin, boxCuller, new BoxCuller(halfPlaneLength * renderMultiplier)), distanceInfo, cullingInfo); + if (hasSafeZone) { + return holder.setInfo(new SafeZoneAdvancedShadowCullingFrustum(projView, PROJECTION, shadowLightVectorFromOrigin, boxCuller, new BoxCuller(halfPlaneLength * renderMultiplier)), distanceInfo, cullingInfo); } else { return holder.setInfo(new AdvancedShadowCullingFrustum(projView, PROJECTION, shadowLightVectorFromOrigin, boxCuller), distanceInfo, cullingInfo); } diff --git a/common/src/main/java/net/irisshaders/iris/shadows/frustum/advanced/AdvancedShadowCullingFrustum.java b/common/src/main/java/net/irisshaders/iris/shadows/frustum/advanced/AdvancedShadowCullingFrustum.java index c2f8e514c0..0f2dd6e4ea 100644 --- a/common/src/main/java/net/irisshaders/iris/shadows/frustum/advanced/AdvancedShadowCullingFrustum.java +++ b/common/src/main/java/net/irisshaders/iris/shadows/frustum/advanced/AdvancedShadowCullingFrustum.java @@ -435,13 +435,16 @@ public int intersectAab(float minX, float minY, float minZ, float maxX, float ma if (distanceResult == FrustumIntersection.OUTSIDE) { return FrustumIntersection.OUTSIDE; } - if (distanceResult == FrustumIntersection.INSIDE) { - return this.checkCornerVisibility(minX, minY, minZ, maxX, maxY, maxZ); - } - // distanceResult == FrustumIntersection.INTERSECT, so the final result is either OUTSIDE or INTERSECT. - // critically, it's not INSIDE, because the frustum test can't determine that alone. var frustumResult = this.checkCornerVisibility(minX, minY, minZ, maxX, maxY, maxZ); - return frustumResult == FrustumIntersection.INSIDE ? FrustumIntersection.INTERSECT : frustumResult; + if (frustumResult == FrustumIntersection.OUTSIDE) { + return FrustumIntersection.OUTSIDE; + } + + if (frustumResult == FrustumIntersection.INSIDE && distanceResult == FrustumIntersection.INSIDE) { + return FrustumIntersection.INSIDE; + } + + return FrustumIntersection.INTERSECT; } } diff --git a/common/src/main/java/net/irisshaders/iris/shadows/frustum/advanced/ReversedAdvancedShadowCullingFrustum.java b/common/src/main/java/net/irisshaders/iris/shadows/frustum/advanced/SafeZoneAdvancedShadowCullingFrustum.java similarity index 69% rename from common/src/main/java/net/irisshaders/iris/shadows/frustum/advanced/ReversedAdvancedShadowCullingFrustum.java rename to common/src/main/java/net/irisshaders/iris/shadows/frustum/advanced/SafeZoneAdvancedShadowCullingFrustum.java index d6593e298f..c30248e953 100644 --- a/common/src/main/java/net/irisshaders/iris/shadows/frustum/advanced/ReversedAdvancedShadowCullingFrustum.java +++ b/common/src/main/java/net/irisshaders/iris/shadows/frustum/advanced/SafeZoneAdvancedShadowCullingFrustum.java @@ -7,11 +7,11 @@ import org.joml.Matrix4fc; import org.joml.Vector3f; -// nothing is rendered that falls outside the distanceCuller, and everything is rendered that falls within the boxCuller (voxel culler) -public class ReversedAdvancedShadowCullingFrustum extends AdvancedShadowCullingFrustum { +// nothing is rendered that falls outside the distanceCuller, and everything is rendered that falls within the boxCuller (safe zone) +public class SafeZoneAdvancedShadowCullingFrustum extends AdvancedShadowCullingFrustum { private final @NotNull BoxCuller distanceCuller; - public ReversedAdvancedShadowCullingFrustum(Matrix4fc modelViewProjection, Matrix4fc shadowProjection, Vector3f shadowLightVectorFromOrigin, BoxCuller voxelCuller, @NotNull BoxCuller distanceCuller) { + public SafeZoneAdvancedShadowCullingFrustum(Matrix4fc modelViewProjection, Matrix4fc shadowProjection, Vector3f shadowLightVectorFromOrigin, BoxCuller voxelCuller, @NotNull BoxCuller distanceCuller) { super(modelViewProjection, shadowProjection, shadowLightVectorFromOrigin, voxelCuller); this.distanceCuller = distanceCuller; } @@ -55,15 +55,28 @@ public int intersectAab(float minX, float minY, float minZ, float maxX, float ma return FrustumIntersection.OUTSIDE; } - if (this.boxCuller != null && !this.boxCuller.isCulledSodium(minX, minY, minZ, maxX, maxY, maxZ)) { - return FrustumIntersection.INSIDE; + var safeZoneResult = FrustumIntersection.OUTSIDE; + if (this.boxCuller != null) { + safeZoneResult = this.boxCuller.intersectAab(minX, minY, minZ, maxX, maxY, maxZ); + if (safeZoneResult == FrustumIntersection.INSIDE) { + return FrustumIntersection.INSIDE; + } } - if (distanceResult == FrustumIntersection.INSIDE) { - return this.checkCornerVisibility(minX, minY, minZ, maxX, maxY, maxZ); + if (distanceResult == FrustumIntersection.INTERSECT && safeZoneResult == FrustumIntersection.INTERSECT) { + return FrustumIntersection.INTERSECT; } var frustumResult = this.checkCornerVisibility(minX, minY, minZ, maxX, maxY, maxZ); - return frustumResult == FrustumIntersection.INSIDE ? FrustumIntersection.INTERSECT : frustumResult; + + if (safeZoneResult == FrustumIntersection.OUTSIDE && frustumResult == FrustumIntersection.OUTSIDE) { + return FrustumIntersection.OUTSIDE; + } + + if (frustumResult == FrustumIntersection.INSIDE && distanceResult == FrustumIntersection.INSIDE) { + return FrustumIntersection.INSIDE; + } + + return FrustumIntersection.INTERSECT; } } From 6628324d7e95e55aaf05291d30e946c5460b5610 Mon Sep 17 00:00:00 2001 From: douira Date: Sun, 24 Nov 2024 04:11:39 +0100 Subject: [PATCH 8/9] don't force terrain update every frame in shadow pass --- .../java/net/irisshaders/iris/shadows/ShadowRenderer.java | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/common/src/main/java/net/irisshaders/iris/shadows/ShadowRenderer.java b/common/src/main/java/net/irisshaders/iris/shadows/ShadowRenderer.java index 2044a1b724..c986fee490 100644 --- a/common/src/main/java/net/irisshaders/iris/shadows/ShadowRenderer.java +++ b/common/src/main/java/net/irisshaders/iris/shadows/ShadowRenderer.java @@ -440,13 +440,7 @@ public void renderShadows(LevelRendererAccessor levelRenderer, Camera playerCame boolean wasChunkCullingEnabled = client.smartCull; client.smartCull = false; - // Always schedule a terrain update - // TODO: Only schedule a terrain update if the sun / moon is moving, or the shadow map camera moved. - // We have to ensure that we don't regenerate clouds every frame, since that's what needsUpdate ends up doing. - // This took up to 10% of the frame time before we applied this fix! That's really bad! - - // TODO IMS 24w35a determine clouds - ((LevelRenderer) levelRenderer).needsUpdate(); + // forcing a terrain update it not necessary here, sodium figured it out on its own // Execute the vanilla terrain setup / culling routines using our shadow frustum. levelRenderer.invokeSetupRender(playerCamera, terrainFrustumHolder.getFrustum(), false, false); From e9426aed817f6c672751b350bbd4d294be007d96 Mon Sep 17 00:00:00 2001 From: douira Date: Sun, 24 Nov 2024 04:43:05 +0100 Subject: [PATCH 9/9] delete github workflows to make it stop sending me emails --- .github/workflows/build-release.yml | 51 ----------------------------- .github/workflows/build.yml | 32 ------------------ 2 files changed, 83 deletions(-) delete mode 100644 .github/workflows/build-release.yml delete mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml deleted file mode 100644 index 30577674d7..0000000000 --- a/.github/workflows/build-release.yml +++ /dev/null @@ -1,51 +0,0 @@ -# This workflow will build a Java project with Brachyra -# For more information see: docs/development/brachyura.md - -name: Release script - -on: - release: - types: - - published - -jobs: - build: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - - uses: actions/setup-java@v4 - with: - distribution: temurin - java-version: 21 - - - name: Setup Gradle - uses: gradle/actions/setup-gradle@v3 - with: - cache-read-only: false - - - name: Run build with Gradle Wrapper - run: ./gradlew build -Dbuild.release=true - - - name: Upload artifacts to Modrinth and GitHub - uses: Kir-Antipov/mc-publish@v3.3 - with: - modrinth-id: YL57xq9U - modrinth-token: ${{ secrets.MODRINTH_TOKEN }} - modrinth-featured: true - - curseforge-id: 455508 - curseforge-token: ${{ secrets.CURSEFORGE_TOKEN }} - - github-token: ${{ secrets.GITHUB_TOKEN }} - - files: build/libs/!(*-@(dev|sources|all)).jar - - version-type: release - - loaders: fabric quilt - - dependencies: sodium - - version-resolver: latest # Defaults to selecting the latest compatible version of Minecraft, using the tag from the fabric.mod.json diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index 713c9b7ec9..0000000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,32 +0,0 @@ -# This workflow will build a Java project with Brachyra -# For more information see: docs/development/brachyura.md - -name: Java CI with Gradle - -on: [push, pull_request] - -jobs: - build: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - - uses: actions/setup-java@v4 - with: - distribution: temurin - java-version: 21 - - - name: Setup Gradle - uses: gradle/actions/setup-gradle@v3 - with: - cache-read-only: false - - - name: Run build with Gradle Wrapper - run: ./gradlew build - - - name: Upload built JAR (Fabric) - uses: actions/upload-artifact@v3 - with: - name: iris-artifacts - path: build/libs