salt in the wound

add sodium compat
This commit is contained in:
techno-sam
2025-09-02 09:21:23 +02:00
parent 57fe03df35
commit 9ecc05520b
21 changed files with 649 additions and 40 deletions
@@ -0,0 +1,40 @@
/*
* MIT License
*
* Copyright (c) 2023-Present Bawnorton
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.slimeistdev.crystalline_sky.annotation.mixin;
import io.github.slimeistdev.crystalline_sky.compat.Mods;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ConditionalMixin {
Mods[] mods();
boolean applyIfPresent() default true;
}
@@ -0,0 +1,41 @@
package io.github.slimeistdev.crystalline_sky.compat;
import net.fabricmc.loader.api.FabricLoader;
import java.util.Optional;
import java.util.function.Supplier;
public enum Mods {
SODIUM("sodium");
public final String id;
public final boolean isLoaded;
Mods(String id) {
this.id = id;
this.isLoaded = FabricLoader.getInstance().isModLoaded(id);
}
/**
* Simple hook to run code if a mod is installed
*
* @param toRun will be run only if the mod is loaded
* @return Optional.empty() if the mod is not loaded, otherwise an Optional of the return value of the given supplier
*/
public <T> Optional<T> runIfInstalled(Supplier<Supplier<T>> toRun) {
if (isLoaded)
return Optional.of(toRun.get().get());
return Optional.empty();
}
/**
* Simple hook to execute code if a mod is installed
*
* @param toExecute will be executed only if the mod is loaded
*/
public void executeIfInstalled(Supplier<Runnable> toExecute) {
if (isLoaded) {
toExecute.get().run();
}
}
}
@@ -0,0 +1,103 @@
package io.github.slimeistdev.crystalline_sky.compat.sodium;
import com.mojang.blaze3d.opengl.GlStateManager;
import com.mojang.blaze3d.textures.GpuTextureView;
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;
import net.caffeinemc.mods.sodium.client.gl.shader.uniform.GlUniformInt;
import net.caffeinemc.mods.sodium.client.gl.shader.uniform.GlUniformMatrix4f;
import net.caffeinemc.mods.sodium.client.render.chunk.shader.*;
import net.caffeinemc.mods.sodium.client.render.chunk.terrain.TerrainRenderPass;
import net.caffeinemc.mods.sodium.client.util.FogParameters;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.texture.GlTexture;
import net.minecraft.util.math.MathHelper;
import org.joml.Matrix4fc;
import org.lwjgl.opengl.GL32C;
import java.util.EnumMap;
import java.util.Map;
@SuppressWarnings("DeprecatedIsStillUsed")
public class SkyShaderInterface implements ChunkShaderInterface {
private final Map<ChunkShaderTextureSlot, GlUniformInt> uniformTextures;
private final GlUniformMatrix4f uniformModelViewMatrix;
private final GlUniformMatrix4f uniformProjectionMatrix;
private final GlUniformFloat3v uniformRegionOffset;
private final GlUniformFloat4v uniformColorModulator;
// The fog shader component used by this program in order to set up the appropriate GL state
private final ChunkShaderFogComponent fogShader;
public SkyShaderInterface(ShaderBindingContext context, ChunkShaderOptions options) {
this.uniformModelViewMatrix = context.bindUniform("u_ModelViewMatrix", GlUniformMatrix4f::new);
this.uniformProjectionMatrix = context.bindUniform("u_ProjectionMatrix", GlUniformMatrix4f::new);
this.uniformRegionOffset = context.bindUniform("u_RegionOffset", GlUniformFloat3v::new);
this.uniformColorModulator = context.bindUniform("u_ColorModulator", GlUniformFloat4v::new);
this.uniformTextures = new EnumMap<>(ChunkShaderTextureSlot.class);
this.uniformTextures.put(ChunkShaderTextureSlot.BLOCK, context.bindUniform("u_BlockTex", GlUniformInt::new));
this.fogShader = options.fog().getFactory().apply(context);
}
@Override // the shader interface should not modify pipeline state
public void setupState(TerrainRenderPass pass, FogParameters parameters) {
this.bindTexture(ChunkShaderTextureSlot.BLOCK, pass.getAtlas());
MinecraftClient client = MinecraftClient.getInstance();
if (client.world != null
&& client.player != null
&& (client.player.getMainHandStack().isOf(CrystallineItems.SKY)
|| client.player.getOffHandStack().isOf(CrystallineItems.SKY)
|| client.player.getMainHandStack().isOf(CrystallineItems.WEEPING_SKY)
|| client.player.getOffHandStack().isOf(CrystallineItems.WEEPING_SKY))) {
float f = client.world.getTime() + client.getRenderTickCounter().getTickProgress(true);
float alpha = (MathHelper.sin(f / 10.0f) + 1.0f) / 2.0f;
// remap alpha from [0, 1] to [0, 0.75]
float maxAlpha = 1.0f - 0.25f;
alpha = alpha * maxAlpha;
this.uniformColorModulator.set(1.0f, 1.0f, 1.0f, alpha);
} else {
this.uniformColorModulator.set(1.0f, 1.0f, 1.0f, 1.0f);
}
this.fogShader.setup(parameters);
}
@Override // the shader interface should not modify pipeline state
public void resetState() {
// This is used by alternate implementations.
}
@Deprecated(forRemoval = true) // should be handled properly in GFX instead.
private void bindTexture(ChunkShaderTextureSlot slot, GpuTextureView textureView) {
GlTexture tex = (GlTexture) textureView.texture();
GlStateManager._activeTexture(GL32C.GL_TEXTURE0 + slot.ordinal());
GlStateManager._bindTexture(tex.getGlId());
GlStateManager._texParameter(GL32C.GL_TEXTURE_2D, 33084, textureView.baseMipLevel());
GlStateManager._texParameter(GL32C.GL_TEXTURE_2D, 33085, textureView.baseMipLevel() + textureView.mipLevels() - 1);
tex.checkDirty(GL32C.GL_TEXTURE_2D);
var uniform = this.uniformTextures.get(slot);
uniform.setInt(slot.ordinal());
}
@Override
public void setProjectionMatrix(Matrix4fc matrix) {
this.uniformProjectionMatrix.set(matrix);
}
@Override
public void setModelViewMatrix(Matrix4fc matrix) {
this.uniformModelViewMatrix.set(matrix);
}
@Override
public void setRegionOffset(float x, float y, float z) {
this.uniformRegionOffset.set(x, y, z);
}
}
@@ -143,8 +143,8 @@ public abstract class ChunkSkyLightMixin implements ChunkSkyLight_Duck {
crystalline_sky$weepingStorage.insertSolid(localX, y - weepingMinY, localZ, crystalline_sky$weepingScanner);
}
CrystallineSky.LOG.info("Weeping sky ranges for local column [{}, {}] in {}:", localX, localZ, blockView);
crystalline_sky$weepingStorage.debugState(localX, localZ, CrystallineSky.LOG::info);
CrystallineSky.LOG.debug("Weeping sky ranges for local column [{}, {}] in {}:", localX, localZ, blockView);
crystalline_sky$weepingStorage.debugState(localX, localZ, CrystallineSky.LOG::debug);
crystalline_sky$weepingScanner.setBlockView(null);
}
@@ -0,0 +1,38 @@
package io.github.slimeistdev.crystalline_sky.mixin;
import io.github.slimeistdev.crystalline_sky.util.ConditionalMixinManager;
import org.objectweb.asm.tree.ClassNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
import java.util.List;
import java.util.Set;
public class CrystallineSkyMixinPlugin implements IMixinConfigPlugin {
public static final Logger LOGGER = LoggerFactory.getLogger("CrystallineSky/MixinPlugin");
@Override
public void onLoad(String mixinPackage) { } // NO-OP
@Override
public String getRefMapperConfig() { return null; } // DEFAULT
@Override
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
return ConditionalMixinManager.shouldApply(mixinClassName);
}
@Override
public void acceptTargets(Set<String> myTargets, Set<String> otherTargets) { } // NO-OP
@Override
public List<String> getMixins() { return null; } // DEFAULT
@Override
public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { } // NO-OP
@Override
public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { } // NO-OP
}
@@ -1,16 +1,11 @@
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;
@@ -18,10 +13,10 @@ 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.math.MathHelper;
import net.minecraft.util.profiler.Profiler;
import org.jetbrains.annotations.Nullable;
import org.joml.*;
import org.joml.Matrix4f;
import org.joml.Vector4f;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@@ -61,13 +56,7 @@ public abstract class WorldRendererMixin {
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> framebuffer = frameGraphBuilder.createResourceHandle("crystalline_sky:sky_framebuffer", depthlessFactory);
Handle<Framebuffer> framebuffer = frameGraphBuilder.createResourceHandle("crystalline_sky:sky_framebuffer", factory);
((DefaultFramebufferSet_Duck) framebufferSet).crystalline_sky$setSkyFramebuffer(framebuffer);
}
@@ -149,27 +138,4 @@ public abstract class WorldRendererMixin {
@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<DynamicUniforms.UniformValue> 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)
|| client.player.getMainHandStack().isOf(CrystallineItems.WEEPING_SKY)
|| client.player.getOffHandStack().isOf(CrystallineItems.WEEPING_SKY))) {
float f = ticks + client.getRenderTickCounter().getTickProgress(true);
float alpha = (MathHelper.sin(f / 10.0f) + 1.0f) / 2.0f;
// remap alpha from [0, 1] to [0, 0.75]
float maxAlpha = 1.0f - 0.25f;
alpha = alpha * maxAlpha;
colorModulator = new Vector4f(1.0f, 1.0f, 1.0f, alpha).mul(colorModulator);
}
return original.call(modelView, colorModulator, modelOffset, textureMatrix, lineWidth);
}
}
@@ -0,0 +1,56 @@
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 io.github.slimeistdev.crystalline_sky.annotation.mixin.ConditionalMixin;
import io.github.slimeistdev.crystalline_sky.compat.Mods;
import io.github.slimeistdev.crystalline_sky.extenders_cove.BlockRenderLayerExt;
import io.github.slimeistdev.crystalline_sky.registry.CrystallineItems;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gl.DynamicUniforms;
import net.minecraft.client.render.BlockRenderLayer;
import net.minecraft.client.render.WorldRenderer;
import net.minecraft.util.math.MathHelper;
import org.joml.Matrix4fc;
import org.joml.Vector3fc;
import org.joml.Vector4f;
import org.joml.Vector4fc;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
@ConditionalMixin(mods = Mods.SODIUM, applyIfPresent = false)
@Mixin(WorldRenderer.class)
public class WorldRenderer_NoSodium_Mixin {
@Shadow
@Final
private MinecraftClient client;
@Shadow
private int ticks;
@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<DynamicUniforms.UniformValue> 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)
|| client.player.getMainHandStack().isOf(CrystallineItems.WEEPING_SKY)
|| client.player.getOffHandStack().isOf(CrystallineItems.WEEPING_SKY))) {
float f = ticks + client.getRenderTickCounter().getTickProgress(true);
float alpha = (MathHelper.sin(f / 10.0f) + 1.0f) / 2.0f;
// remap alpha from [0, 1] to [0, 0.75]
float maxAlpha = 1.0f - 0.25f;
alpha = alpha * maxAlpha;
colorModulator = new Vector4f(1.0f, 1.0f, 1.0f, alpha).mul(colorModulator);
}
return original.call(modelView, colorModulator, modelOffset, textureMatrix, lineWidth);
}
}
@@ -0,0 +1,39 @@
package io.github.slimeistdev.crystalline_sky.mixin.client.compat.sodium;
import io.github.slimeistdev.crystalline_sky.annotation.mixin.ConditionalMixin;
import io.github.slimeistdev.crystalline_sky.extenders_cove.BlockRenderLayerExt;
import io.github.slimeistdev.crystalline_sky.compat.Mods;
import net.caffeinemc.mods.sodium.client.render.chunk.terrain.DefaultTerrainRenderPasses;
import net.caffeinemc.mods.sodium.client.render.chunk.terrain.material.DefaultMaterials;
import net.caffeinemc.mods.sodium.client.render.chunk.terrain.material.Material;
import net.caffeinemc.mods.sodium.client.render.chunk.terrain.material.parameters.AlphaCutoffParameter;
import net.minecraft.client.render.BlockRenderLayer;
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.CallbackInfoReturnable;
import java.util.Arrays;
@ConditionalMixin(mods = Mods.SODIUM)
@Mixin(DefaultMaterials.class)
public class DefaultMaterialsMixin {
@Unique
@SuppressWarnings("OptionalGetWithoutIsPresent")
private static final Material crystalline_sky$SKY = new Material(
Arrays.stream(DefaultTerrainRenderPasses.ALL)
.filter(pass -> ((TerrainRenderPassAccessor) pass).crystalline_sky$getRenderLayer() == BlockRenderLayerExt.CRYSTALLINE_SKY_SKY)
.findFirst()
.get(),
AlphaCutoffParameter.ZERO,
false
);
@Inject(method = "forChunkLayer", at = @At(value = "NEW", target = "(Ljava/lang/String;Ljava/lang/Throwable;)Ljava/lang/MatchException;"), cancellable = true)
private static void addCrystallineSkyMaterial(BlockRenderLayer layer, CallbackInfoReturnable<Material> cir) {
if (layer == BlockRenderLayerExt.CRYSTALLINE_SKY_SKY) {
cir.setReturnValue(crystalline_sky$SKY);
}
}
}
@@ -0,0 +1,31 @@
package io.github.slimeistdev.crystalline_sky.mixin.client.compat.sodium;
import io.github.slimeistdev.crystalline_sky.annotation.mixin.ConditionalMixin;
import io.github.slimeistdev.crystalline_sky.extenders_cove.BlockRenderLayerExt;
import io.github.slimeistdev.crystalline_sky.compat.Mods;
import net.caffeinemc.mods.sodium.client.render.chunk.terrain.DefaultTerrainRenderPasses;
import net.caffeinemc.mods.sodium.client.render.chunk.terrain.TerrainRenderPass;
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;
@ConditionalMixin(mods = Mods.SODIUM)
@Mixin(DefaultTerrainRenderPasses.class)
public class DefaultTerrainRenderPassesMixin {
@Mutable
@Shadow
@Final
public static TerrainRenderPass[] ALL;
@Inject(method = "<clinit>", at = @At("RETURN"))
private static void addCrystallineSkyPass(CallbackInfo ci) {
var ALL$ = new TerrainRenderPass[ALL.length + 1];
System.arraycopy(ALL, 0, ALL$, 0, ALL.length);
ALL$[ALL.length] = new TerrainRenderPass(BlockRenderLayerExt.CRYSTALLINE_SKY_SKY, false, true);
ALL = ALL$;
}
}
@@ -0,0 +1,6 @@
The following mixins in this package are from derived from https://github.com/wisp-forest/affinity, and as such are licensed under the MIT license:
- DefaultMaterialsMixin
- DefaultTerrainRenderPassesMixin
- SodiumWorldRendererMixin
- TerrainRenderPassAccessor
@@ -0,0 +1,50 @@
package io.github.slimeistdev.crystalline_sky.mixin.client.compat.sodium;
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.compat.sodium.SkyShaderInterface;
import io.github.slimeistdev.crystalline_sky.extenders_cove.BlockRenderLayerExt;
import net.caffeinemc.mods.sodium.client.gl.shader.GlProgram;
import net.caffeinemc.mods.sodium.client.render.chunk.ShaderChunkRenderer;
import net.caffeinemc.mods.sodium.client.render.chunk.shader.ChunkShaderInterface;
import net.caffeinemc.mods.sodium.client.render.chunk.shader.ChunkShaderOptions;
import net.caffeinemc.mods.sodium.client.render.chunk.shader.ShaderBindingContext;
import net.caffeinemc.mods.sodium.client.render.chunk.terrain.material.DefaultMaterials;
import net.minecraft.util.Identifier;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import java.util.function.Function;
@ConditionalMixin(mods = Mods.SODIUM)
@Mixin(ShaderChunkRenderer.class)
public class ShaderChunkRendererMixin {
@WrapOperation(method = "compileProgram", at = @At(value = "INVOKE", target = "Lnet/caffeinemc/mods/sodium/client/render/chunk/ShaderChunkRenderer;createShader(Ljava/lang/String;Lnet/caffeinemc/mods/sodium/client/render/chunk/shader/ChunkShaderOptions;)Lnet/caffeinemc/mods/sodium/client/gl/shader/GlProgram;"), remap = false)
private GlProgram<ChunkShaderInterface> createSkyShader(ShaderChunkRenderer instance, String path, ChunkShaderOptions options, Operation<GlProgram<ChunkShaderInterface>> original) {
if (options.pass() == DefaultMaterials.forChunkLayer(BlockRenderLayerExt.CRYSTALLINE_SKY_SKY).pass) {
return original.call(instance, "sodium_compat/block_layer_sky", options);
}
return original.call(instance, path, options);
}
@WrapOperation(method = "createShader", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/Identifier;of(Ljava/lang/String;Ljava/lang/String;)Lnet/minecraft/util/Identifier;"))
private Identifier redirectShaderNamespace(String namespace, String path, Operation<Identifier> original, String pathArg) {
if (pathArg.equals("sodium_compat/block_layer_sky")) {
namespace = "crystalline_sky";
}
return original.call(namespace, path);
}
@WrapOperation(method = "createShader", at = @At(value = "INVOKE", target = "Lnet/caffeinemc/mods/sodium/client/gl/shader/GlProgram$Builder;link(Ljava/util/function/Function;)Lnet/caffeinemc/mods/sodium/client/gl/shader/GlProgram;"), remap = false)
private static GlProgram<ChunkShaderInterface> useSkyShaderInterface(GlProgram.Builder instance, Function<ShaderBindingContext, ChunkShaderInterface> factory, Operation<GlProgram<ChunkShaderInterface>> original, String argPath, ChunkShaderOptions argOptions) {
if (argPath.equals("sodium_compat/block_layer_sky")) {
factory = (shader) -> new SkyShaderInterface(shader, argOptions);
}
return original.call(instance, factory);
}
}
@@ -0,0 +1,30 @@
package io.github.slimeistdev.crystalline_sky.mixin.client.compat.sodium;
import io.github.slimeistdev.crystalline_sky.annotation.mixin.ConditionalMixin;
import io.github.slimeistdev.crystalline_sky.extenders_cove.BlockRenderLayerExt;
import io.github.slimeistdev.crystalline_sky.extenders_cove.BlockRenderLayerGroupExt;
import io.github.slimeistdev.crystalline_sky.compat.Mods;
import net.caffeinemc.mods.sodium.client.render.SodiumWorldRenderer;
import net.caffeinemc.mods.sodium.client.render.chunk.ChunkRenderMatrices;
import net.caffeinemc.mods.sodium.client.render.chunk.RenderSectionManager;
import net.caffeinemc.mods.sodium.client.render.chunk.terrain.material.DefaultMaterials;
import net.minecraft.client.render.BlockRenderLayerGroup;
import org.spongepowered.asm.mixin.Mixin;
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;
@ConditionalMixin(mods = Mods.SODIUM)
@Mixin(SodiumWorldRenderer.class)
public class SodiumWorldRendererMixin {
@Shadow
private RenderSectionManager renderSectionManager;
@Inject(method = "drawChunkLayer", at = @At("RETURN"))
private void drawCrystallineLayer(BlockRenderLayerGroup group, ChunkRenderMatrices matrices, double x, double y, double z, CallbackInfo ci) {
if (group != BlockRenderLayerGroupExt.CRYSTALLINE_SKY_SKY) return;
renderSectionManager.renderLayer(matrices, DefaultMaterials.forChunkLayer(BlockRenderLayerExt.CRYSTALLINE_SKY_SKY).pass, x, y, z);
}
}
@@ -0,0 +1,15 @@
package io.github.slimeistdev.crystalline_sky.mixin.client.compat.sodium;
import io.github.slimeistdev.crystalline_sky.annotation.mixin.ConditionalMixin;
import io.github.slimeistdev.crystalline_sky.compat.Mods;
import net.caffeinemc.mods.sodium.client.render.chunk.terrain.TerrainRenderPass;
import net.minecraft.client.render.BlockRenderLayer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@ConditionalMixin(mods = Mods.SODIUM)
@Mixin(TerrainRenderPass.class)
public interface TerrainRenderPassAccessor {
@Accessor("renderType")
BlockRenderLayer crystalline_sky$getRenderLayer();
}
@@ -0,0 +1,66 @@
/*
* MIT License
*
* Copyright (c) 2023-Present Bawnorton
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.slimeistdev.crystalline_sky.util;
import io.github.slimeistdev.crystalline_sky.annotation.mixin.ConditionalMixin;
import io.github.slimeistdev.crystalline_sky.compat.Mods;
import io.github.slimeistdev.crystalline_sky.mixin.CrystallineSkyMixinPlugin;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AnnotationNode;
import org.spongepowered.asm.service.MixinService;
import org.spongepowered.asm.util.Annotations;
import java.io.IOException;
import java.util.List;
public class ConditionalMixinManager {
public static boolean shouldApply(String className) {
try {
List<AnnotationNode> annotationNodes = MixinService.getService().getBytecodeProvider().getClassNode(className).visibleAnnotations;
if (annotationNodes == null) return true;
boolean shouldApply = true;
for (AnnotationNode node : annotationNodes) {
if (node.desc.equals(Type.getDescriptor(ConditionalMixin.class))) {
List<Mods> mods = Annotations.getValue(node, "mods", true, Mods.class);
boolean applyIfPresent = Annotations.getValue(node, "applyIfPresent", Boolean.TRUE);
boolean anyModsLoaded = anyModsLoaded(mods);
shouldApply = anyModsLoaded == applyIfPresent;
CrystallineSkyMixinPlugin.LOGGER.debug("{} is{}being applied because the mod(s) {} are{}loaded", className, shouldApply ? " " : " not ", mods, anyModsLoaded ? " " : " not ");
}
}
return shouldApply;
} catch (ClassNotFoundException | IOException e) {
throw new RuntimeException(e);
}
}
private static boolean anyModsLoaded(List<Mods> mods) {
for (Mods mod : mods) {
if (mod.isLoaded) return true;
}
return false;
}
}
@@ -0,0 +1,6 @@
vec4 projection_from_position(vec4 position) {
vec4 projection = position * 0.5;
projection.xy = vec2(projection.x + projection.w, projection.y + projection.w);
projection.zw = position.zw;
return projection;
}
@@ -0,0 +1,50 @@
#version 330 core
#import <sodium:include/fog.glsl>
in vec4 v_Color; // The interpolated vertex color
in vec4 v_TexProj; // The interpolated sky texture coordinates
in vec2 v_FragDistance; // The fragment's distance from the camera (cylindrical and spherical)
in float v_MaterialMipBias;
in float v_MaterialAlphaCutoff;
uniform sampler2D u_BlockTex; // The block (sky) texture
uniform vec4 u_FogColor; // The color of the shader fog
uniform vec2 u_EnvironmentFog; // The start and end position for environmental fog
uniform vec2 u_RenderFog; // The start and end position for border fog
uniform vec4 u_ColorModulator;
out vec4 fragColor; // The output fragment for the color framebuffer
#define SCALE 1
#define BAYER_BIAS 0.03125
const mat4x4 bayerMatrix4x4 = mat4x4(
0.0, 8.0, 2.0, 10.0,
12.0, 4.0, 14.0, 6.0,
3.0, 11.0, 1.0, 9.0,
15.0, 7.0, 13.0, 5.0
) / 16.0;
void main() {
vec4 diffuseColor = textureProj(u_BlockTex, v_TexProj, v_MaterialMipBias);//texture(u_BlockTex, v_TexCoord, v_MaterialMipBias);
/*// Apply per-vertex color
diffuseColor *= v_Color;*/
diffuseColor *= vec4(u_ColorModulator.rgb, 1.0);
#ifdef USE_FRAGMENT_DISCARD
int x = int(gl_FragCoord.x / SCALE) % 4;
int y = int(gl_FragCoord.y / SCALE) % 4;
float bayer = bayerMatrix4x4[y][x];
if (u_ColorModulator.a <= bayer + BAYER_BIAS) {
discard;
}
#endif
fragColor = _linearFog(diffuseColor, v_FragDistance, u_FogColor, u_EnvironmentFog, u_RenderFog);
}
@@ -0,0 +1,54 @@
#version 330 core
#import <sodium:include/fog.glsl>
#import <sodium:include/chunk_vertex.glsl>
#import <sodium:include/chunk_matrices.glsl>
#import <sodium:include/chunk_material.glsl>
#import <crystalline_sky:include/projection.glsl>
out vec4 v_Color;
out vec4 v_TexProj;
out float v_MaterialMipBias;
#ifdef USE_FRAGMENT_DISCARD
out float v_MaterialAlphaCutoff;
#endif
#ifdef USE_FOG
out vec2 v_FragDistance;
#endif
uniform vec3 u_RegionOffset;
uvec3 _get_relative_chunk_coord(uint pos) {
// Packing scheme is defined by LocalSectionIndex
return uvec3(pos) >> uvec3(5u, 0u, 2u) & uvec3(7u, 3u, 7u);
}
vec3 _get_draw_translation(uint pos) {
return _get_relative_chunk_coord(pos) * vec3(16.0);
}
void main() {
_vert_init();
// Transform the chunk-local vertex position into world model space
vec3 translation = u_RegionOffset + _get_draw_translation(_draw_id);
vec3 position = _vert_position + translation;
#ifdef USE_FOG
v_FragDistance = getFragDistance(position);
#endif
// Transform the vertex position into model-view-projection space
gl_Position = u_ProjectionMatrix * u_ModelViewMatrix * vec4(position, 1.0);
v_Color = _vert_color;
v_TexProj = projection_from_position(gl_Position);
v_MaterialMipBias = _material_mip_bias(_material_params);
#ifdef USE_FRAGMENT_DISCARD
v_MaterialAlphaCutoff = _material_alpha_cutoff(_material_params);
#endif
}
@@ -5,6 +5,7 @@
"minVersion": "0.5.0"
},
"package": "io.github.slimeistdev.crystalline_sky.mixin",
"plugin": "io.github.slimeistdev.crystalline_sky.mixin.CrystallineSkyMixinPlugin",
"compatibilityLevel": "JAVA_21",
"mixins": [
"ChunkLightProviderMixin",
@@ -19,8 +20,14 @@
"client.DebugRendererMixin",
"client.DefaultFramebufferSetMixin",
"client.FramebufferMixin",
"client.WorldRenderer_NoSodium_Mixin",
"client.WorldRendererAccessor",
"client.WorldRendererMixin"
"client.WorldRendererMixin",
"client.compat.sodium.DefaultMaterialsMixin",
"client.compat.sodium.DefaultTerrainRenderPassesMixin",
"client.compat.sodium.ShaderChunkRendererMixin",
"client.compat.sodium.SodiumWorldRendererMixin",
"client.compat.sodium.TerrainRenderPassAccessor"
],
"server": [
],