From 23977a3b3a4099cc52a162089cb959dd9573f8c3 Mon Sep 17 00:00:00 2001 From: techno-sam <77073745+techno-sam@users.noreply.github.com> Date: Wed, 27 Aug 2025 00:19:53 +0200 Subject: [PATCH] implement sky rendering --- build.gradle | 19 ++ libs.versions.toml | 2 + .../crystalline_sky/CrystallineSkyClient.java | 13 ++ .../extenders_cove/BlockRenderLayerExt.java | 11 ++ .../BlockRenderLayerGroupExt.java | 8 + .../CrystallineSkyEarlyRiser.java | 16 ++ .../CrystallineSkyEarlyRiserClient.java | 38 ++++ .../mixin/client/BlockRenderLayerMixin.java | 28 +++ .../mixin/client/ClientWorldMixin.java | 21 ++- .../client/DefaultFramebufferSetMixin.java | 49 ++++++ .../mixin/client/FramebufferMixin.java | 36 ++++ .../mixin/client/WorldRendererAccessor.java | 12 ++ .../mixin/client/WorldRendererMixin.java | 166 ++++++++++++++++++ .../client/DefaultFramebufferSet_Duck.java | 13 ++ .../mixin_ducks/client/Framebuffer_Duck.java | 7 + .../registry/CrystallineBlocks.java | 3 +- .../client/CrystallineRenderPipelines.java | 18 ++ .../shaders/core/terrain_sky.fsh | 22 +++ .../shaders/core/terrain_sky.vsh | 26 +++ .../resources/crystalline_sky.mixins.json | 7 +- src/main/resources/fabric.mod.json | 4 + 21 files changed, 510 insertions(+), 9 deletions(-) create mode 100644 src/main/java/io/github/slimeistdev/crystalline_sky/CrystallineSkyClient.java create mode 100644 src/main/java/io/github/slimeistdev/crystalline_sky/extenders_cove/BlockRenderLayerExt.java create mode 100644 src/main/java/io/github/slimeistdev/crystalline_sky/extenders_cove/BlockRenderLayerGroupExt.java create mode 100644 src/main/java/io/github/slimeistdev/crystalline_sky/extenders_cove/CrystallineSkyEarlyRiser.java create mode 100644 src/main/java/io/github/slimeistdev/crystalline_sky/extenders_cove/CrystallineSkyEarlyRiserClient.java create mode 100644 src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/BlockRenderLayerMixin.java create mode 100644 src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/DefaultFramebufferSetMixin.java create mode 100644 src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/FramebufferMixin.java create mode 100644 src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/WorldRendererAccessor.java create mode 100644 src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/WorldRendererMixin.java create mode 100644 src/main/java/io/github/slimeistdev/crystalline_sky/mixin_ducks/client/DefaultFramebufferSet_Duck.java create mode 100644 src/main/java/io/github/slimeistdev/crystalline_sky/mixin_ducks/client/Framebuffer_Duck.java create mode 100644 src/main/java/io/github/slimeistdev/crystalline_sky/registry/client/CrystallineRenderPipelines.java create mode 100644 src/main/resources/assets/crystalline_sky/shaders/core/terrain_sky.fsh create mode 100644 src/main/resources/assets/crystalline_sky/shaders/core/terrain_sky.vsh diff --git a/build.gradle b/build.gradle index c19d249..bd19fe2 100644 --- a/build.gradle +++ b/build.gradle @@ -36,6 +36,19 @@ repositories { includeGroup "com.terraformersmc" } } + exclusiveContent { // Fabric ASM + //"https://jitpack.io/" + forRepository { + //noinspection ForeignDelegate + maven { + name 'JitPack (Manningham Mills)' + url "https://jitpack.io/" + } + } + filter { + includeGroup "com.github.Chocohead" + } + } } dependencies { @@ -48,6 +61,12 @@ dependencies { modImplementation libs.fl modImplementation libs.fapi + // Fabric ASM (enum extension etc) + modImplementation(libs.manningham) { + exclude (group: "net.fabricmc.fabric-api") + } + include libs.manningham + if (!inCI) { modRuntimeOnly libs.mm } diff --git a/libs.versions.toml b/libs.versions.toml index b5461ed..0ba7e40 100644 --- a/libs.versions.toml +++ b/libs.versions.toml @@ -8,6 +8,7 @@ yarn = "1.21.8+build.1" fapi = "0.130.0+1.21.8" mixinextras = "0.5.0" mm = "15.0.0-beta.3" +manningham = "v2.3" [plugins] loom = { id = "fabric-loom", version.ref = "loom" } @@ -20,3 +21,4 @@ yarn = { group = "net.fabricmc", name = "yarn", version.ref = "yarn" } fapi = { group = "net.fabricmc.fabric-api", name = "fabric-api", version.ref = "fapi" } mixinextras = { group = "io.github.llamalad7", name = "mixinextras-fabric", version.ref = "mixinextras" } mm = { group = "com.terraformersmc", name = "modmenu", version.ref = "mm" } +manningham = { group = "com.github.Chocohead", name = "Fabric-ASM", version.ref = "manningham" } diff --git a/src/main/java/io/github/slimeistdev/crystalline_sky/CrystallineSkyClient.java b/src/main/java/io/github/slimeistdev/crystalline_sky/CrystallineSkyClient.java new file mode 100644 index 0000000..e0b3260 --- /dev/null +++ b/src/main/java/io/github/slimeistdev/crystalline_sky/CrystallineSkyClient.java @@ -0,0 +1,13 @@ +package io.github.slimeistdev.crystalline_sky; + +import io.github.slimeistdev.crystalline_sky.extenders_cove.BlockRenderLayerExt; +import io.github.slimeistdev.crystalline_sky.registry.CrystallineBlocks; +import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.fabric.api.client.rendering.v1.BlockRenderLayerMap; + +public class CrystallineSkyClient implements ClientModInitializer { + @Override + public void onInitializeClient() { + BlockRenderLayerMap.putBlock(CrystallineBlocks.SKY, BlockRenderLayerExt.CRYSTALLINE_SKY_SKY); + } +} diff --git a/src/main/java/io/github/slimeistdev/crystalline_sky/extenders_cove/BlockRenderLayerExt.java b/src/main/java/io/github/slimeistdev/crystalline_sky/extenders_cove/BlockRenderLayerExt.java new file mode 100644 index 0000000..ee62f4c --- /dev/null +++ b/src/main/java/io/github/slimeistdev/crystalline_sky/extenders_cove/BlockRenderLayerExt.java @@ -0,0 +1,11 @@ +package io.github.slimeistdev.crystalline_sky.extenders_cove; + +import com.chocohead.mm.api.ClassTinkerers; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.render.BlockRenderLayer; + +public class BlockRenderLayerExt { + @Environment(EnvType.CLIENT) + public static final BlockRenderLayer CRYSTALLINE_SKY_SKY = ClassTinkerers.getEnum(BlockRenderLayer.class, "CRYSTALLINE_SKY_SKY"); +} diff --git a/src/main/java/io/github/slimeistdev/crystalline_sky/extenders_cove/BlockRenderLayerGroupExt.java b/src/main/java/io/github/slimeistdev/crystalline_sky/extenders_cove/BlockRenderLayerGroupExt.java new file mode 100644 index 0000000..1dfd7b4 --- /dev/null +++ b/src/main/java/io/github/slimeistdev/crystalline_sky/extenders_cove/BlockRenderLayerGroupExt.java @@ -0,0 +1,8 @@ +package io.github.slimeistdev.crystalline_sky.extenders_cove; + +import com.chocohead.mm.api.ClassTinkerers; +import net.minecraft.client.render.BlockRenderLayerGroup; + +public class BlockRenderLayerGroupExt { + public static final BlockRenderLayerGroup CRYSTALLINE_SKY_SKY = ClassTinkerers.getEnum(BlockRenderLayerGroup.class, "CRYSTALLINE_SKY_SKY"); +} diff --git a/src/main/java/io/github/slimeistdev/crystalline_sky/extenders_cove/CrystallineSkyEarlyRiser.java b/src/main/java/io/github/slimeistdev/crystalline_sky/extenders_cove/CrystallineSkyEarlyRiser.java new file mode 100644 index 0000000..ecd4ead --- /dev/null +++ b/src/main/java/io/github/slimeistdev/crystalline_sky/extenders_cove/CrystallineSkyEarlyRiser.java @@ -0,0 +1,16 @@ +package io.github.slimeistdev.crystalline_sky.extenders_cove; + +import net.fabricmc.api.EnvType; +import net.fabricmc.loader.api.FabricLoader; + +import java.util.function.Supplier; + +public class CrystallineSkyEarlyRiser implements Runnable { + @Override + @SuppressWarnings({"Convert2MethodRef", "TrivialFunctionalExpressionUsage"}) + public void run() { + if (FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) { + ((Supplier) (() -> () -> CrystallineSkyEarlyRiserClient.runClient())).get().run(); + } + } +} diff --git a/src/main/java/io/github/slimeistdev/crystalline_sky/extenders_cove/CrystallineSkyEarlyRiserClient.java b/src/main/java/io/github/slimeistdev/crystalline_sky/extenders_cove/CrystallineSkyEarlyRiserClient.java new file mode 100644 index 0000000..cd0953c --- /dev/null +++ b/src/main/java/io/github/slimeistdev/crystalline_sky/extenders_cove/CrystallineSkyEarlyRiserClient.java @@ -0,0 +1,38 @@ +package io.github.slimeistdev.crystalline_sky.extenders_cove; + +import com.chocohead.mm.api.ClassTinkerers; +import io.github.slimeistdev.crystalline_sky.registry.client.CrystallineRenderPipelines; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.loader.api.FabricLoader; +import net.fabricmc.loader.api.MappingResolver; +import net.minecraft.client.render.BlockRenderLayer; + +class CrystallineSkyEarlyRiserClient { + @Environment(EnvType.CLIENT) + static void runClient() { + MappingResolver remapper = FabricLoader.getInstance().getMappingResolver(); + + // net.minecraft.client.render.BlockRenderLayer + String blockRenderLayer = remapper.mapClassName("intermediary", "net.minecraft.class_11515"); + + // RenderPipeline is not obfuscated + ClassTinkerers.enumBuilder(blockRenderLayer, "Lcom/mojang/blaze3d/pipeline/RenderPipeline;", "I", "Z", "Z") + .addEnum("CRYSTALLINE_SKY_SKY", () -> new Object[]{ + CrystallineRenderPipelines.SKY_PIPELINE, + 1536, + false, + false + }) + .build(); + + // net.minecraft.client.render.BlockRenderLayerGroup + String blockRenderLayerGroup = remapper.mapClassName("intermediary", "net.minecraft.class_11531"); + + ClassTinkerers.enumBuilder(blockRenderLayerGroup, "[L"+blockRenderLayer+";") + .addEnum("CRYSTALLINE_SKY_SKY", () -> new Object[] { + new BlockRenderLayer[] {BlockRenderLayerExt.CRYSTALLINE_SKY_SKY} + }) + .build(); + } +} diff --git a/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/BlockRenderLayerMixin.java b/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/BlockRenderLayerMixin.java new file mode 100644 index 0000000..78fec1a --- /dev/null +++ b/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/BlockRenderLayerMixin.java @@ -0,0 +1,28 @@ +package io.github.slimeistdev.crystalline_sky.mixin.client; + +import com.mojang.blaze3d.textures.GpuTextureView; +import io.github.slimeistdev.crystalline_sky.extenders_cove.BlockRenderLayerExt; +import io.github.slimeistdev.crystalline_sky.mixin_ducks.client.DefaultFramebufferSet_Duck; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gl.Framebuffer; +import net.minecraft.client.render.BlockRenderLayer; +import net.minecraft.client.render.DefaultFramebufferSet; +import net.minecraft.client.util.Handle; +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.CallbackInfoReturnable; + +@Mixin(BlockRenderLayer.class) +public class BlockRenderLayerMixin { + @Inject(method = "getTextureView", at = @At("HEAD"), cancellable = true) + private void shatterTheSky(CallbackInfoReturnable cir) { + if (((Object) this) == BlockRenderLayerExt.CRYSTALLINE_SKY_SKY) { + MinecraftClient mc = MinecraftClient.getInstance(); + DefaultFramebufferSet framebuffers = ((WorldRendererAccessor) mc.worldRenderer).crystalline_sky$getFramebufferSet(); + Handle skyFramebuffer = ((DefaultFramebufferSet_Duck) framebuffers).crystalline_sky$getSkyFramebuffer(); + + cir.setReturnValue(skyFramebuffer.get().getColorAttachmentView()); + } + } +} diff --git a/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/ClientWorldMixin.java b/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/ClientWorldMixin.java index 9942e2f..08e8f63 100644 --- a/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/ClientWorldMixin.java +++ b/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/ClientWorldMixin.java @@ -1,22 +1,29 @@ package io.github.slimeistdev.crystalline_sky.mixin.client; -import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import io.github.slimeistdev.crystalline_sky.registry.CrystallineItems; import net.minecraft.client.world.ClientWorld; import net.minecraft.item.Item; -import org.objectweb.asm.Opcodes; +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.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.util.HashSet; import java.util.Set; @Mixin(ClientWorld.class) public class ClientWorldMixin { - @ModifyExpressionValue(method = "", at = @At(value = "FIELD", target = "Lnet/minecraft/client/world/ClientWorld;BLOCK_MARKER_ITEMS:Ljava/util/Set;", opcode = Opcodes.PUTSTATIC)) - private static Set modifyBlockMarkerItems(Set original) { - Set extended = new HashSet<>(original); - extended.add(CrystallineItems.SKY_LIGHT); - return Set.copyOf(extended); + @Shadow + @Final + @Mutable + private static Set BLOCK_MARKER_ITEMS; + + @Inject(method = "", at = @At("RETURN")) + private static void modifyBlockMarkerItems(CallbackInfo ci) { + BLOCK_MARKER_ITEMS = new HashSet<>(BLOCK_MARKER_ITEMS); + BLOCK_MARKER_ITEMS.add(CrystallineItems.SKY_LIGHT); } } diff --git a/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/DefaultFramebufferSetMixin.java b/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/DefaultFramebufferSetMixin.java new file mode 100644 index 0000000..c1de328 --- /dev/null +++ b/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/DefaultFramebufferSetMixin.java @@ -0,0 +1,49 @@ +package io.github.slimeistdev.crystalline_sky.mixin.client; + +import io.github.slimeistdev.crystalline_sky.mixin_ducks.client.DefaultFramebufferSet_Duck; +import net.minecraft.client.gl.Framebuffer; +import net.minecraft.client.render.DefaultFramebufferSet; +import net.minecraft.client.util.Handle; +import net.minecraft.util.Identifier; +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(DefaultFramebufferSet.class) +public class DefaultFramebufferSetMixin implements DefaultFramebufferSet_Duck { + @Unique + private Handle crystalline_sky$skyFramebuffer = Handle.empty(); + + @Override + public Handle crystalline_sky$getSkyFramebuffer() { + return crystalline_sky$skyFramebuffer; + } + + @Override + public void crystalline_sky$setSkyFramebuffer(Handle framebuffer) { + crystalline_sky$skyFramebuffer = framebuffer; + } + + @Inject(method = "set", at = @At("HEAD"), cancellable = true) + private void setSky(Identifier id, Handle framebuffer, CallbackInfo ci) { + if (id.equals(crystalline_sky$SKY_FRAMEBUFFER)) { + crystalline_sky$skyFramebuffer = framebuffer; + ci.cancel(); + } + } + + @Inject(method = "get", at = @At("HEAD"), cancellable = true) + private void getSky(Identifier id, CallbackInfoReturnable> cir) { + if (id.equals(crystalline_sky$SKY_FRAMEBUFFER)) { + cir.setReturnValue(crystalline_sky$skyFramebuffer); + } + } + + @Inject(method = "clear", at = @At("HEAD")) + private void clearSky(CallbackInfo ci) { + crystalline_sky$skyFramebuffer = Handle.empty(); + } +} diff --git a/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/FramebufferMixin.java b/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/FramebufferMixin.java new file mode 100644 index 0000000..6b24c3f --- /dev/null +++ b/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/FramebufferMixin.java @@ -0,0 +1,36 @@ +package io.github.slimeistdev.crystalline_sky.mixin.client; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.textures.GpuTexture; +import io.github.slimeistdev.crystalline_sky.mixin_ducks.client.Framebuffer_Duck; +import net.minecraft.client.gl.Framebuffer; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(Framebuffer.class) +public class FramebufferMixin implements Framebuffer_Duck { + @Shadow + @Nullable + protected GpuTexture colorAttachment; + + @Shadow + public int textureWidth; + + @Shadow + public int textureHeight; + + @Override + public void crystalline_sky$copyColorFrom(Framebuffer framebuffer) { + RenderSystem.assertOnRenderThread(); + if (this.colorAttachment == null) { + throw new IllegalStateException("Trying to copy color texture to a RenderTarget without a color texture"); + } else if (framebuffer.getColorAttachment() == null) { + throw new IllegalStateException("Trying to copy color texture from a RenderTarget without a color texture"); + } else { + RenderSystem.getDevice() + .createCommandEncoder() + .copyTextureToTexture(framebuffer.getColorAttachment(), this.colorAttachment, 0, 0, 0, 0, 0, this.textureWidth, this.textureHeight); + } + } +} diff --git a/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/WorldRendererAccessor.java b/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/WorldRendererAccessor.java new file mode 100644 index 0000000..f16e6fe --- /dev/null +++ b/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/WorldRendererAccessor.java @@ -0,0 +1,12 @@ +package io.github.slimeistdev.crystalline_sky.mixin.client; + +import net.minecraft.client.render.DefaultFramebufferSet; +import net.minecraft.client.render.WorldRenderer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(WorldRenderer.class) +public interface WorldRendererAccessor { + @Accessor("framebufferSet") + DefaultFramebufferSet crystalline_sky$getFramebufferSet(); +} diff --git a/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/WorldRendererMixin.java b/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/WorldRendererMixin.java new file mode 100644 index 0000000..9abbfd4 --- /dev/null +++ b/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/WorldRendererMixin.java @@ -0,0 +1,166 @@ +package io.github.slimeistdev.crystalline_sky.mixin.client; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; +import com.mojang.blaze3d.buffers.GpuBufferSlice; +import io.github.slimeistdev.crystalline_sky.extenders_cove.BlockRenderLayerExt; +import io.github.slimeistdev.crystalline_sky.extenders_cove.BlockRenderLayerGroupExt; +import io.github.slimeistdev.crystalline_sky.mixin_ducks.client.DefaultFramebufferSet_Duck; +import io.github.slimeistdev.crystalline_sky.mixin_ducks.client.Framebuffer_Duck; +import io.github.slimeistdev.crystalline_sky.registry.CrystallineItems; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gl.DynamicUniforms; +import net.minecraft.client.gl.Framebuffer; +import net.minecraft.client.gl.SimpleFramebufferFactory; +import net.minecraft.client.option.CloudRenderMode; +import net.minecraft.client.render.*; +import net.minecraft.client.util.Handle; +import net.minecraft.client.util.ObjectAllocator; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.util.profiler.Profiler; +import org.jetbrains.annotations.Nullable; +import org.joml.*; +import org.spongepowered.asm.mixin.Final; +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.callback.CallbackInfo; + +import java.util.Optional; + +@Mixin(WorldRenderer.class) +public abstract class WorldRendererMixin { + @Shadow + @Final + private DefaultFramebufferSet framebufferSet; + + @Shadow + @Final + private MinecraftClient client; + + @Shadow + private @Nullable ClientWorld world; + + @Shadow + private int ticks; + + @Shadow + @Final + private CloudRenderer cloudRenderer; + + @Shadow + protected abstract boolean hasBlindnessOrDarkness(Camera camera); + + @Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/WorldRenderer;getTransparencyPostEffectProcessor()Lnet/minecraft/client/gl/PostEffectProcessor;")) + private void setupSkyBuffer(ObjectAllocator allocator, RenderTickCounter tickCounter, boolean renderBlockOutline, + Camera camera, Matrix4f positionMatrix, Matrix4f projectionMatrix, GpuBufferSlice fog, + Vector4f fogColor, boolean shouldRenderSky, CallbackInfo ci, + @Local FrameGraphBuilder frameGraphBuilder, + @Local SimpleFramebufferFactory factory) { + SimpleFramebufferFactory depthlessFactory = new SimpleFramebufferFactory( + factory.width(), + factory.height(), + false, + factory.clearColor() + ); + Handle framebuffer = frameGraphBuilder.createResourceHandle("crystalline_sky:sky_framebuffer", depthlessFactory); + ((DefaultFramebufferSet_Duck) framebufferSet).crystalline_sky$setSkyFramebuffer(framebuffer); + } + + @Unique + private Handle crystalline_sky$transferSkyBuffer(FramePass pass) { + Handle skyFramebuffer = pass.transfer( + ((DefaultFramebufferSet_Duck) framebufferSet).crystalline_sky$getSkyFramebuffer()); + ((DefaultFramebufferSet_Duck) framebufferSet).crystalline_sky$setSkyFramebuffer(skyFramebuffer); + return skyFramebuffer; + } + + @Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/WorldRenderer;renderMain(Lnet/minecraft/client/render/FrameGraphBuilder;Lnet/minecraft/client/render/Frustum;Lnet/minecraft/client/render/Camera;Lorg/joml/Matrix4f;Lcom/mojang/blaze3d/buffers/GpuBufferSlice;ZZLnet/minecraft/client/render/RenderTickCounter;Lnet/minecraft/util/profiler/Profiler;)V")) + private void copyAfterSky(ObjectAllocator allocator, RenderTickCounter tickCounter, boolean renderBlockOutline, + Camera camera, Matrix4f positionMatrix, Matrix4f projectionMatrix, GpuBufferSlice fog, + Vector4f fogColor, boolean shouldRenderSky, CallbackInfo ci, + @Local FrameGraphBuilder frameGraphBuilder) { + FramePass skyCopyPass = frameGraphBuilder.createPass("crystalline_sky:copy_sky_pass"); + + framebufferSet.mainFramebuffer = skyCopyPass.transfer(framebufferSet.mainFramebuffer); + + Handle skyFramebuffer = crystalline_sky$transferSkyBuffer(skyCopyPass); + + skyCopyPass.setRenderer(() -> { + ((Framebuffer_Duck) skyFramebuffer.get()).crystalline_sky$copyColorFrom(framebufferSet.mainFramebuffer.get()); + }); + + // render clouds + float f = tickCounter.getTickProgress(false); + + CloudRenderMode cloudRenderMode = this.client.options.getCloudRenderModeValue(); + if (cloudRenderMode != CloudRenderMode.OFF && !this.hasBlindnessOrDarkness(camera)) { + //noinspection DataFlowIssue + Optional optional = this.world.getDimension().cloudHeight(); + if (optional.isPresent()) { + float cloudPhase = this.ticks + f; + int color = this.world.getCloudsColor(f); + + // modified renderClouds function + { + FramePass framePass = frameGraphBuilder.createPass("crystallized clouds"); + crystalline_sky$transferSkyBuffer(framePass); + + framePass.setRenderer(() -> { + Handle backupCloudBuffer = this.framebufferSet.cloudsFramebuffer; + this.framebufferSet.cloudsFramebuffer = ((DefaultFramebufferSet_Duck) framebufferSet).crystalline_sky$getSkyFramebuffer(); + + this.cloudRenderer.renderClouds(color, cloudRenderMode, optional.get() + 0.33F, camera.getPos(), cloudPhase); + + ((DefaultFramebufferSet_Duck) framebufferSet).crystalline_sky$setSkyFramebuffer(framebufferSet.cloudsFramebuffer); + this.framebufferSet.cloudsFramebuffer = backupCloudBuffer; + }); + } + } + } + } + + @Inject(method = "renderMain", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/FramePass;transfer(Lnet/minecraft/client/util/Handle;)Lnet/minecraft/client/util/Handle;", ordinal = 0)) + private void transferCrystallineSky(FrameGraphBuilder frameGraphBuilder, Frustum frustum, Camera camera, + Matrix4f positionMatrix, GpuBufferSlice fog, boolean renderBlockOutline, + boolean renderEntityOutline, RenderTickCounter tickCounter, Profiler profiler, + CallbackInfo ci, @Local FramePass framePass) { + crystalline_sky$transferSkyBuffer(framePass); + } + + // renderMain : framePass.setRenderer(@{() -> ...}); + @Inject( + method = "method_62214", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/client/render/SectionRenderState;renderSection(Lnet/minecraft/client/render/BlockRenderLayerGroup;)V", + ordinal = 0, + shift = At.Shift.AFTER + ) + ) + private void renderCrystallineSky(GpuBufferSlice fog, RenderTickCounter tickCounter, Camera camera, + Profiler profiler, Matrix4f positionMatrix, Handle itemEntityFramebuffer, + Handle entityOutlineFramebuffer, boolean renderBlockOutline, Frustum frustum, + Handle translucentFramebuffer, Handle mainFramebuffer, CallbackInfo ci, + @Local SectionRenderState sectionRenderState) { + sectionRenderState.renderSection(BlockRenderLayerGroupExt.CRYSTALLINE_SKY_SKY); + } + + @WrapOperation(method = "renderBlockLayers", at = @At(value = "NEW", target = "net/minecraft/client/gl/DynamicUniforms$UniformValue")) + private DynamicUniforms.UniformValue tintSkyBlocks(Matrix4fc modelView, Vector4fc colorModulator, + Vector3fc modelOffset, Matrix4fc textureMatrix, float lineWidth, + Operation original, + @Local BlockRenderLayer blockRenderLayer) { + if (blockRenderLayer == BlockRenderLayerExt.CRYSTALLINE_SKY_SKY + && client.player != null + && (client.player.getMainHandStack().isOf(CrystallineItems.SKY) + || client.player.getOffHandStack().isOf(CrystallineItems.SKY))) { + colorModulator = new Vector4f(1.0f, 0.5f, 0.5f, 1.0f).mul(colorModulator); + } + + return original.call(modelView, colorModulator, modelOffset, textureMatrix, lineWidth); + } +} diff --git a/src/main/java/io/github/slimeistdev/crystalline_sky/mixin_ducks/client/DefaultFramebufferSet_Duck.java b/src/main/java/io/github/slimeistdev/crystalline_sky/mixin_ducks/client/DefaultFramebufferSet_Duck.java new file mode 100644 index 0000000..bc7dabd --- /dev/null +++ b/src/main/java/io/github/slimeistdev/crystalline_sky/mixin_ducks/client/DefaultFramebufferSet_Duck.java @@ -0,0 +1,13 @@ +package io.github.slimeistdev.crystalline_sky.mixin_ducks.client; + +import io.github.slimeistdev.crystalline_sky.CrystallineSky; +import net.minecraft.client.gl.Framebuffer; +import net.minecraft.client.util.Handle; +import net.minecraft.util.Identifier; + +public interface DefaultFramebufferSet_Duck { + Identifier crystalline_sky$SKY_FRAMEBUFFER = CrystallineSky.id("sky"); + + Handle crystalline_sky$getSkyFramebuffer(); + void crystalline_sky$setSkyFramebuffer(Handle framebuffer); +} diff --git a/src/main/java/io/github/slimeistdev/crystalline_sky/mixin_ducks/client/Framebuffer_Duck.java b/src/main/java/io/github/slimeistdev/crystalline_sky/mixin_ducks/client/Framebuffer_Duck.java new file mode 100644 index 0000000..7bb1b33 --- /dev/null +++ b/src/main/java/io/github/slimeistdev/crystalline_sky/mixin_ducks/client/Framebuffer_Duck.java @@ -0,0 +1,7 @@ +package io.github.slimeistdev.crystalline_sky.mixin_ducks.client; + +import net.minecraft.client.gl.Framebuffer; + +public interface Framebuffer_Duck { + void crystalline_sky$copyColorFrom(Framebuffer framebuffer); +} diff --git a/src/main/java/io/github/slimeistdev/crystalline_sky/registry/CrystallineBlocks.java b/src/main/java/io/github/slimeistdev/crystalline_sky/registry/CrystallineBlocks.java index 96727e1..c72f130 100644 --- a/src/main/java/io/github/slimeistdev/crystalline_sky/registry/CrystallineBlocks.java +++ b/src/main/java/io/github/slimeistdev/crystalline_sky/registry/CrystallineBlocks.java @@ -21,7 +21,8 @@ public class CrystallineBlocks { .allowsSpawning(Blocks::never) .solidBlock(Blocks::never) .suffocates(Blocks::never) - .blockVision(Blocks::never)); + .blockVision(Blocks::never) + .emissiveLighting(Blocks::always)); public static final Block SKY_LIGHT = register( "sky_light", diff --git a/src/main/java/io/github/slimeistdev/crystalline_sky/registry/client/CrystallineRenderPipelines.java b/src/main/java/io/github/slimeistdev/crystalline_sky/registry/client/CrystallineRenderPipelines.java new file mode 100644 index 0000000..9ab3162 --- /dev/null +++ b/src/main/java/io/github/slimeistdev/crystalline_sky/registry/client/CrystallineRenderPipelines.java @@ -0,0 +1,18 @@ +package io.github.slimeistdev.crystalline_sky.registry.client; + +import com.mojang.blaze3d.pipeline.RenderPipeline; +import io.github.slimeistdev.crystalline_sky.CrystallineSky; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.gl.RenderPipelines; + +@Environment(EnvType.CLIENT) +public class CrystallineRenderPipelines { + public static final RenderPipeline SKY_PIPELINE = RenderPipelines.register( + RenderPipeline.builder(RenderPipelines.TERRAIN_SNIPPET) + .withFragmentShader(CrystallineSky.id("core/terrain_sky")) + .withVertexShader(CrystallineSky.id("core/terrain_sky")) + .withLocation(CrystallineSky.id("pipeline/sky")) + .build() + ); +} diff --git a/src/main/resources/assets/crystalline_sky/shaders/core/terrain_sky.fsh b/src/main/resources/assets/crystalline_sky/shaders/core/terrain_sky.fsh new file mode 100644 index 0000000..7a8d5e1 --- /dev/null +++ b/src/main/resources/assets/crystalline_sky/shaders/core/terrain_sky.fsh @@ -0,0 +1,22 @@ +#version 150 + +#moj_import +#moj_import + +uniform sampler2D Sampler0; + +in float sphericalVertexDistance; +in float cylindricalVertexDistance; +in vec4 texProj0; + +out vec4 fragColor; + +void main() { + vec4 color = textureProj(Sampler0, texProj0) * ColorModulator; +#ifdef ALPHA_CUTOUT + if (color.a < ALPHA_CUTOUT) { + discard; + } +#endif + fragColor = apply_fog(color, sphericalVertexDistance, cylindricalVertexDistance, FogEnvironmentalStart, FogEnvironmentalEnd, FogRenderDistanceStart, FogRenderDistanceEnd, FogColor); +} diff --git a/src/main/resources/assets/crystalline_sky/shaders/core/terrain_sky.vsh b/src/main/resources/assets/crystalline_sky/shaders/core/terrain_sky.vsh new file mode 100644 index 0000000..091b9e4 --- /dev/null +++ b/src/main/resources/assets/crystalline_sky/shaders/core/terrain_sky.vsh @@ -0,0 +1,26 @@ +#version 150 + +#moj_import +#moj_import +#moj_import + +in vec3 Position; +in vec4 Color; +in vec2 UV0; +in ivec2 UV2; +in vec3 Normal; + +uniform sampler2D Sampler2; + +out float sphericalVertexDistance; +out float cylindricalVertexDistance; +out vec4 texProj0; + +void main() { + vec3 pos = Position + ModelOffset; + gl_Position = ProjMat * ModelViewMat * vec4(pos, 1.0); + + sphericalVertexDistance = fog_spherical_distance(pos); + cylindricalVertexDistance = fog_cylindrical_distance(pos); + texProj0 = projection_from_position(gl_Position); +} diff --git a/src/main/resources/crystalline_sky.mixins.json b/src/main/resources/crystalline_sky.mixins.json index 563dac2..4c2ccd2 100644 --- a/src/main/resources/crystalline_sky.mixins.json +++ b/src/main/resources/crystalline_sky.mixins.json @@ -12,7 +12,12 @@ "LightStorageAccessor" ], "client": [ - "client.ClientWorldMixin" + "client.BlockRenderLayerMixin", + "client.ClientWorldMixin", + "client.DefaultFramebufferSetMixin", + "client.FramebufferMixin", + "client.WorldRendererAccessor", + "client.WorldRendererMixin" ], "server": [ ], diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 81ebab0..cc22e16 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -32,9 +32,13 @@ "io.github.slimeistdev.crystalline_sky.CrystallineSky" ], "client": [ + "io.github.slimeistdev.crystalline_sky.CrystallineSkyClient" ], "fabric-datagen": [ "io.github.slimeistdev.crystalline_sky.datagen.CrystallineSkyDataGenerator" + ], + "mm:early_risers": [ + "io.github.slimeistdev.crystalline_sky.extenders_cove.CrystallineSkyEarlyRiser" ] } }