From 21af1b16e2dadd0c789da967883d007f43d0a68b Mon Sep 17 00:00:00 2001 From: djefrey Date: Wed, 22 Apr 2026 14:59:40 +0200 Subject: [PATCH] Fix Iris matrices when rendering sublevels Iris replaces ShaderInstance with ExtendedShader. When ExtendedShader.apply() is called, modelViewInverse and normalMatrix are updated using MODEL_VIEW_MATRIX value. However, in VanillaChunkedSubLevelRenderData.renderChunkedSubLevel(), MODEL_VIEW_MATRIX.set() is called after apply() has already been called. This leaves the Iris matrices in an incorrect state. Calling apply() after every MODEL_VIEW_MATRIX update results in a significant performance impact. Instead, these matrices are recomputed manually after each MODEL_VIEW_MATRIX update. --- .../src/main/groovy/multiloader-common.gradle | 1 + .../iris/ExtendedShaderMixin.java | 58 +++++++++++++++++++ .../iris/ExtendedShaderExtension.java | 5 ++ .../VanillaChunkedSubLevelRenderData.java | 5 ++ common/src/main/resources/sable.mixins.json | 1 + 5 files changed, 70 insertions(+) create mode 100644 common/src/main/java/dev/ryanhcode/sable/mixin/compatibility/iris/ExtendedShaderMixin.java create mode 100644 common/src/main/java/dev/ryanhcode/sable/mixinterface/compatibility/iris/ExtendedShaderExtension.java diff --git a/buildSrc/src/main/groovy/multiloader-common.gradle b/buildSrc/src/main/groovy/multiloader-common.gradle index f8d9344..e1c47c2 100644 --- a/buildSrc/src/main/groovy/multiloader-common.gradle +++ b/buildSrc/src/main/groovy/multiloader-common.gradle @@ -93,6 +93,7 @@ repositories { dependencies { compileOnly "maven.modrinth:lithium:mc1.21.1-0.15.3-neoforge" compileOnly "maven.modrinth:sodium:$sodium_version" + compileOnly "maven.modrinth:iris:$iris_version" compileOnly "maven.modrinth:distanthorizons:$distant_horizons_version" compileOnly("cc.tweaked:cc-tweaked-$minecraft_version-forge:$cc_tweaked_version") compileOnly("io.github.mortuusars.exposure:exposure-${minecraft_version}-neoforge:${exposure_version}") { transitive = false } diff --git a/common/src/main/java/dev/ryanhcode/sable/mixin/compatibility/iris/ExtendedShaderMixin.java b/common/src/main/java/dev/ryanhcode/sable/mixin/compatibility/iris/ExtendedShaderMixin.java new file mode 100644 index 0000000..558c324 --- /dev/null +++ b/common/src/main/java/dev/ryanhcode/sable/mixin/compatibility/iris/ExtendedShaderMixin.java @@ -0,0 +1,58 @@ +package dev.ryanhcode.sable.mixin.compatibility.iris; + +import com.mojang.blaze3d.shaders.Uniform; +import dev.ryanhcode.sable.mixinterface.compatibility.iris.ExtendedShaderExtension; +import net.irisshaders.iris.pipeline.programs.ExtendedShader; +import net.minecraft.client.renderer.ShaderInstance; +import org.joml.Matrix3f; +import org.joml.Matrix4f; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; + +@Mixin(ExtendedShader.class) +public class ExtendedShaderMixin implements ExtendedShaderExtension { + + @Shadow + @Final + private Uniform modelViewInverse; + + @Shadow + @Final + private Uniform normalMatrix; + + @Shadow + @Final + private Matrix4f tempMatrix4f; + + @Shadow + @Final + private Matrix3f tempMatrix3f; + + @Shadow + @Final + private float[] tempFloats; + + @Shadow + @Final + private float[] tempFloats2; + + @Override + @Unique + public void sable$refreshModelViewDerivedMatrices() { + final var modelView = ((ShaderInstance) (Object) this).MODEL_VIEW_MATRIX; + + if (modelView != null) { + if (this.modelViewInverse != null) { + this.modelViewInverse.set(this.tempMatrix4f.set(modelView.getFloatBuffer()).invert().get(this.tempFloats)); + this.modelViewInverse.upload(); + } + + if (this.normalMatrix != null) { + this.normalMatrix.set(this.tempMatrix3f.set(this.tempMatrix4f.set(modelView.getFloatBuffer())).invert().transpose().get(this.tempFloats2)); + this.normalMatrix.upload(); + } + } + } +} diff --git a/common/src/main/java/dev/ryanhcode/sable/mixinterface/compatibility/iris/ExtendedShaderExtension.java b/common/src/main/java/dev/ryanhcode/sable/mixinterface/compatibility/iris/ExtendedShaderExtension.java new file mode 100644 index 0000000..c56558b --- /dev/null +++ b/common/src/main/java/dev/ryanhcode/sable/mixinterface/compatibility/iris/ExtendedShaderExtension.java @@ -0,0 +1,5 @@ +package dev.ryanhcode.sable.mixinterface.compatibility.iris; + +public interface ExtendedShaderExtension { + void sable$refreshModelViewDerivedMatrices(); +} diff --git a/common/src/main/java/dev/ryanhcode/sable/sublevel/render/vanilla/VanillaChunkedSubLevelRenderData.java b/common/src/main/java/dev/ryanhcode/sable/sublevel/render/vanilla/VanillaChunkedSubLevelRenderData.java index c291fbc..606126e 100644 --- a/common/src/main/java/dev/ryanhcode/sable/sublevel/render/vanilla/VanillaChunkedSubLevelRenderData.java +++ b/common/src/main/java/dev/ryanhcode/sable/sublevel/render/vanilla/VanillaChunkedSubLevelRenderData.java @@ -9,6 +9,7 @@ import dev.ryanhcode.sable.companion.math.JOMLConversion; import dev.ryanhcode.sable.companion.math.Pose3dc; import dev.ryanhcode.sable.mixin.sublevel_render.RenderSectionAccessor; +import dev.ryanhcode.sable.mixinterface.compatibility.iris.ExtendedShaderExtension; import dev.ryanhcode.sable.mixinterface.sublevel_render.vanilla.RenderSectionExtension; import dev.ryanhcode.sable.sublevel.ClientSubLevel; import dev.ryanhcode.sable.sublevel.render.SubLevelRenderData; @@ -319,6 +320,10 @@ public void renderChunkedSubLevel(final RenderType layer, final ShaderInstance s if (shader.MODEL_VIEW_MATRIX != null) { shader.MODEL_VIEW_MATRIX.set(modelView.mul(transform, MODEL_MATRIX)); shader.MODEL_VIEW_MATRIX.upload(); + + if (shader instanceof final ExtendedShaderExtension ext) { + ext.sable$refreshModelViewDerivedMatrices(); + } } // TODO: sorting diff --git a/common/src/main/resources/sable.mixins.json b/common/src/main/resources/sable.mixins.json index d1e1db1..b37909c 100644 --- a/common/src/main/resources/sable.mixins.json +++ b/common/src/main/resources/sable.mixins.json @@ -16,6 +16,7 @@ "camera.new_camera_types.MinecraftMixin", "clip_overwrite.ClientLevelMixin", "clip_overwrite.GameRendererMixin", + "compatibility.iris.ExtendedShaderMixin", "config.GameRendererAccessor", "debug_render.DebugRendererMixin", "debug_render.DebugScreenOverlayMixin",