basic functioning on fabric
This commit is contained in:
techno-sam
2026-04-25 13:00:26 +02:00
parent 62ed623c1f
commit bad5f29b4e
39 changed files with 602 additions and 19 deletions
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "crystalline_sky:block/skybox_test"
}
}
}
@@ -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"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "crystalline_sky:block/skybox_test"
}
}
@@ -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<ResourceLocation> original, JsonObject json) {
if (json.has("crystalline_sky:atlas")) {
return ResourceLocation.parse(json.get("crystalline_sky:atlas").getAsString());
} else {
return original.call();
}
}
}
@@ -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 <E extends Pair<ShaderInstance, Consumer<ShaderInstance>>> boolean loadSkyProgram(
List<E> instance,
@@ -29,6 +50,32 @@ public class GameRendererMixin {
"crystalline_sky_rendertype_sky",
DefaultVertexFormat.BLOCK
), (Consumer<ShaderInstance>) program -> CrystallineShaderInstances.renderTypeSkyProgram = program));
original.call(instance, Pair.of(new ShaderInstance(
factory,
"crystalline_sky_rendertype_skybox",
DefaultVertexFormat.BLOCK
), (Consumer<ShaderInstance>) 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<Matrix4f> 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<Void> 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);
}
}
@@ -134,5 +134,6 @@ public abstract class LevelRendererMixin implements LevelRenderer_Duck {
Matrix4f matrix4f, Matrix4f positionMatrix, Operation<Void> 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);
}
}
@@ -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())
@@ -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<Material> cir) {
if (layer == CrystallineRenderTypes.SKY) {
cir.setReturnValue(crystalline_sky$SKY);
} else if (layer == CrystallineRenderTypes.SKYBOX) {
cir.setReturnValue(crystalline_sky$SKYBOX);
}
}
}
@@ -23,9 +23,10 @@ public class DefaultTerrainRenderPassesMixin {
@Inject(method = "<clinit>", 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$;
}
}
@@ -25,6 +25,8 @@ public class ShaderChunkRendererMixin {
private GlProgram<ChunkShaderInterface> createSkyShader(ShaderChunkRenderer instance, String path, ChunkShaderOptions options, Operation<GlProgram<ChunkShaderInterface>> 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<ResourceLocation> 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<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")) {
if (argPath.equals("sodium_compat/block_layer_sky") || argPath.equals("sodium_compat/block_layer_skybox")) {
factory = (shader) -> new SkyShaderInterface(shader, argOptions);
}
@@ -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);
}
}
@@ -48,6 +48,10 @@ public class CrystallineBlocks {
.initialProperties(SKY_LIGHT::value)
.register();
public static final BlockHolder<SkyBlock> SKYBOX_TEST = REGISTRY.block("skybox_test", SkyBlock::new)
.initialProperties(SKY::value)
.register();
public static void init() {}
public static boolean isCrystallineSky(BlockState state) {
@@ -42,6 +42,10 @@ public class CrystallineItems {
.properties(p -> p.rarity(Rarity.EPIC))
.register();
public static final ItemHolder<BlockItem> SKYBOX_TEST = REGISTRY.item(CrystallineBlocks.SKYBOX_TEST)
.properties(p -> p.rarity(Rarity.EPIC))
.register();
@SuppressWarnings("SameParameterValue")
private static ResourceKey<CreativeModeTab> 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);
}
}
@@ -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<ResourceLocation, ResourceLocation> registrar) {
for (CrystallineAtlases atlas : values()) {
registrar.accept(atlas.texture, atlas.info);
}
}
}
@@ -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) {
@@ -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;
}
}
@@ -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();
}
@@ -0,0 +1,9 @@
{
"sources": [
{
"type": "directory",
"source": "crystalline_sky_skybox",
"prefix": "crystalline_sky_skybox/"
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

@@ -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 ] },
@@ -0,0 +1,80 @@
#version 150
#moj_import <fog.glsl>
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);
}
@@ -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 ] }
]
}
@@ -0,0 +1,39 @@
#version 150
#moj_import <fog.glsl>
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;
}
@@ -16,6 +16,7 @@
"SkyLightSectionStorageAccessor"
],
"client": [
"client.BlockModelDeserializerMixin",
"client.ClientLevelMixin",
"client.DebugRendererMixin",
"client.GameRendererMixin",
@@ -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<Block> makeSky = b -> BlockRenderLayerMap.INSTANCE.putBlock(b, CrystallineRenderTypes.SKY);
Consumer<Block> 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();
}
}
@@ -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<Integer> singleProperty = PropertyDispatch.property(BlockStateProperties.LEVEL);
@@ -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<RegisterMaterialAtlasesEvent> EVENT = EventFactory.createArrayBacked(RegisterMaterialAtlasesEvent.class, (callbacks) -> (context) -> {
for (RegisterMaterialAtlasesEvent callback : callbacks) {
callback.run(context);
}
});
@ApiStatus.Internal
static Map<ResourceLocation, ResourceLocation> gatherMaterialAtlases(Map<ResourceLocation, ResourceLocation> vanillaAtlases) {
Map<ResourceLocation, ResourceLocation> 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);
}
}
@@ -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 = "<init>", at = @At(value = "NEW", target = "(Ljava/util/Map;Lnet/minecraft/client/renderer/texture/TextureManager;)Lnet/minecraft/client/resources/model/AtlasSet;"))
private AtlasSet addCustomAtlases(Map<ResourceLocation, ResourceLocation> atlasMap, TextureManager textureManager, Operation<AtlasSet> original) {
return original.call(RegisterMaterialAtlasesEvent.gatherMaterialAtlases(atlasMap), textureManager);
}
}
@@ -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<ChunkRenderOverrider.AxiomChunkOverrideLayer> cir) {
if (layer == CrystallineRenderTypes.SKY) {
if (layer == CrystallineRenderTypes.SKY || layer == CrystallineRenderTypes.SKYBOX) {
cir.setReturnValue(ChunkRenderOverrider.AxiomChunkOverrideLayer.CUTOUT_MIPPED);
}
}
@@ -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<RandomSource> 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<BakedQuad> 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<RandomSource> randomSupplier, RenderContext context) {
super.emitItemQuads(stack, randomSupplier, context);
}
}
@@ -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());
}
}
@@ -10,6 +10,7 @@
"mixins": [
],
"client": [
"client.ModelManagerMixin",
"client.RenderTypeMixin",
"client.compat.axiom.ChunkRenderOverrider_AxiomChunkOverrideLayerMixin"
],
+1 -1
View File
@@ -26,5 +26,5 @@ modVersion=0.1.2
compatibleVersions=1.21.1
# mod compat
enable_sodium=true
enable_sodium=false
enable_axiom=false
@@ -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);
}
}