diff --git a/common/src/generated/resources/.cache/5790708f1bab3bc9da26dbe9791dce16c55e0cb8 b/common/src/generated/resources/.cache/5790708f1bab3bc9da26dbe9791dce16c55e0cb8 index 902de1a..aa17019 100644 --- a/common/src/generated/resources/.cache/5790708f1bab3bc9da26dbe9791dce16c55e0cb8 +++ b/common/src/generated/resources/.cache/5790708f1bab3bc9da26dbe9791dce16c55e0cb8 @@ -1,4 +1,4 @@ -// 1.21.1 2026-04-16T11:05:11.823836864 Crystalline Sky/Model Definitions +// 1.21.1 2026-04-25T02:02:19.160711408 Crystalline Sky/Model Definitions e832366c216102270b75085db7a7169881b853b3 assets/crystalline_sky/blockstates/sky.json 0ac5351c3a01e0f9e76517452918e12770b3b54b assets/crystalline_sky/models/block/sky_light_14.json ee9cb7604922cdb2ad71d021a593ca82f0baf493 assets/crystalline_sky/models/block/sky_light_03.json @@ -12,6 +12,8 @@ ef9e5aca345b59cb4692a7bcfaac539aed6f6889 assets/crystalline_sky/models/block/sky 2ce612b8445da92c6cecd07bd5364a25bcfb127f assets/crystalline_sky/models/block/sky_light_05.json ef5afdbcc8401a27029b6f0a29fa1117761c620d assets/crystalline_sky/models/item/sky_light.json 59463cef438e58b137e5ce27402acf42a3a0ae87 assets/crystalline_sky/models/block/sky_light_02.json +2763952a1919802e34f0976b023fc7b486456b91 assets/crystalline_sky/models/item/skybox_test.json +9f63a1dc282986e15f9b22bee0ab0a2eaf4f994d assets/crystalline_sky/models/block/skybox_test.json c0d693e4f78ce15c238909130382909abda4c922 assets/crystalline_sky/models/block/sky_light_08.json 008a0d0a76a34d8f375fa355452a5d0f93f9af3b assets/crystalline_sky/models/item/sky.json 508ffb97ee711b53767b9d33659596197f69ee20 assets/crystalline_sky/models/block/weeping_sky_light.json @@ -31,14 +33,15 @@ fceb0c59b7f6d431200764ccf87596541bacb17f assets/crystalline_sky/models/block/sky e2c7bebd9eca446bb06fff866ec4d4996917e7e4 assets/crystalline_sky/models/block/sky_light_12.json 04f1e4eba184b8e7b1669fc61006e3d00e09d164 assets/crystalline_sky/models/item/sky_light_11.json 58349dc5dedb8016fb0bc958fcd4a9ccde13a1cd assets/crystalline_sky/models/item/sky_light_14.json -03e2eb768bc34fbeaabffbff8ed3a2a3044a6db1 assets/crystalline_sky/blockstates/weeping_sky.json 51fa40ff02afcec303e7a18478cbae5375dfb140 assets/crystalline_sky/models/item/sky_light_04.json +03e2eb768bc34fbeaabffbff8ed3a2a3044a6db1 assets/crystalline_sky/blockstates/weeping_sky.json 7c7d944714b5bcbee6a7e8014599ade8fbc5e804 assets/crystalline_sky/models/block/weeping_sky.json dff33a68a694de0f3ef177886c002204ffe49a8c assets/crystalline_sky/models/item/sky_light_07.json b29c14f77a08da7a6994cff4c6801d6f04b12ec0 assets/crystalline_sky/models/item/sky_light_03.json a87d8988452529a1f5af5662ad636223fdd98fec assets/crystalline_sky/models/block/sky_light_15.json be0be7e1d7ce1ccabed01ef09c6499a2a7f2b132 assets/crystalline_sky/models/item/weeping_sky_light.json d500e56057c0c2f3c948894694e2826f1726fd9e assets/crystalline_sky/models/item/sky_light_15.json +662d2389357e6f00a3a59042d08aec47df9c2c10 assets/crystalline_sky/blockstates/skybox_test.json 9f0d9fe5dfb05bbe18177db5c40e600c5b256858 assets/crystalline_sky/models/item/sky_light_00.json 3183aeb9fff78d0c65f1ddd0dfb599420573e281 assets/crystalline_sky/models/block/sky_light_00.json 04fb705807dd052f00ff861343ebe6fe0a78ca41 assets/crystalline_sky/models/block/sky.json diff --git a/common/src/generated/resources/.cache/6c343772b5bbed02cb8017d08d07aa1ea684e455 b/common/src/generated/resources/.cache/6c343772b5bbed02cb8017d08d07aa1ea684e455 index f5d536d..95d586c 100644 --- a/common/src/generated/resources/.cache/6c343772b5bbed02cb8017d08d07aa1ea684e455 +++ b/common/src/generated/resources/.cache/6c343772b5bbed02cb8017d08d07aa1ea684e455 @@ -1,3 +1,3 @@ -// 1.21.1 2026-04-16T11:05:11.822516104 Crystalline Sky/Tags for minecraft:block +// 1.21.1 2026-04-25T02:02:19.159567873 Crystalline Sky/Tags for minecraft:block 1389c0b812f7a6e4d5dd00edac1dc07beb5f9552 data/crystalline_sky/tags/block/sky_light_emitters.json 606477607a09045ff2830cbc036e744d6a728bbd data/minecraft/tags/block/crystal_sound_blocks.json diff --git a/common/src/generated/resources/.cache/dcc41341364508cf6e5f757a3f66d54c126e2c9d b/common/src/generated/resources/.cache/dcc41341364508cf6e5f757a3f66d54c126e2c9d index f77167e..f3bda29 100644 --- a/common/src/generated/resources/.cache/dcc41341364508cf6e5f757a3f66d54c126e2c9d +++ b/common/src/generated/resources/.cache/dcc41341364508cf6e5f757a3f66d54c126e2c9d @@ -1,3 +1,3 @@ -// 1.21.1 2026-04-16T11:05:11.825012592 Crystalline Sky/Block Loot Tables +// 1.21.1 2026-04-25T02:02:19.161914767 Crystalline Sky/Block Loot Tables 337de0acfc1b9b86adde0705e342ed1d4b5c9c4e data/crystalline_sky/loot_table/blocks/weeping_sky.json 6a9b7a08424cbd3d699dfd3252d432517254aa45 data/crystalline_sky/loot_table/blocks/sky.json diff --git a/common/src/generated/resources/assets/crystalline_sky/blockstates/skybox_test.json b/common/src/generated/resources/assets/crystalline_sky/blockstates/skybox_test.json new file mode 100644 index 0000000..227f8ce --- /dev/null +++ b/common/src/generated/resources/assets/crystalline_sky/blockstates/skybox_test.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "crystalline_sky:block/skybox_test" + } + } +} \ No newline at end of file diff --git a/common/src/generated/resources/assets/crystalline_sky/models/block/skybox_test.json b/common/src/generated/resources/assets/crystalline_sky/models/block/skybox_test.json new file mode 100644 index 0000000..52183fc --- /dev/null +++ b/common/src/generated/resources/assets/crystalline_sky/models/block/skybox_test.json @@ -0,0 +1,8 @@ +{ + "parent": "minecraft:block/cube_all", + "crystalline_sky:atlas": "crystalline_sky:textures/atlas/skyboxes.png", + "render_type": "crystalline_sky:skybox", + "textures": { + "all": "crystalline_sky:crystalline_sky_skybox/skybox_test" + } +} \ No newline at end of file diff --git a/common/src/generated/resources/assets/crystalline_sky/models/item/skybox_test.json b/common/src/generated/resources/assets/crystalline_sky/models/item/skybox_test.json new file mode 100644 index 0000000..a6f504d --- /dev/null +++ b/common/src/generated/resources/assets/crystalline_sky/models/item/skybox_test.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "crystalline_sky:block/skybox_test" + } +} \ No newline at end of file diff --git a/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/BlockModelDeserializerMixin.java b/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/BlockModelDeserializerMixin.java new file mode 100644 index 0000000..1746866 --- /dev/null +++ b/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/BlockModelDeserializerMixin.java @@ -0,0 +1,22 @@ +package io.github.slimeistdev.crystalline_sky.mixin.client; + +import com.google.gson.JsonObject; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import net.minecraft.client.renderer.block.model.BlockModel; +import net.minecraft.resources.ResourceLocation; +import org.objectweb.asm.Opcodes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(BlockModel.Deserializer.class) +public class BlockModelDeserializerMixin { + @WrapOperation(method = "getTextureMap", at = @At(value = "FIELD", target = "Lnet/minecraft/client/renderer/texture/TextureAtlas;LOCATION_BLOCKS:Lnet/minecraft/resources/ResourceLocation;", opcode = Opcodes.GETSTATIC)) + private ResourceLocation modifyAtlas(Operation original, JsonObject json) { + if (json.has("crystalline_sky:atlas")) { + return ResourceLocation.parse(json.get("crystalline_sky:atlas").getAsString()); + } else { + return original.call(); + } + } +} diff --git a/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/GameRendererMixin.java b/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/GameRendererMixin.java index a47e20a..52ef6b2 100644 --- a/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/GameRendererMixin.java +++ b/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/GameRendererMixin.java @@ -2,21 +2,42 @@ 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.vertex.DefaultVertexFormat; import com.mojang.datafixers.util.Pair; import io.github.slimeistdev.crystalline_sky.registry.client.CrystallineShaderInstances; -import net.minecraft.client.renderer.ShaderInstance; +import net.minecraft.client.Camera; +import net.minecraft.client.DeltaTracker; +import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GameRenderer; -import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import net.minecraft.client.renderer.LevelRenderer; +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.ShaderInstance; import net.minecraft.server.packs.resources.ResourceProvider; +import org.joml.Matrix4f; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import java.io.IOException; import java.util.List; import java.util.function.Consumer; +import static io.github.slimeistdev.crystalline_sky.util.SharedRenderVariables.invSkyboxMat; + @Mixin(GameRenderer.class) -public class GameRendererMixin { +public abstract class GameRendererMixin { + @Shadow + @Final + Minecraft minecraft; + + @Shadow + public abstract float getDepthFar(); + + @Unique + private static final Matrix4f crystalline_sky$scratch = new Matrix4f(); + @WrapOperation(method = "reloadShaders", at = @At(value = "INVOKE", target = "Ljava/util/List;add(Ljava/lang/Object;)Z", ordinal = 0)) private >> boolean loadSkyProgram( List instance, @@ -29,6 +50,32 @@ public class GameRendererMixin { "crystalline_sky_rendertype_sky", DefaultVertexFormat.BLOCK ), (Consumer) program -> CrystallineShaderInstances.renderTypeSkyProgram = program)); + original.call(instance, Pair.of(new ShaderInstance( + factory, + "crystalline_sky_rendertype_skybox", + DefaultVertexFormat.BLOCK + ), (Consumer) program -> CrystallineShaderInstances.renderTypeSkyboxProgram = program)); return original.call(instance, e); } + + @WrapOperation(method = "renderLevel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GameRenderer;getProjectionMatrix(D)Lorg/joml/Matrix4f;")) + private Matrix4f storeInverseProjectionMatrix(GameRenderer instance, double fov, Operation original) { + invSkyboxMat.setPerspective( + (float)(fov * (float) (Math.PI / 180.0)), + (float)this.minecraft.getWindow().getWidth() / this.minecraft.getWindow().getHeight(), + 0.05F, + this.getDepthFar() + ).invert(); + // TODO: do we need inv view multiplied in here? + return original.call(instance, fov); + } + + @WrapOperation(method = "renderLevel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/LevelRenderer;renderLevel(Lnet/minecraft/client/DeltaTracker;ZLnet/minecraft/client/Camera;Lnet/minecraft/client/renderer/GameRenderer;Lnet/minecraft/client/renderer/LightTexture;Lorg/joml/Matrix4f;Lorg/joml/Matrix4f;)V")) + private void mulInvViewMat(LevelRenderer instance, DeltaTracker deltaTracker, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f frustumMatrix, Matrix4f projectionMatrix, Operation original) { + // invSkyboxMat = inv(ModelViewMat) * inv(ProjMat) + projectionMatrix.invert(invSkyboxMat); + Matrix4f invViewMat = frustumMatrix.invert(crystalline_sky$scratch); + invViewMat.mul(invSkyboxMat, invSkyboxMat); + original.call(instance, deltaTracker, renderBlockOutline, camera, gameRenderer, lightTexture, frustumMatrix, projectionMatrix); + } } 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 e5f712d..8ec2ec6 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 @@ -134,5 +134,6 @@ public abstract class LevelRendererMixin implements LevelRenderer_Duck { Matrix4f matrix4f, Matrix4f positionMatrix, Operation original) { original.call(instance, renderLayer, x, y, z, matrix4f, positionMatrix); renderSectionLayer(CrystallineRenderTypes.SKY, x, y, z, matrix4f, positionMatrix); + renderSectionLayer(CrystallineRenderTypes.SKYBOX, x, y, z, matrix4f, positionMatrix); } } diff --git a/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/LevelRenderer_NoSodium_Mixin.java b/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/LevelRenderer_NoSodium_Mixin.java index 930e9c5..6753a2d 100644 --- a/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/LevelRenderer_NoSodium_Mixin.java +++ b/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/LevelRenderer_NoSodium_Mixin.java @@ -36,7 +36,7 @@ public class LevelRenderer_NoSodium_Mixin { RenderType renderLayer) { original.call(instance, drawMode, viewMatrix, projectionMatrix, window); - if (renderLayer == CrystallineRenderTypes.SKY + if ((renderLayer == CrystallineRenderTypes.SKY || renderLayer == CrystallineRenderTypes.SKYBOX) && instance.COLOR_MODULATOR != null && minecraft.player != null && (CrystallineItems.isSky(minecraft.player.getMainHandItem()) diff --git a/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/compat/sodium/DefaultMaterialsMixin.java b/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/compat/sodium/DefaultMaterialsMixin.java index 4f0c1b9..3acc398 100644 --- a/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/compat/sodium/DefaultMaterialsMixin.java +++ b/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/compat/sodium/DefaultMaterialsMixin.java @@ -30,10 +30,23 @@ public class DefaultMaterialsMixin { false ); + @Unique + @SuppressWarnings("OptionalGetWithoutIsPresent") + private static final Material crystalline_sky$SKYBOX = new Material( + Arrays.stream(DefaultTerrainRenderPasses.ALL) + .filter(pass -> ((TerrainRenderPassAccessor) pass).crystalline_sky$getRenderLayer() == CrystallineRenderTypes.SKYBOX) + .findFirst() + .get(), + AlphaCutoffParameter.ZERO, + false + ); + @Inject(method = "forRenderLayer", at = @At(value = "NEW", target = "(Ljava/lang/String;)Ljava/lang/IllegalArgumentException;"), cancellable = true) private static void addCrystallineSkyMaterial(RenderType layer, CallbackInfoReturnable cir) { if (layer == CrystallineRenderTypes.SKY) { cir.setReturnValue(crystalline_sky$SKY); + } else if (layer == CrystallineRenderTypes.SKYBOX) { + cir.setReturnValue(crystalline_sky$SKYBOX); } } } diff --git a/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/compat/sodium/DefaultTerrainRenderPassesMixin.java b/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/compat/sodium/DefaultTerrainRenderPassesMixin.java index 77467a1..e376eb8 100644 --- a/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/compat/sodium/DefaultTerrainRenderPassesMixin.java +++ b/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/compat/sodium/DefaultTerrainRenderPassesMixin.java @@ -23,9 +23,10 @@ public class DefaultTerrainRenderPassesMixin { @Inject(method = "", at = @At("RETURN")) private static void addCrystallineSkyPass(CallbackInfo ci) { - var ALL$ = new TerrainRenderPass[ALL.length + 1]; + var ALL$ = new TerrainRenderPass[ALL.length + 2]; System.arraycopy(ALL, 0, ALL$, 0, ALL.length); ALL$[ALL.length] = new TerrainRenderPass(CrystallineRenderTypes.SKY, false, true); + ALL$[ALL.length + 1] = new TerrainRenderPass(CrystallineRenderTypes.SKYBOX, false, true); ALL = ALL$; } } diff --git a/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/compat/sodium/ShaderChunkRendererMixin.java b/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/compat/sodium/ShaderChunkRendererMixin.java index 59162e2..f005bf8 100644 --- a/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/compat/sodium/ShaderChunkRendererMixin.java +++ b/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/compat/sodium/ShaderChunkRendererMixin.java @@ -25,6 +25,8 @@ public class ShaderChunkRendererMixin { private GlProgram createSkyShader(ShaderChunkRenderer instance, String path, ChunkShaderOptions options, Operation> original) { if (options.pass() == DefaultMaterials.forRenderLayer(CrystallineRenderTypes.SKY).pass) { return original.call(instance, "sodium_compat/block_layer_sky", options); + } else if (options.pass() == DefaultMaterials.forRenderLayer(CrystallineRenderTypes.SKYBOX).pass) { + return original.call(instance, "sodium_compat/block_layer_skybox", options); } return original.call(instance, path, options); @@ -32,7 +34,7 @@ public class ShaderChunkRendererMixin { @WrapOperation(method = "createShader", at = @At(value = "INVOKE", target = "Lnet/minecraft/resources/ResourceLocation;fromNamespaceAndPath(Ljava/lang/String;Ljava/lang/String;)Lnet/minecraft/resources/ResourceLocation;")) private ResourceLocation redirectShaderNamespace(String namespace, String path, Operation original, String pathArg) { - if (pathArg.equals("sodium_compat/block_layer_sky")) { + if (pathArg.equals("sodium_compat/block_layer_sky") || pathArg.equals("sodium_compat/block_layer_skybox")) { namespace = "crystalline_sky"; } @@ -41,7 +43,7 @@ public class ShaderChunkRendererMixin { @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 useSkyShaderInterface(GlProgram.Builder instance, Function factory, Operation> original, String argPath, ChunkShaderOptions argOptions) { - if (argPath.equals("sodium_compat/block_layer_sky")) { + if (argPath.equals("sodium_compat/block_layer_sky") || argPath.equals("sodium_compat/block_layer_skybox")) { factory = (shader) -> new SkyShaderInterface(shader, argOptions); } diff --git a/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/compat/sodium/SodiumWorldRendererMixin.java b/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/compat/sodium/SodiumWorldRendererMixin.java index 9c96ba3..d14f4c3 100644 --- a/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/compat/sodium/SodiumWorldRendererMixin.java +++ b/common/src/main/java/io/github/slimeistdev/crystalline_sky/mixin/client/compat/sodium/SodiumWorldRendererMixin.java @@ -22,8 +22,8 @@ public class SodiumWorldRendererMixin { @Inject(method = "drawChunkLayer", at = @At("RETURN")) private void drawCrystallineLayer(RenderType renderLayer, ChunkRenderMatrices matrices, double x, double y, double z, CallbackInfo ci) { - if (renderLayer != CrystallineRenderTypes.SKY) return; + if (renderLayer != CrystallineRenderTypes.SKY && renderLayer != CrystallineRenderTypes.SKYBOX) return; - renderSectionManager.renderLayer(matrices, DefaultMaterials.forRenderLayer(CrystallineRenderTypes.SKY).pass, x, y, z); + renderSectionManager.renderLayer(matrices, DefaultMaterials.forRenderLayer(renderLayer).pass, x, y, z); } } diff --git a/common/src/main/java/io/github/slimeistdev/crystalline_sky/registry/CrystallineBlocks.java b/common/src/main/java/io/github/slimeistdev/crystalline_sky/registry/CrystallineBlocks.java index 6b6e6e3..c306122 100644 --- a/common/src/main/java/io/github/slimeistdev/crystalline_sky/registry/CrystallineBlocks.java +++ b/common/src/main/java/io/github/slimeistdev/crystalline_sky/registry/CrystallineBlocks.java @@ -48,6 +48,10 @@ public class CrystallineBlocks { .initialProperties(SKY_LIGHT::value) .register(); + public static final BlockHolder SKYBOX_TEST = REGISTRY.block("skybox_test", SkyBlock::new) + .initialProperties(SKY::value) + .register(); + public static void init() {} public static boolean isCrystallineSky(BlockState state) { diff --git a/common/src/main/java/io/github/slimeistdev/crystalline_sky/registry/CrystallineItems.java b/common/src/main/java/io/github/slimeistdev/crystalline_sky/registry/CrystallineItems.java index a7306fa..0129a14 100644 --- a/common/src/main/java/io/github/slimeistdev/crystalline_sky/registry/CrystallineItems.java +++ b/common/src/main/java/io/github/slimeistdev/crystalline_sky/registry/CrystallineItems.java @@ -42,6 +42,10 @@ public class CrystallineItems { .properties(p -> p.rarity(Rarity.EPIC)) .register(); + public static final ItemHolder SKYBOX_TEST = REGISTRY.item(CrystallineBlocks.SKYBOX_TEST) + .properties(p -> p.rarity(Rarity.EPIC)) + .register(); + @SuppressWarnings("SameParameterValue") private static ResourceKey tabKey(String name) { return ResourceKey.create(Registries.CREATIVE_MODE_TAB, ResourceLocation.withDefaultNamespace(name)); @@ -53,6 +57,7 @@ public class CrystallineItems { stacks.add(new ItemStack(SKY)); stacks.add(new ItemStack(WEEPING_SKY)); + stacks.add(new ItemStack(SKYBOX_TEST)); for (int i = 15; i >= 0; i--) { stacks.add(SkyLightBlock.setLightOnStack(new ItemStack(SKY_LIGHT), i)); @@ -67,6 +72,6 @@ public class CrystallineItems { public static void init() {} public static boolean isSky(ItemStack stack) { - return SKY.is(stack) || WEEPING_SKY.is(stack); + return SKY.is(stack) || WEEPING_SKY.is(stack) || SKYBOX_TEST.is(stack); } } diff --git a/common/src/main/java/io/github/slimeistdev/crystalline_sky/registry/client/CrystallineAtlases.java b/common/src/main/java/io/github/slimeistdev/crystalline_sky/registry/client/CrystallineAtlases.java new file mode 100644 index 0000000..34b45e4 --- /dev/null +++ b/common/src/main/java/io/github/slimeistdev/crystalline_sky/registry/client/CrystallineAtlases.java @@ -0,0 +1,24 @@ +package io.github.slimeistdev.crystalline_sky.registry.client; + +import io.github.slimeistdev.crystalline_sky.CrystallineSky; +import net.minecraft.resources.ResourceLocation; + +import java.util.function.BiConsumer; + +public enum CrystallineAtlases { + SKYBOXES("skyboxes"); + + public final ResourceLocation texture; + public final ResourceLocation info; + + CrystallineAtlases(String name) { + texture = CrystallineSky.id("textures/atlas/" + name + ".png"); + info = CrystallineSky.id(name); + } + + public static void register(BiConsumer registrar) { + for (CrystallineAtlases atlas : values()) { + registrar.accept(atlas.texture, atlas.info); + } + } +} diff --git a/common/src/main/java/io/github/slimeistdev/crystalline_sky/registry/client/CrystallineRenderTypes.java b/common/src/main/java/io/github/slimeistdev/crystalline_sky/registry/client/CrystallineRenderTypes.java index f930ab9..79a044d 100644 --- a/common/src/main/java/io/github/slimeistdev/crystalline_sky/registry/client/CrystallineRenderTypes.java +++ b/common/src/main/java/io/github/slimeistdev/crystalline_sky/registry/client/CrystallineRenderTypes.java @@ -5,6 +5,7 @@ import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.VertexFormat; import io.github.slimeistdev.crystalline_sky.mixin_ducks.client.LevelRenderer_Duck; import io.github.slimeistdev.crystalline_sky.mixin_ducks.client.RenderType_Duck; +import io.github.slimeistdev.crystalline_sky.util.SharedRenderVariables; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.Minecraft; @@ -15,12 +16,21 @@ import net.minecraft.client.renderer.RenderType; public abstract class CrystallineRenderTypes extends RenderType { private static final RenderStateShard.EmptyTextureStateShard SKY_TEXTURE = new SkyBufferTexture(); private static final RenderStateShard.ShaderStateShard SKY_PROGRAM = new RenderStateShard.ShaderStateShard(CrystallineShaderInstances::getRenderTypeSkyProgram); + private static final RenderStateShard.ShaderStateShard SKYBOX_PROGRAM = new RenderStateShard.ShaderStateShard(CrystallineShaderInstances::getRenderTypeSkyboxProgram); + public static final RenderStateShard.TextureStateShard SKYBOX_SHEET = new RenderStateShard.TextureStateShard(CrystallineAtlases.SKYBOXES.texture, false, false); + public static final RenderStateShard.OutputStateShard SKYBOX_MATRICES = new RenderStateShard.OutputStateShard("skybox main_target", () -> { + MAIN_TARGET.setupRenderState(); + RenderSystem.setTextureMatrix(SharedRenderVariables.invSkyboxMat); + }, () -> { + RenderSystem.resetTextureMatrix(); + MAIN_TARGET.clearRenderState(); + }); public static final RenderType SKY = create( "crystalline_sky_sky", DefaultVertexFormat.BLOCK, VertexFormat.Mode.QUADS, - 4194304, + 786432, true, false, RenderType.CompositeState.builder() @@ -30,9 +40,26 @@ public abstract class CrystallineRenderTypes extends RenderType { .createCompositeState(true) ); + public static final RenderType SKYBOX = create( + "crystalline_sky_skybox", + DefaultVertexFormat.BLOCK, + VertexFormat.Mode.QUADS, + 786432, + true, + false, + RenderType.CompositeState.builder() + .setLightmapState(LIGHTMAP) + .setShaderState(SKYBOX_PROGRAM) + .setTextureState(SKYBOX_SHEET) + .setOutputState(SKYBOX_MATRICES) + .createCompositeState(true) + ); + static { //noinspection DataFlowIssue ((RenderType_Duck) SKY).crystalline_sky$markAsBlockLayer(); + //noinspection DataFlowIssue + ((RenderType_Duck) SKYBOX).crystalline_sky$markAsBlockLayer(); } private CrystallineRenderTypes(String name, VertexFormat format, VertexFormat.Mode mode, int bufferSize, boolean affectsCrumbling, boolean sortOnUpload, Runnable setupState, Runnable clearState) { diff --git a/common/src/main/java/io/github/slimeistdev/crystalline_sky/registry/client/CrystallineShaderInstances.java b/common/src/main/java/io/github/slimeistdev/crystalline_sky/registry/client/CrystallineShaderInstances.java index 52bc946..c232d47 100644 --- a/common/src/main/java/io/github/slimeistdev/crystalline_sky/registry/client/CrystallineShaderInstances.java +++ b/common/src/main/java/io/github/slimeistdev/crystalline_sky/registry/client/CrystallineShaderInstances.java @@ -8,7 +8,14 @@ public class CrystallineShaderInstances { @ApiStatus.Internal public static @Nullable ShaderInstance renderTypeSkyProgram; + @ApiStatus.Internal + public static @Nullable ShaderInstance renderTypeSkyboxProgram; + public static @Nullable ShaderInstance getRenderTypeSkyProgram() { return renderTypeSkyProgram; } + + public static @Nullable ShaderInstance getRenderTypeSkyboxProgram() { + return renderTypeSkyboxProgram; + } } 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 new file mode 100644 index 0000000..f36909c --- /dev/null +++ b/common/src/main/java/io/github/slimeistdev/crystalline_sky/util/SharedRenderVariables.java @@ -0,0 +1,7 @@ +package io.github.slimeistdev.crystalline_sky.util; + +import org.joml.Matrix4f; + +public class SharedRenderVariables { + public static final Matrix4f invSkyboxMat = new Matrix4f(); +} diff --git a/common/src/main/resources/assets/crystalline_sky/atlases/skyboxes.json b/common/src/main/resources/assets/crystalline_sky/atlases/skyboxes.json new file mode 100644 index 0000000..2bf77ed --- /dev/null +++ b/common/src/main/resources/assets/crystalline_sky/atlases/skyboxes.json @@ -0,0 +1,9 @@ +{ + "sources": [ + { + "type": "directory", + "source": "crystalline_sky_skybox", + "prefix": "crystalline_sky_skybox/" + } + ] +} diff --git a/common/src/main/resources/assets/crystalline_sky/textures/block/skybox_test.png b/common/src/main/resources/assets/crystalline_sky/textures/block/skybox_test.png new file mode 100644 index 0000000..8e5c72b Binary files /dev/null and b/common/src/main/resources/assets/crystalline_sky/textures/block/skybox_test.png differ diff --git a/common/src/main/resources/assets/crystalline_sky/textures/crystalline_sky_skybox/skybox_test.png b/common/src/main/resources/assets/crystalline_sky/textures/crystalline_sky_skybox/skybox_test.png new file mode 100644 index 0000000..f14041a Binary files /dev/null and b/common/src/main/resources/assets/crystalline_sky/textures/crystalline_sky_skybox/skybox_test.png differ diff --git a/common/src/main/resources/assets/crystalline_sky/textures/crystalline_sky_skybox/skybox_test.xcf b/common/src/main/resources/assets/crystalline_sky/textures/crystalline_sky_skybox/skybox_test.xcf new file mode 100644 index 0000000..c180d88 Binary files /dev/null and b/common/src/main/resources/assets/crystalline_sky/textures/crystalline_sky_skybox/skybox_test.xcf differ diff --git a/common/src/main/resources/assets/minecraft/shaders/core/crystalline_sky_rendertype_sky.json b/common/src/main/resources/assets/minecraft/shaders/core/crystalline_sky_rendertype_sky.json index 220fd24..220ca98 100644 --- a/common/src/main/resources/assets/minecraft/shaders/core/crystalline_sky_rendertype_sky.json +++ b/common/src/main/resources/assets/minecraft/shaders/core/crystalline_sky_rendertype_sky.json @@ -2,8 +2,7 @@ "vertex": "crystalline_sky_rendertype_sky", "fragment": "crystalline_sky_rendertype_sky", "samplers": [ - { "name": "Sampler0" }, - { "name": "Sampler2" } + { "name": "Sampler0" } ], "uniforms": [ { "name": "ModelViewMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, diff --git a/common/src/main/resources/assets/minecraft/shaders/core/crystalline_sky_rendertype_skybox.fsh b/common/src/main/resources/assets/minecraft/shaders/core/crystalline_sky_rendertype_skybox.fsh new file mode 100644 index 0000000..595ef43 --- /dev/null +++ b/common/src/main/resources/assets/minecraft/shaders/core/crystalline_sky_rendertype_skybox.fsh @@ -0,0 +1,80 @@ +#version 150 + +#moj_import + +uniform sampler2D Sampler0; + +uniform vec4 ColorModulator; +uniform float FogStart; +uniform float FogEnd; +uniform vec4 FogColor; + +in float vertexDistance; +//in vec4 texProj0; +in vec2 uv0; +in vec2 uv1; +in vec3 vPos; + +out vec4 fragColor; + +#ifndef BAYER_BIAS +#define BAYER_BIAS 0.03125 +#endif + +#ifndef SCALE +#define SCALE 1 +#endif + +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() { + int x = int(gl_FragCoord.x / SCALE) % 4; + int y = int(gl_FragCoord.y / SCALE) % 4; + float bayer = bayerMatrix4x4[y][x]; + + if (ColorModulator.a <= bayer + BAYER_BIAS) { + discard; + } + + vec3 dir = normalize(vPos); + vec3 dabs = abs(dir); + float dmax = max(dabs.x, max(dabs.y, dabs.z)); + vec3 col; + bool positive; + vec2 uv; + vec2 section; + if (dabs.x == dmax) { + col = vec3(1.0, 0.0, 0.0); + positive = dir.x > 0; + uv = positive ? -dir.zy : vec2(dir.z, -dir.y); + section = vec2(positive ? 2.0 : 0.0, 1.0); + } else if (dabs.y == dmax) { + col = vec3(0.0, 1.0, 0.0); + positive = dir.y > 0; + uv = positive ? dir.xz : vec2(dir.x, -dir.z); + section = vec2(positive ? 1.0 : 2.0, 0.0); + } else { + col = vec3(0.0, 0.0, 1.0); + positive = dir.z > 0; + uv = positive ? vec2(dir.x, -dir.y) : -dir.xy; + section = vec2(positive ? 1.0 : 3.0, 1.0); + } + + uv = (uv / dmax + 1.0) / 2.0; + uv = clamp(uv, vec2(0.0), vec2(1.0)); + uv = (uv + section) / vec2(4.0, 2.0); + + col *= positive ? 1.0 : 0.5; + //col = vec3(uv, 0.0); + + vec2 uvR = uv0 + uv * (uv1 - uv0); + + //vec4 color = vec4(col, 1.0) * vec4(ColorModulator.rgb, 1.0); + vec4 color = texture(Sampler0, uvR) * vec4(ColorModulator.rgb, 1.0); + fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); +} diff --git a/common/src/main/resources/assets/minecraft/shaders/core/crystalline_sky_rendertype_skybox.json b/common/src/main/resources/assets/minecraft/shaders/core/crystalline_sky_rendertype_skybox.json new file mode 100644 index 0000000..3a1a51c --- /dev/null +++ b/common/src/main/resources/assets/minecraft/shaders/core/crystalline_sky_rendertype_skybox.json @@ -0,0 +1,18 @@ +{ + "vertex": "crystalline_sky_rendertype_skybox", + "fragment": "crystalline_sky_rendertype_skybox", + "samplers": [ + { "name": "Sampler0" } + ], + "uniforms": [ + { "name": "ModelViewMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, + { "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, + { "name": "ChunkOffset", "type": "float", "count": 3, "values": [ 0.0, 0.0, 0.0 ] }, + { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, + { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, + { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, + { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] }, + { "name": "FogShape", "type": "int", "count": 1, "values": [ 0 ] }, + { "name": "TextureMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } + ] +} diff --git a/common/src/main/resources/assets/minecraft/shaders/core/crystalline_sky_rendertype_skybox.vsh b/common/src/main/resources/assets/minecraft/shaders/core/crystalline_sky_rendertype_skybox.vsh new file mode 100644 index 0000000..80b6d0e --- /dev/null +++ b/common/src/main/resources/assets/minecraft/shaders/core/crystalline_sky_rendertype_skybox.vsh @@ -0,0 +1,39 @@ +#version 150 + +#moj_import + +in vec3 Position; +in vec4 Color; +in vec2 UV0; +in ivec2 UV2; +in vec3 Normal; + +uniform sampler2D Sampler2; + +uniform mat4 ModelViewMat; +uniform mat4 ProjMat; +uniform mat4 TextureMat; +uniform vec3 ChunkOffset; +uniform int FogShape; + +out float vertexDistance; +out vec2 uv0; +out vec2 uv1; +out vec3 vPos; + +void main() { + vec3 pos = Position + ChunkOffset; + gl_Position = ProjMat * ModelViewMat * vec4(pos, 1.0); + + vertexDistance = fog_distance(pos, FogShape); + uv0 = UV0; + uv1 = (Color.ag * 255.0 / 256.0) + (Color.rb / 256.0); + + // somehow this unbreaks view bobbing. No clue *how*, but it does. + vec3 screenPos = gl_Position.xyz / gl_Position.w; + vec4 projected4 = TextureMat * vec4(screenPos, 1.0); + vec3 projected = projected4.xyz / projected4.w; + vec4 projectedO4 = TextureMat * vec4(0.0, 0.0, 1.0, 0.0); + vec3 projectedO = projectedO4.xyz / projectedO4.w; + vPos = projected - projectedO; +} diff --git a/common/src/main/resources/crystalline_sky-common.mixins.json b/common/src/main/resources/crystalline_sky-common.mixins.json index 892cd81..c313f45 100644 --- a/common/src/main/resources/crystalline_sky-common.mixins.json +++ b/common/src/main/resources/crystalline_sky-common.mixins.json @@ -16,6 +16,7 @@ "SkyLightSectionStorageAccessor" ], "client": [ + "client.BlockModelDeserializerMixin", "client.ClientLevelMixin", "client.DebugRendererMixin", "client.GameRendererMixin", diff --git a/fabric/src/main/java/io/github/slimeistdev/crystalline_sky/fabric/CrystallineSkyClientImpl.java b/fabric/src/main/java/io/github/slimeistdev/crystalline_sky/fabric/CrystallineSkyClientImpl.java index 14a5263..92e5d16 100644 --- a/fabric/src/main/java/io/github/slimeistdev/crystalline_sky/fabric/CrystallineSkyClientImpl.java +++ b/fabric/src/main/java/io/github/slimeistdev/crystalline_sky/fabric/CrystallineSkyClientImpl.java @@ -1,8 +1,11 @@ package io.github.slimeistdev.crystalline_sky.fabric; import io.github.slimeistdev.crystalline_sky.CrystallineSkyClient; +import io.github.slimeistdev.crystalline_sky.fabric.events.RegisterMaterialAtlasesEvent; +import io.github.slimeistdev.crystalline_sky.fabric.render_tmp.SkyboxModelLoadingPlugin; import io.github.slimeistdev.crystalline_sky.multiloader.fabric.ItemGroupRegistrationEventImpl; import io.github.slimeistdev.crystalline_sky.registry.CrystallineBlocks; +import io.github.slimeistdev.crystalline_sky.registry.client.CrystallineAtlases; import io.github.slimeistdev.crystalline_sky.registry.client.CrystallineRenderTypes; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.api.EnvType; @@ -23,9 +26,14 @@ public class CrystallineSkyClientImpl implements ClientModInitializer { ItemGroupRegistrationEventImpl.register(); Consumer makeSky = b -> BlockRenderLayerMap.INSTANCE.putBlock(b, CrystallineRenderTypes.SKY); + Consumer makeSkybox = b -> BlockRenderLayerMap.INSTANCE.putBlock(b, CrystallineRenderTypes.SKYBOX); CrystallineBlocks.SKY.onRegistered(makeSky); CrystallineBlocks.WEEPING_SKY.onRegistered(makeSky); + CrystallineBlocks.SKYBOX_TEST.onRegistered(makeSkybox); ClientTickEvents.END_CLIENT_TICK.register(CrystallineSkyClient::onEndTick); + + RegisterMaterialAtlasesEvent.EVENT.register(ctx -> CrystallineAtlases.register(ctx::addAtlas)); + SkyboxModelLoadingPlugin.register(); } } diff --git a/fabric/src/main/java/io/github/slimeistdev/crystalline_sky/fabric/datagen/providers/CrystallineSkyModelProvider.java b/fabric/src/main/java/io/github/slimeistdev/crystalline_sky/fabric/datagen/providers/CrystallineSkyModelProvider.java index 08a1e28..075f96a 100644 --- a/fabric/src/main/java/io/github/slimeistdev/crystalline_sky/fabric/datagen/providers/CrystallineSkyModelProvider.java +++ b/fabric/src/main/java/io/github/slimeistdev/crystalline_sky/fabric/datagen/providers/CrystallineSkyModelProvider.java @@ -5,8 +5,10 @@ import com.google.gson.JsonObject; import io.github.slimeistdev.crystalline_sky.CrystallineSky; import io.github.slimeistdev.crystalline_sky.registry.CrystallineBlocks; import io.github.slimeistdev.crystalline_sky.registry.CrystallineItems; +import io.github.slimeistdev.crystalline_sky.registry.client.CrystallineAtlases; import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput; import net.fabricmc.fabric.api.datagen.v1.provider.FabricModelProvider; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.data.models.BlockModelGenerators; import net.minecraft.data.models.ItemModelGenerators; import net.minecraft.data.models.blockstates.MultiVariantGenerator; @@ -24,8 +26,20 @@ import net.minecraft.world.level.block.state.properties.BlockStateProperties; import java.util.Locale; +import static net.minecraft.data.models.model.TexturedModel.createDefault; + @SuppressWarnings("SameParameterValue") public class CrystallineSkyModelProvider extends FabricModelProvider { + private static ResourceLocation getSkyboxBlockTexture(Block block) { + ResourceLocation resourceLocation = BuiltInRegistries.BLOCK.getKey(block); + return resourceLocation.withPrefix("crystalline_sky_skybox/"); + } + + private static final TexturedModel.Provider SKYBOX_CUBE = createDefault( + block -> TextureMapping.cube(getSkyboxBlockTexture(block)), + ModelTemplates.CUBE_ALL + ); + public CrystallineSkyModelProvider(FabricDataOutput output) { super(output); } @@ -38,6 +52,8 @@ public class CrystallineSkyModelProvider extends FabricModelProvider { gen.createAirLikeBlock(CrystallineBlocks.WEEPING_SKY_LIGHT.value(), CrystallineItems.WEEPING_SKY_LIGHT.value()); gen.createSimpleFlatItemModel(CrystallineItems.WEEPING_SKY_LIGHT.value()); + + registerSkyboxBlock(gen, CrystallineBlocks.SKYBOX_TEST.value()); } private void registerSkyBlock(BlockModelGenerators gen, Block block) { @@ -54,6 +70,21 @@ public class CrystallineSkyModelProvider extends FabricModelProvider { gen.createSimpleFlatItemModel(block); } + private void registerSkyboxBlock(BlockModelGenerators gen, Block block) { + gen.blockStateOutput.accept(BlockModelGenerators.createSimpleBlock(block, SKYBOX_CUBE.create( + block, + (id, json) -> { + gen.modelOutput.accept(id, () -> { + JsonObject root = json.get().getAsJsonObject(); + root.addProperty("render_type", CrystallineSky.id("skybox").toString()); + root.addProperty(CrystallineSky.id("atlas").toString(), CrystallineAtlases.SKYBOXES.texture.toString()); + return root; + }); + } + ))); + gen.createSimpleFlatItemModel(block); + } + private void registerSkyLightBlock(BlockModelGenerators gen, Block block, Item item) { gen.skipAutoItemBlock(block); PropertyDispatch.C1 singleProperty = PropertyDispatch.property(BlockStateProperties.LEVEL); diff --git a/fabric/src/main/java/io/github/slimeistdev/crystalline_sky/fabric/events/RegisterMaterialAtlasesEvent.java b/fabric/src/main/java/io/github/slimeistdev/crystalline_sky/fabric/events/RegisterMaterialAtlasesEvent.java new file mode 100644 index 0000000..4e3edc5 --- /dev/null +++ b/fabric/src/main/java/io/github/slimeistdev/crystalline_sky/fabric/events/RegisterMaterialAtlasesEvent.java @@ -0,0 +1,40 @@ +package io.github.slimeistdev.crystalline_sky.fabric.events; + +import net.fabricmc.fabric.api.event.Event; +import net.fabricmc.fabric.api.event.EventFactory; +import net.minecraft.resources.ResourceLocation; +import org.jetbrains.annotations.ApiStatus; + +import java.util.HashMap; +import java.util.Map; + +public interface RegisterMaterialAtlasesEvent { + Event EVENT = EventFactory.createArrayBacked(RegisterMaterialAtlasesEvent.class, (callbacks) -> (context) -> { + for (RegisterMaterialAtlasesEvent callback : callbacks) { + callback.run(context); + } + }); + + @ApiStatus.Internal + static Map gatherMaterialAtlases(Map vanillaAtlases) { + Map atlases = new HashMap<>(vanillaAtlases); + EVENT.invoker().run(((atlasLocation, atlasInfoLocation) -> { + ResourceLocation oldAtlasInfoLoc = atlases.putIfAbsent(atlasLocation, atlasInfoLocation); + if (oldAtlasInfoLoc != null) { + throw new IllegalStateException(String.format( + "Duplicate registration of atlas: %s (old info: %s, new info: %s)", + atlasLocation, + oldAtlasInfoLoc, + atlasInfoLocation)); + } + })); + return Map.copyOf(atlases); + } + + void run(Context context); + + @FunctionalInterface + interface Context { + void addAtlas(ResourceLocation atlasLocation, ResourceLocation atlasInfoLocation); + } +} diff --git a/fabric/src/main/java/io/github/slimeistdev/crystalline_sky/fabric/mixin/client/ModelManagerMixin.java b/fabric/src/main/java/io/github/slimeistdev/crystalline_sky/fabric/mixin/client/ModelManagerMixin.java new file mode 100644 index 0000000..d2afe5d --- /dev/null +++ b/fabric/src/main/java/io/github/slimeistdev/crystalline_sky/fabric/mixin/client/ModelManagerMixin.java @@ -0,0 +1,21 @@ +package io.github.slimeistdev.crystalline_sky.fabric.mixin.client; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import io.github.slimeistdev.crystalline_sky.fabric.events.RegisterMaterialAtlasesEvent; +import net.minecraft.client.renderer.texture.TextureManager; +import net.minecraft.client.resources.model.AtlasSet; +import net.minecraft.client.resources.model.ModelManager; +import net.minecraft.resources.ResourceLocation; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import java.util.Map; + +@Mixin(ModelManager.class) +public class ModelManagerMixin { + @WrapOperation(method = "", at = @At(value = "NEW", target = "(Ljava/util/Map;Lnet/minecraft/client/renderer/texture/TextureManager;)Lnet/minecraft/client/resources/model/AtlasSet;")) + private AtlasSet addCustomAtlases(Map atlasMap, TextureManager textureManager, Operation original) { + return original.call(RegisterMaterialAtlasesEvent.gatherMaterialAtlases(atlasMap), textureManager); + } +} diff --git a/fabric/src/main/java/io/github/slimeistdev/crystalline_sky/fabric/mixin/client/compat/axiom/ChunkRenderOverrider_AxiomChunkOverrideLayerMixin.java b/fabric/src/main/java/io/github/slimeistdev/crystalline_sky/fabric/mixin/client/compat/axiom/ChunkRenderOverrider_AxiomChunkOverrideLayerMixin.java index a301106..067f952 100644 --- a/fabric/src/main/java/io/github/slimeistdev/crystalline_sky/fabric/mixin/client/compat/axiom/ChunkRenderOverrider_AxiomChunkOverrideLayerMixin.java +++ b/fabric/src/main/java/io/github/slimeistdev/crystalline_sky/fabric/mixin/client/compat/axiom/ChunkRenderOverrider_AxiomChunkOverrideLayerMixin.java @@ -15,7 +15,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; public class ChunkRenderOverrider_AxiomChunkOverrideLayerMixin { @Inject(method = "fromVanilla", at = @At("HEAD"), cancellable = true) private static void unexplodeSky(RenderType layer, CallbackInfoReturnable cir) { - if (layer == CrystallineRenderTypes.SKY) { + if (layer == CrystallineRenderTypes.SKY || layer == CrystallineRenderTypes.SKYBOX) { cir.setReturnValue(ChunkRenderOverrider.AxiomChunkOverrideLayer.CUTOUT_MIPPED); } } diff --git a/fabric/src/main/java/io/github/slimeistdev/crystalline_sky/fabric/render_tmp/SkyboxBakedModel.java b/fabric/src/main/java/io/github/slimeistdev/crystalline_sky/fabric/render_tmp/SkyboxBakedModel.java new file mode 100644 index 0000000..41bcd26 --- /dev/null +++ b/fabric/src/main/java/io/github/slimeistdev/crystalline_sky/fabric/render_tmp/SkyboxBakedModel.java @@ -0,0 +1,116 @@ +package io.github.slimeistdev.crystalline_sky.fabric.render_tmp; + +import net.fabricmc.fabric.api.renderer.v1.Renderer; +import net.fabricmc.fabric.api.renderer.v1.RendererAccess; +import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial; +import net.fabricmc.fabric.api.renderer.v1.material.ShadeMode; +import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter; +import net.fabricmc.fabric.api.renderer.v1.model.ForwardingBakedModel; +import net.fabricmc.fabric.api.renderer.v1.model.ModelHelper; +import net.fabricmc.fabric.api.renderer.v1.render.RenderContext; +import net.fabricmc.fabric.api.util.TriState; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.state.BlockState; + +import java.util.List; +import java.util.function.Supplier; + +public class SkyboxBakedModel extends ForwardingBakedModel { + private static final RenderMaterial FULL_BRIGHT_MATERIAL; + static { + Renderer renderer = RendererAccess.INSTANCE.getRenderer(); + if (renderer == null) { + FULL_BRIGHT_MATERIAL = null; + } else { + FULL_BRIGHT_MATERIAL = renderer.materialFinder() + .shadeMode(ShadeMode.VANILLA) + .ambientOcclusion(TriState.FALSE) + .emissive(true) + .disableDiffuse(true) + .disableColorIndex(true) + .find(); + } + } + + public SkyboxBakedModel(BakedModel wrapped) { + super(wrapped); + } + + @Override + public boolean useAmbientOcclusion() { + return false; + } + + @Override + public boolean usesBlockLight() { + return false; + } + + @Override + public boolean isVanillaAdapter() { + return false; + } + + // copied from net.fabricmc.fabric.impl.renderer.VanillaModelEncoder.emitBlockQuads + @Override + public void emitBlockQuads(BlockAndTintGetter blockView, BlockState state, BlockPos pos, Supplier randomSupplier, RenderContext context) { + /*TextureAtlasSprite sprite = getParticleIcon(); + float u0 = sprite.getU0(); + float v0 = sprite.getV0(); + int u1 = (int) (sprite.getU1() * 0xffff); + int v1 = (int) (sprite.getV1() * 0xffff); + + int color = (u1 << 16) | v1; + var emitter = context.getEmitter() + .square(Direction.UP, 0, 0, 1, 1, 0) + .material(FULLBRIGHT_MATERIAL); + for (int i = 0; i < 4; i++) { + emitter + .color(i, color) + .lightmap(i, LightTexture.FULL_BRIGHT) + .normal(i, 0, 1, 0) + .uv(i, u0, v0); + } + emitter.emit();*/ + + QuadEmitter emitter = context.getEmitter(); + + for (int i = 0; i <= ModelHelper.NULL_FACE_ID; i++) { + final Direction cullFace = ModelHelper.faceFromIndex(i); + + if (!context.hasTransform() && context.isFaceCulled(cullFace)) { + // Skip entire quad list if possible + continue; + } + + final List quads = getQuads(state, cullFace, randomSupplier.get()); + + for (final BakedQuad q : quads) { + emitter.fromVanilla(q, FULL_BRIGHT_MATERIAL, cullFace); // fixme view bobbing breaks projection, use TextureMatrix to pass a view projection matrix along :) + TextureAtlasSprite sprite = q.getSprite(); + float u0 = sprite.getU0(); + float v0 = sprite.getV0(); + int u1 = (int) (sprite.getU1() * 0xffff); + int v1 = (int) (sprite.getV1() * 0xffff); + int uv1 = (u1 << 16) | v1; + for (int j = 0; j < 4; j++) { + emitter.uv(j, u0, v0); + emitter.color(j, uv1); + } + emitter.emit(); + } + } + } + + @Override + public void emitItemQuads(ItemStack stack, Supplier randomSupplier, RenderContext context) { + super.emitItemQuads(stack, randomSupplier, context); + } +} diff --git a/fabric/src/main/java/io/github/slimeistdev/crystalline_sky/fabric/render_tmp/SkyboxModelLoadingPlugin.java b/fabric/src/main/java/io/github/slimeistdev/crystalline_sky/fabric/render_tmp/SkyboxModelLoadingPlugin.java new file mode 100644 index 0000000..2afe44b --- /dev/null +++ b/fabric/src/main/java/io/github/slimeistdev/crystalline_sky/fabric/render_tmp/SkyboxModelLoadingPlugin.java @@ -0,0 +1,28 @@ +package io.github.slimeistdev.crystalline_sky.fabric.render_tmp; + +import io.github.slimeistdev.crystalline_sky.CrystallineSky; +import net.fabricmc.fabric.api.client.model.loading.v1.ModelLoadingPlugin; +import net.minecraft.resources.ResourceLocation; + +public class SkyboxModelLoadingPlugin implements ModelLoadingPlugin { + private SkyboxModelLoadingPlugin() {} + + @Override + public void onInitializeModelLoader(Context pluginContext) { + pluginContext.modifyModelAfterBake().register((model, ctx) -> { + if (model == null) return null; + + ResourceLocation id = ctx.resourceId(); + if (id == null) { + id = ctx.topLevelId().id(); + } + if (!id.equals(CrystallineSky.id("block/skybox_test"))) return model; + + return new SkyboxBakedModel(model); + }); + } + + public static void register() { + ModelLoadingPlugin.register(new SkyboxModelLoadingPlugin()); + } +} diff --git a/fabric/src/main/resources/crystalline_sky.mixins.json b/fabric/src/main/resources/crystalline_sky.mixins.json index cbb1742..97f5060 100644 --- a/fabric/src/main/resources/crystalline_sky.mixins.json +++ b/fabric/src/main/resources/crystalline_sky.mixins.json @@ -10,6 +10,7 @@ "mixins": [ ], "client": [ + "client.ModelManagerMixin", "client.RenderTypeMixin", "client.compat.axiom.ChunkRenderOverrider_AxiomChunkOverrideLayerMixin" ], diff --git a/gradle.properties b/gradle.properties index 4f61ea4..f239bfd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -26,5 +26,5 @@ modVersion=0.1.2 compatibleVersions=1.21.1 # mod compat -enable_sodium=true +enable_sodium=false enable_axiom=false diff --git a/neoforge/src/main/java/io/github/slimeistdev/crystalline_sky/neoforge/CrystallineSkyClientImpl.java b/neoforge/src/main/java/io/github/slimeistdev/crystalline_sky/neoforge/CrystallineSkyClientImpl.java index 5a49d44..5d1a44e 100644 --- a/neoforge/src/main/java/io/github/slimeistdev/crystalline_sky/neoforge/CrystallineSkyClientImpl.java +++ b/neoforge/src/main/java/io/github/slimeistdev/crystalline_sky/neoforge/CrystallineSkyClientImpl.java @@ -4,6 +4,7 @@ import io.github.slimeistdev.crystalline_sky.CrystallineSky; import io.github.slimeistdev.crystalline_sky.CrystallineSkyClient; import io.github.slimeistdev.crystalline_sky.multiloader.neoforge.ItemGroupRegistrationEventImpl; import io.github.slimeistdev.crystalline_sky.registry.CrystallineItems; +import io.github.slimeistdev.crystalline_sky.registry.client.CrystallineAtlases; import io.github.slimeistdev.crystalline_sky.registry.client.CrystallineRenderTypes; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.RenderType; @@ -12,6 +13,7 @@ import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.fml.common.EventBusSubscriber; import net.neoforged.neoforge.client.event.ClientTickEvent; import net.neoforged.neoforge.client.event.RegisterKeyMappingsEvent; +import net.neoforged.neoforge.client.event.RegisterMaterialAtlasesEvent; import net.neoforged.neoforge.client.event.RegisterNamedRenderTypesEvent; import net.neoforged.neoforge.event.BuildCreativeModeTabContentsEvent; @@ -25,6 +27,7 @@ public class CrystallineSkyClientImpl { public static void registerNamedRenderTypes(RegisterNamedRenderTypesEvent event) { // NOTE: entity render type is just a placeholder, sky rendering isn't supported for entities event.register(CrystallineSky.id("sky"), CrystallineRenderTypes.SKY, RenderType.entitySolid(CrystallineSky.id("sky"))); + event.register(CrystallineSky.id("skybox"), CrystallineRenderTypes.SKYBOX, RenderType.entitySolid(CrystallineSky.id("skybox"))); } @SubscribeEvent @@ -41,4 +44,9 @@ public class CrystallineSkyClientImpl { public static void buildCreativeModeTabContents(BuildCreativeModeTabContentsEvent event) { CrystallineItems.onItemGroupRegistration(new ItemGroupRegistrationEventImpl(event)); } + + @SubscribeEvent + public static void registerAtlases(RegisterMaterialAtlasesEvent event) { + CrystallineAtlases.register(event::register); + } }