fix rendering with shaders as much as i can

This commit is contained in:
wisplite
2026-06-12 18:50:02 -05:00
parent 75e0a72d89
commit 867c169830
9 changed files with 144 additions and 13 deletions
@@ -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;
@@ -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);
@@ -34,4 +34,9 @@ public class SkyboxShaderInterface extends SkyShaderInterface {
);
}
}
@Override
protected int getBoundTextureId() {
return Minecraft.getInstance().getTextureManager().getTexture(CrystallineAtlases.SKYBOXES.texture).getId();
}
}
@@ -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) {
float partialTick = tickCounter.getGameTimeDeltaPartialTick(false);
if (crystalline_sky$isBelowHorizon(partialTick)
|| Mods.IRIS.runIfInstalled(() -> IrisHelpers::isShaderpackPipelineActive).orElse(false)) {
var skyBuffer = crystalline_sky$getSkyFramebuffer();
skyBuffer.clear(Minecraft.ON_OSX);
float partialTick = tickCounter.getGameTimeDeltaPartialTick(false);
if (crystalline_sky$isBelowHorizon(partialTick)) {
crystalline_sky$renderSkyBuffer(skyBuffer, tickCounter, camera, gameRenderer, matrix4f, matrix4f2);
} else {
var copiedFromIris = Mods.IRIS.runIfInstalled(() -> () -> IrisHelpers.copySkyToBuffer(skyBuffer));
if (!copiedFromIris.orElse(false))
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);
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 {
Mods.IRIS.executeIfInstalled(() -> IrisHelpers::popVanillaShaders);
SharedRenderVariables.popBlockIrisShaderFramebufferBind();
if (belowHorizon) {
SharedRenderVariables.popSkipVoidSky();
minecraft.getMainRenderTarget().bindWrite(false);
}
SharedRenderVariables.popCapturingSkyBuffer();
Mods.IRIS.executeIfInstalled(() -> IrisHelpers::resetRenderingPhase);
var main = minecraft.getMainRenderTarget();
main.bindWrite(false);
RenderSystem.viewport(0, 0, main.width, main.height);
}
}
}
@@ -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);
}
}
}
@@ -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<Void> original) {
if (!SharedRenderVariables.shouldBlockIrisShaderFramebufferBind()) {
original.call(instance);
}
}
}
@@ -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<GlProgram<?>> cir) {
RenderType renderType = ((TerrainRenderPassAccessor) pass).crystalline_sky$getRenderLayer();
if (renderType == CrystallineRenderTypes.SKY || renderType == CrystallineRenderTypes.SKYBOX) {
cir.setReturnValue(null);
}
}
}
@@ -9,6 +9,19 @@ public class SharedRenderVariables {
public static final ThreadLocal<MutableInt> 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;
@@ -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",