From f942c31971a01bf722fe961252c46c7810b02ec7 Mon Sep 17 00:00:00 2001 From: MoePus <547007249@qq.com> Date: Sat, 26 Sep 2026 03:11:43 +0900 Subject: [PATCH 1/4] Respect shaderpack shadow ownership --- .../flywheel/lib/visual/component/ShadowComponent.java | 5 ++++- .../dev/engine_room/vanillin/elements/ShadowElement.java | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/visual/component/ShadowComponent.java b/common/src/lib/java/dev/engine_room/flywheel/lib/visual/component/ShadowComponent.java index 2a86de5eca..918e62f4a0 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/visual/component/ShadowComponent.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/visual/component/ShadowComponent.java @@ -17,6 +17,7 @@ import dev.engine_room.flywheel.lib.model.QuadMesh; import dev.engine_room.flywheel.lib.model.SingleMeshModel; import dev.engine_room.flywheel.lib.visual.util.InstanceRecycler; +import dev.engine_room.flywheel.lib.util.ShadersModHelper; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.Lightmap; import net.minecraft.client.renderer.texture.OverlayTexture; @@ -56,6 +57,7 @@ public final class ShadowComponent implements EntityComponent { private final VisualizationContext context; private final Entity entity; private final Level level; + private final boolean shaderPackShadowSuppressed; private final BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(); private final InstanceRecycler instances = new InstanceRecycler<>(this::createInstance); @@ -68,6 +70,7 @@ public ShadowComponent(VisualizationContext context, Entity entity) { this.context = context; this.entity = entity; this.level = entity.level(); + this.shaderPackShadowSuppressed = ShadersModHelper.isShaderPackInUse(); } private ShadowInstance createInstance() { @@ -118,7 +121,7 @@ public void beginFrame(DynamicVisual.Context context) { boolean shadowsEnabled = Minecraft.getInstance().options.entityShadows() .get(); - if (shadowsEnabled && radius > 0 && !entity.isInvisible()) { + if (shadowsEnabled && !shaderPackShadowSuppressed && radius > 0 && !entity.isInvisible()) { setupInstances(context); } diff --git a/vanillin/common/src/main/java/dev/engine_room/vanillin/elements/ShadowElement.java b/vanillin/common/src/main/java/dev/engine_room/vanillin/elements/ShadowElement.java index 9bf9fafbb7..5a193b8017 100644 --- a/vanillin/common/src/main/java/dev/engine_room/vanillin/elements/ShadowElement.java +++ b/vanillin/common/src/main/java/dev/engine_room/vanillin/elements/ShadowElement.java @@ -19,6 +19,7 @@ import dev.engine_room.flywheel.lib.visual.AbstractVisual; import dev.engine_room.flywheel.lib.visual.SimpleDynamicVisual; import dev.engine_room.flywheel.lib.visual.util.InstanceRecycler; +import dev.engine_room.flywheel.lib.util.ShadersModHelper; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.Lightmap; import net.minecraft.client.renderer.texture.OverlayTexture; @@ -55,6 +56,7 @@ public final class ShadowElement extends AbstractVisual implements SimpleDynamic private static final Model SHADOW_MODEL = new SingleMeshModel(ShadowMesh.INSTANCE, SHADOW_MATERIAL); private final Entity entity; + private final boolean shaderPackShadowSuppressed; private final BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(); private final InstanceRecycler instances = new InstanceRecycler<>(this::createInstance); @@ -66,6 +68,7 @@ public final class ShadowElement extends AbstractVisual implements SimpleDynamic public ShadowElement(VisualizationContext ctx, Entity entity, float partialTick, Config config) { super(ctx, entity.level(), partialTick); this.entity = entity; + shaderPackShadowSuppressed = ShadersModHelper.isShaderPackInUse(); radius(config.radius); strength(config.strength); } @@ -118,7 +121,7 @@ public void beginFrame(DynamicVisual.Context context) { boolean shadowsEnabled = Minecraft.getInstance().options.entityShadows() .get(); - if (shadowsEnabled && radius > 0 && !entity.isInvisible()) { + if (shadowsEnabled && !shaderPackShadowSuppressed && radius > 0 && !entity.isInvisible()) { setupInstances(context); } From 9d3d53a08fb686f195461df2aba74648134e2423 Mon Sep 17 00:00:00 2001 From: MoePus <547007249@qq.com> Date: Sat, 26 Sep 2026 03:12:04 +0900 Subject: [PATCH 2/4] Match vanilla shadow UV orientation --- .../resources/assets/flywheel/flywheel/instance/shadow.vert | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/common/src/lib/resources/assets/flywheel/flywheel/instance/shadow.vert b/common/src/lib/resources/assets/flywheel/flywheel/instance/shadow.vert index 97649f6249..67d030f6eb 100644 --- a/common/src/lib/resources/assets/flywheel/flywheel/instance/shadow.vert +++ b/common/src/lib/resources/assets/flywheel/flywheel/instance/shadow.vert @@ -1,10 +1,12 @@ +// Vanilla reference: net/minecraft/client/renderer/entity/EntityRenderDispatcher.java +// (renderShadow -> renderBlockShadow -> shadowVertex). void flw_instanceVertex(in FlwInstance i) { // Stretch the quad to the shape of the block the shadow is being cast on, // then move it to the correct position. flw_vertexPos.xyz = flw_vertexPos.xyz * vec3(i.size.x, 1., i.size.y) + i.pos; // Uvs are calculated based on the distance to the entity. - flw_vertexTexCoord = (flw_vertexPos.xz - i.entityPosXZ) * 0.5 / i.radius + 0.5; + flw_vertexTexCoord = (i.entityPosXZ - flw_vertexPos.xz) * 0.5 / i.radius + 0.5; flw_vertexColor.a = i.alpha; } From 6e9ef9c55c31414ea35f850ee84af3dc85a93e63 Mon Sep 17 00:00:00 2001 From: MoePus <547007249@qq.com> Date: Sat, 26 Sep 2026 03:11:17 +0900 Subject: [PATCH 3/4] Clip entity shadows to their radius --- .../lib/visual/component/ShadowComponent.java | 19 +++++++++++++------ .../vanillin/elements/ShadowElement.java | 19 +++++++++++++------ 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/visual/component/ShadowComponent.java b/common/src/lib/java/dev/engine_room/flywheel/lib/visual/component/ShadowComponent.java index 918e62f4a0..a5955d86d0 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/visual/component/ShadowComponent.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/visual/component/ShadowComponent.java @@ -184,18 +184,25 @@ private void setupInstance(ChunkAccess chunk, MutableBlockPos pos, float entityX int y = pos.getY() - renderOrigin.getY() + 1; // +1 since we moved the pos down. int z = pos.getZ() - renderOrigin.getZ(); - double minX = x + shape.min(Axis.X); + double entityLocalX = entityX - renderOrigin.getX(); + double entityLocalZ = entityZ - renderOrigin.getZ(); + // Do not submit a whole block for a small-radius shadow; clipping here keeps the + // primitive and its UV domain bounded by the same radius. + double minX = Math.max(x + shape.min(Axis.X), entityLocalX - radius); double minY = y + shape.min(Axis.Y); - double minZ = z + shape.min(Axis.Z); - double maxX = x + shape.max(Axis.X); - double maxZ = z + shape.max(Axis.Z); + double minZ = Math.max(z + shape.min(Axis.Z), entityLocalZ - radius); + double maxX = Math.min(x + shape.max(Axis.X), entityLocalX + radius); + double maxZ = Math.min(z + shape.max(Axis.Z), entityLocalZ + radius); + if (minX >= maxX || minZ >= maxZ) { + return; + } var instance = instances.get(); instance.x = (float) minX; instance.y = (float) minY; instance.z = (float) minZ; - instance.entityX = entityX - renderOrigin.getX(); - instance.entityZ = entityZ - renderOrigin.getZ(); + instance.entityX = (float) entityLocalX; + instance.entityZ = (float) entityLocalZ; instance.sizeX = (float) (maxX - minX); instance.sizeZ = (float) (maxZ - minZ); instance.alpha = alpha; diff --git a/vanillin/common/src/main/java/dev/engine_room/vanillin/elements/ShadowElement.java b/vanillin/common/src/main/java/dev/engine_room/vanillin/elements/ShadowElement.java index 5a193b8017..f53601a56f 100644 --- a/vanillin/common/src/main/java/dev/engine_room/vanillin/elements/ShadowElement.java +++ b/vanillin/common/src/main/java/dev/engine_room/vanillin/elements/ShadowElement.java @@ -184,18 +184,25 @@ private void setupInstance(ChunkAccess chunk, MutableBlockPos pos, double entity int y = pos.getY() - renderOrigin.getY() + 1; // +1 since we moved the pos down. int z = pos.getZ() - renderOrigin.getZ(); - double minX = x + shape.min(Axis.X); + double entityLocalX = entityX - renderOrigin.getX(); + double entityLocalZ = entityZ - renderOrigin.getZ(); + // Do not submit a whole block for a small-radius shadow; clipping here keeps the + // primitive and its UV domain bounded by the same radius. + double minX = Math.max(x + shape.min(Axis.X), entityLocalX - radius); double minY = y + shape.min(Axis.Y); - double minZ = z + shape.min(Axis.Z); - double maxX = x + shape.max(Axis.X); - double maxZ = z + shape.max(Axis.Z); + double minZ = Math.max(z + shape.min(Axis.Z), entityLocalZ - radius); + double maxX = Math.min(x + shape.max(Axis.X), entityLocalX + radius); + double maxZ = Math.min(z + shape.max(Axis.Z), entityLocalZ + radius); + if (minX >= maxX || minZ >= maxZ) { + return; + } var instance = instances.get(); instance.x = (float) minX; instance.y = (float) minY; instance.z = (float) minZ; - instance.entityX = (float) (entityX - renderOrigin.getX()); - instance.entityZ = (float) (entityZ - renderOrigin.getZ()); + instance.entityX = (float) entityLocalX; + instance.entityZ = (float) entityLocalZ; instance.sizeX = (float) (maxX - minX); instance.sizeZ = (float) (maxZ - minZ); instance.alpha = alpha; From a0fe09c8c1e0c62806b8aaf44ff84a99f0f72ca1 Mon Sep 17 00:00:00 2001 From: MoePus <547007249@qq.com> Date: Sun, 27 Sep 2026 02:08:20 +0900 Subject: [PATCH 4/4] update shadow UV vanilla reference --- .../resources/assets/flywheel/flywheel/instance/shadow.vert | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/common/src/lib/resources/assets/flywheel/flywheel/instance/shadow.vert b/common/src/lib/resources/assets/flywheel/flywheel/instance/shadow.vert index 67d030f6eb..99d99e47b7 100644 --- a/common/src/lib/resources/assets/flywheel/flywheel/instance/shadow.vert +++ b/common/src/lib/resources/assets/flywheel/flywheel/instance/shadow.vert @@ -1,5 +1,4 @@ -// Vanilla reference: net/minecraft/client/renderer/entity/EntityRenderDispatcher.java -// (renderShadow -> renderBlockShadow -> shadowVertex). +// Vanilla reference: net.minecraft.client.renderer.feature.ShadowFeatureRenderer#renderTranslucent void flw_instanceVertex(in FlwInstance i) { // Stretch the quad to the shape of the block the shadow is being cast on, // then move it to the correct position.