From 867c16983085b06438fc74a86a36be557af28d29 Mon Sep 17 00:00:00 2001 From: wisplite Date: Fri, 12 Jun 2026 18:50:02 -0500 Subject: [PATCH] fix rendering with shaders as much as i can --- .../compat/iris/IrisHelpers.java | 21 +++++++ .../compat/sodium/SkyShaderInterface.java | 11 +++- .../compat/sodium/SkyboxShaderInterface.java | 5 ++ .../mixin/client/LevelRendererMixin.java | 57 +++++++++++++++---- .../client/LevelRendererRenderSkyMixin.java | 18 ++++++ .../compat/iris/FallbackShaderMixin.java | 22 +++++++ .../compat/iris/SodiumProgramsMixin.java | 9 +++ .../util/SharedRenderVariables.java | 13 +++++ .../crystalline_sky-common.mixins.json | 1 + 9 files changed, 144 insertions(+), 13 deletions(-) create mode 100644 common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/compat/iris/FallbackShaderMixin.java diff --git a/common/src/main/java/io/github/slimeistdev/crystalline_sky/compat/iris/IrisHelpers.java b/common/src/main/java/io/github/slimeistdev/crystalline_sky/compat/iris/IrisHelpers.java index 269c461..20f8ca5 100644 --- a/common/src/main/java/io/github/slimeistdev/crystalline_sky/compat/iris/IrisHelpers.java +++ b/common/src/main/java/io/github/slimeistdev/crystalline_sky/compat/iris/IrisHelpers.java @@ -8,10 +8,31 @@ import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.irisshaders.iris.Iris; import net.irisshaders.iris.pipeline.IrisRenderingPipeline; +import net.irisshaders.iris.pipeline.WorldRenderingPhase; import net.irisshaders.iris.targets.RenderTargets; +import net.irisshaders.iris.vertices.ImmediateState; @Environment(EnvType.CLIENT) public class IrisHelpers { + public static boolean isShaderpackPipelineActive() { + return Iris.getPipelineManager().getPipelineNullable() instanceof IrisRenderingPipeline; + } + + public static void pushVanillaShaders() { + ImmediateState.bypass = true; + } + + public static void popVanillaShaders() { + ImmediateState.bypass = false; + } + + public static void resetRenderingPhase() { + var pipeline = Iris.getPipelineManager().getPipelineNullable(); + if (pipeline instanceof IrisRenderingPipeline irisPipeline) { + irisPipeline.setPhase(WorldRenderingPhase.NONE); + } + } + public static boolean copySkyToBuffer(RenderTarget skyBuffer) { var pipeline = Iris.getPipelineManager().getPipelineNullable(); if (!(pipeline instanceof IrisRenderingPipeline irisPipeline)) return false; diff --git a/common/src/main/java/io/github/slimeistdev/crystalline_sky/compat/sodium/SkyShaderInterface.java b/common/src/main/java/io/github/slimeistdev/crystalline_sky/compat/sodium/SkyShaderInterface.java index c3c4e6d..c02b3e5 100644 --- a/common/src/main/java/io/github/slimeistdev/crystalline_sky/compat/sodium/SkyShaderInterface.java +++ b/common/src/main/java/io/github/slimeistdev/crystalline_sky/compat/sodium/SkyShaderInterface.java @@ -1,6 +1,8 @@ package io.github.slimeistdev.crystalline_sky.compat.sodium; import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.systems.RenderSystem; +import io.github.slimeistdev.crystalline_sky.mixin_ducks.client.LevelRenderer_Duck; import io.github.slimeistdev.crystalline_sky.registry.CrystallineItems; import net.caffeinemc.mods.sodium.client.gl.shader.uniform.GlUniformFloat3v; import net.caffeinemc.mods.sodium.client.gl.shader.uniform.GlUniformFloat4v; @@ -11,7 +13,6 @@ import net.caffeinemc.mods.sodium.client.render.chunk.shader.ChunkShaderInterfac import net.caffeinemc.mods.sodium.client.render.chunk.shader.ChunkShaderOptions; import net.caffeinemc.mods.sodium.client.render.chunk.shader.ChunkShaderTextureSlot; import net.caffeinemc.mods.sodium.client.render.chunk.shader.ShaderBindingContext; -import net.caffeinemc.mods.sodium.client.util.TextureUtil; import net.minecraft.client.Minecraft; import net.minecraft.util.Mth; import org.joml.Matrix4fc; @@ -46,9 +47,14 @@ public class SkyShaderInterface implements ChunkShaderInterface { this.fogShader = options.fog().getFactory().apply(context); } + protected int getBoundTextureId() { + var fb = ((LevelRenderer_Duck) Minecraft.getInstance().levelRenderer).crystalline_sky$getSkyFramebuffer(); + return fb.getColorTextureId(); + } + @Override public void setupState() { - this.bindTexture(ChunkShaderTextureSlot.BLOCK, TextureUtil.getBlockTextureId()); + this.bindTexture(ChunkShaderTextureSlot.BLOCK, getBoundTextureId()); Minecraft client = Minecraft.getInstance(); if (client.level != null @@ -80,6 +86,7 @@ public class SkyShaderInterface implements ChunkShaderInterface { forRemoval = true ) private void bindTexture(ChunkShaderTextureSlot slot, int textureId) { + RenderSystem.setShaderTexture(slot.ordinal(), textureId); GlStateManager._activeTexture(GL32C.GL_TEXTURE0 + slot.ordinal()); GlStateManager._bindTexture(textureId); GlUniformInt uniform = this.uniformTextures.get(slot); diff --git a/common/src/main/java/io/github/slimeistdev/crystalline_sky/compat/sodium/SkyboxShaderInterface.java b/common/src/main/java/io/github/slimeistdev/crystalline_sky/compat/sodium/SkyboxShaderInterface.java index fadaf99..ec773b4 100644 --- a/common/src/main/java/io/github/slimeistdev/crystalline_sky/compat/sodium/SkyboxShaderInterface.java +++ b/common/src/main/java/io/github/slimeistdev/crystalline_sky/compat/sodium/SkyboxShaderInterface.java @@ -34,4 +34,9 @@ public class SkyboxShaderInterface extends SkyShaderInterface { ); } } + + @Override + protected int getBoundTextureId() { + return Minecraft.getInstance().getTextureManager().getTexture(CrystallineAtlases.SKYBOXES.texture).getId(); + } } diff --git a/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/LevelRendererMixin.java b/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/LevelRendererMixin.java index d1cdaca..6405ba9 100644 --- a/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/LevelRendererMixin.java +++ b/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/LevelRendererMixin.java @@ -2,6 +2,8 @@ package io.github.slimeistdev.crystalline_sky.mixin.client; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.mojang.blaze3d.platform.GlConst; +import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.pipeline.RenderTarget; import com.mojang.blaze3d.pipeline.TextureTarget; import com.mojang.blaze3d.systems.RenderSystem; @@ -63,6 +65,7 @@ public abstract class LevelRendererMixin implements LevelRenderer_Duck { if (crystalline_sky$skyBuffer == null) { var fb = minecraft.getMainRenderTarget(); crystalline_sky$skyBuffer = new TextureTarget(fb.width, fb.height, true, Minecraft.ON_OSX); + crystalline_sky$configureSkyBufferTexture(); } return crystalline_sky$skyBuffer; } @@ -86,6 +89,7 @@ public abstract class LevelRendererMixin implements LevelRenderer_Duck { private void resizeSkyBuffer(int width, int height, CallbackInfo ci) { if (crystalline_sky$skyBuffer != null) { crystalline_sky$skyBuffer.resize(width, height, Minecraft.ON_OSX); + crystalline_sky$configureSkyBufferTexture(); } } @@ -108,27 +112,31 @@ public abstract class LevelRendererMixin implements LevelRenderer_Duck { private void copyAfterSky(DeltaTracker tickCounter, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightTexture lightmapTextureManager, Matrix4f matrix4f, Matrix4f matrix4f2, CallbackInfo ci) { - var skyBuffer = crystalline_sky$getSkyFramebuffer(); - skyBuffer.clear(Minecraft.ON_OSX); - float partialTick = tickCounter.getGameTimeDeltaPartialTick(false); - if (crystalline_sky$isBelowHorizon(partialTick)) { + if (crystalline_sky$isBelowHorizon(partialTick) + || Mods.IRIS.runIfInstalled(() -> IrisHelpers::isShaderpackPipelineActive).orElse(false)) { + var skyBuffer = crystalline_sky$getSkyFramebuffer(); + skyBuffer.clear(Minecraft.ON_OSX); crystalline_sky$renderSkyBuffer(skyBuffer, tickCounter, camera, gameRenderer, matrix4f, matrix4f2); } else { - var copiedFromIris = Mods.IRIS.runIfInstalled(() -> () -> IrisHelpers.copySkyToBuffer(skyBuffer)); - if (!copiedFromIris.orElse(false)) - ((RenderTarget_Duck) skyBuffer).crystalline_sky$copyColorFrom(minecraft.getMainRenderTarget()); + var skyBuffer = crystalline_sky$getSkyFramebuffer(); + skyBuffer.clear(Minecraft.ON_OSX); + ((RenderTarget_Duck) skyBuffer).crystalline_sky$copyColorFrom(minecraft.getMainRenderTarget()); } + // Iris shader packs replace cloud rendering; baking them into the sky buffer causes artifacts. + boolean irisShaderpackActive = Mods.IRIS.runIfInstalled(() -> IrisHelpers::isShaderpackPipelineActive).orElse(false); + // render clouds CloudStatus cloudRenderMode = this.minecraft.options.getCloudsType(); - if (cloudRenderMode != CloudStatus.OFF && !this.doesMobEffectBlockSky(camera)) { + if (cloudRenderMode != CloudStatus.OFF && !irisShaderpackActive && !this.doesMobEffectBlockSky(camera)) { float f = tickCounter.getGameTimeDeltaPartialTick(false); Vec3 vec3d = camera.getPosition(); double cx = vec3d.x(); double cy = vec3d.y(); double cz = vec3d.z(); + var skyBuffer = crystalline_sky$getSkyFramebuffer(); var cloudsFramebuffer0 = this.cloudsTarget; this.cloudsTarget = skyBuffer; cloudsTarget.bindWrite(false); @@ -156,6 +164,18 @@ public abstract class LevelRendererMixin implements LevelRenderer_Duck { renderSectionLayer(CrystallineRenderTypes.SKYBOX, x, y, z, matrix4f, positionMatrix); } + @Unique + private void crystalline_sky$configureSkyBufferTexture() { + if (crystalline_sky$skyBuffer == null) { + return; + } + + RenderSystem.assertOnRenderThreadOrInit(); + GlStateManager._bindTexture(crystalline_sky$skyBuffer.getColorTextureId()); + GlStateManager._texParameter(GlConst.GL_TEXTURE_2D, GlConst.GL_TEXTURE_WRAP_S, GlConst.GL_CLAMP_TO_EDGE); + GlStateManager._texParameter(GlConst.GL_TEXTURE_2D, GlConst.GL_TEXTURE_WRAP_T, GlConst.GL_CLAMP_TO_EDGE); + } + @Unique private boolean crystalline_sky$isBelowHorizon(float partialTick) { var level = minecraft.level; @@ -185,7 +205,14 @@ public abstract class LevelRendererMixin implements LevelRenderer_Duck { || minecraft.gui.getBossOverlay().shouldCreateWorldFog(); skyBuffer.bindWrite(false); - SharedRenderVariables.pushSkipVoidSky(); + RenderSystem.viewport(0, 0, skyBuffer.width, skyBuffer.height); + SharedRenderVariables.pushCapturingSkyBuffer(); + boolean belowHorizon = crystalline_sky$isBelowHorizon(partialTick); + if (belowHorizon) { + SharedRenderVariables.pushSkipVoidSky(); + } + SharedRenderVariables.pushBlockIrisShaderFramebufferBind(); + Mods.IRIS.executeIfInstalled(() -> IrisHelpers::pushVanillaShaders); try { FogRenderer.setupColor( camera, @@ -207,8 +234,16 @@ public abstract class LevelRendererMixin implements LevelRenderer_Duck { () -> FogRenderer.setupFog(camera, FogRenderer.FogMode.FOG_SKY, renderDistance, isFoggy, partialTick) ); } finally { - SharedRenderVariables.popSkipVoidSky(); - minecraft.getMainRenderTarget().bindWrite(false); + Mods.IRIS.executeIfInstalled(() -> IrisHelpers::popVanillaShaders); + SharedRenderVariables.popBlockIrisShaderFramebufferBind(); + if (belowHorizon) { + SharedRenderVariables.popSkipVoidSky(); + } + SharedRenderVariables.popCapturingSkyBuffer(); + Mods.IRIS.executeIfInstalled(() -> IrisHelpers::resetRenderingPhase); + var main = minecraft.getMainRenderTarget(); + main.bindWrite(false); + RenderSystem.viewport(0, 0, main.width, main.height); } } } diff --git a/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/LevelRendererRenderSkyMixin.java b/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/LevelRendererRenderSkyMixin.java index 5fdfaef..12f21f5 100644 --- a/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/LevelRendererRenderSkyMixin.java +++ b/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/LevelRendererRenderSkyMixin.java @@ -2,12 +2,17 @@ package io.github.slimeistdev.crystalline_sky.mixin.client; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.mojang.blaze3d.platform.GlConst; +import com.mojang.blaze3d.systems.RenderSystem; import io.github.slimeistdev.crystalline_sky.util.SharedRenderVariables; +import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.world.level.LevelHeightAccessor; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(value = LevelRenderer.class, remap = false) public class LevelRendererRenderSkyMixin { @@ -29,4 +34,17 @@ public class LevelRendererRenderSkyMixin { return original.call(levelData, level); } + + @Inject( + method = "renderSky", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/client/multiplayer/ClientLevel;getStarBrightness(F)F" + ) + ) + private void crystalline_sky$clearDepthBeforeStars(CallbackInfo ci) { + if (SharedRenderVariables.isCapturingSkyBuffer()) { + RenderSystem.clear(GlConst.GL_DEPTH_BUFFER_BIT, Minecraft.ON_OSX); + } + } } diff --git a/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/compat/iris/FallbackShaderMixin.java b/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/compat/iris/FallbackShaderMixin.java new file mode 100644 index 0000000..40d37cc --- /dev/null +++ b/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/compat/iris/FallbackShaderMixin.java @@ -0,0 +1,22 @@ +package io.github.slimeistdev.crystalline_sky.mixin.client.compat.iris; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import io.github.slimeistdev.crystalline_sky.annotation.mixin.ConditionalMixin; +import io.github.slimeistdev.crystalline_sky.compat.Mods; +import io.github.slimeistdev.crystalline_sky.util.SharedRenderVariables; +import net.irisshaders.iris.gl.framebuffer.GlFramebuffer; +import net.irisshaders.iris.pipeline.programs.FallbackShader; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@ConditionalMixin(mods = Mods.IRIS) +@Mixin(FallbackShader.class) +public class FallbackShaderMixin { + @WrapOperation(method = "apply", at = @At(value = "INVOKE", target = "Lnet/irisshaders/iris/gl/framebuffer/GlFramebuffer;bind()V")) + private void skipBind(GlFramebuffer instance, Operation original) { + if (!SharedRenderVariables.shouldBlockIrisShaderFramebufferBind()) { + original.call(instance); + } + } +} diff --git a/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/compat/iris/SodiumProgramsMixin.java b/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/compat/iris/SodiumProgramsMixin.java index 2f09c50..89d8cfe 100644 --- a/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/compat/iris/SodiumProgramsMixin.java +++ b/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/compat/iris/SodiumProgramsMixin.java @@ -4,6 +4,7 @@ import io.github.slimeistdev.crystalline_sky.annotation.mixin.ConditionalMixin; import io.github.slimeistdev.crystalline_sky.compat.Mods; import io.github.slimeistdev.crystalline_sky.mixin.client.compat.sodium.TerrainRenderPassAccessor; import io.github.slimeistdev.crystalline_sky.registry.client.CrystallineRenderTypes; +import net.caffeinemc.mods.sodium.client.gl.shader.GlProgram; import net.caffeinemc.mods.sodium.client.render.chunk.terrain.TerrainRenderPass; import net.irisshaders.iris.pipeline.programs.SodiumPrograms; import net.irisshaders.iris.shadows.ShadowRenderingState; @@ -23,4 +24,12 @@ public class SodiumProgramsMixin { cir.setReturnValue(ShadowRenderingState.areShadowsCurrentlyBeingRendered() ? SodiumPrograms.Pass.SHADOW : SodiumPrograms.Pass.TERRAIN); } } + + @Inject(method = "getProgram", at = @At("HEAD"), cancellable = true) + private void crystalline_sky$useCustomSkyShader(TerrainRenderPass pass, CallbackInfoReturnable> cir) { + RenderType renderType = ((TerrainRenderPassAccessor) pass).crystalline_sky$getRenderLayer(); + if (renderType == CrystallineRenderTypes.SKY || renderType == CrystallineRenderTypes.SKYBOX) { + cir.setReturnValue(null); + } + } } diff --git a/common/src/main/java/io/github/slimeistdev/crystalline_sky/util/SharedRenderVariables.java b/common/src/main/java/io/github/slimeistdev/crystalline_sky/util/SharedRenderVariables.java index bc561f6..c7cd3c7 100644 --- a/common/src/main/java/io/github/slimeistdev/crystalline_sky/util/SharedRenderVariables.java +++ b/common/src/main/java/io/github/slimeistdev/crystalline_sky/util/SharedRenderVariables.java @@ -9,6 +9,19 @@ public class SharedRenderVariables { public static final ThreadLocal shadeFullBright = ThreadLocal.withInitial(() -> new MutableInt(0)); private static int blockIrisShaderFramebufferBind = 0; private static int skipVoidSky = 0; + private static int capturingSkyBuffer = 0; + + public static boolean isCapturingSkyBuffer() { + return capturingSkyBuffer > 0; + } + + public static void pushCapturingSkyBuffer() { + capturingSkyBuffer++; + } + + public static void popCapturingSkyBuffer() { + capturingSkyBuffer--; + } public static boolean shouldShadeFullBright() { return shadeFullBright.get().intValue() > 0; diff --git a/common/src/main/resources/crystalline_sky-common.mixins.json b/common/src/main/resources/crystalline_sky-common.mixins.json index bba841e..f002de2 100644 --- a/common/src/main/resources/crystalline_sky-common.mixins.json +++ b/common/src/main/resources/crystalline_sky-common.mixins.json @@ -27,6 +27,7 @@ "client.RenderTargetMixin", "client.TextureAtlasAccessor", "client.compat.iris.ExtendedShaderMixin", + "client.compat.iris.FallbackShaderMixin", "client.compat.iris.IrisRenderingPipelineAccessor", "client.compat.iris.IrisRenderingPipelineMixin", "client.compat.iris.SodiumProgramsMixin",