From 0ce9d2086ae76a4723dba8927244887e965cdbb6 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 3 Jul 2026 13:37:51 +0000 Subject: [PATCH 1/4] Fix translucent items vanishing behind water and glass (v1.2.0) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Translucent entities (armor stands and the items they hold or wear) render in a separate pass from translucent blocks such as water and glass. Vanilla only depth-sorts render layers within each pass, never across them, so a translucent item near a translucent block has no defined blend order and its alpha pixels composite incorrectly — most visibly, the item disappears or is clipped behind water/glass. Add ItemTranslucencyMixin, which mixes into RenderLayer#getItemEntityTranslucentCull (the layer used to draw items in the world) and returns the equivalent getEntityCutout layer instead. Cutout is alpha-tested and writes depth like an opaque surface, so items resolve against translucent blocks correctly. The trade-off is loss of soft alpha edges, which is imperceptible for the vast majority of item textures. The behaviour is gated behind a new "Fix Item Translucency" toggle (default on) in the config and Mod Menu screen, alongside the existing force-render options. Bump mod version to 1.2.0 and refresh the README and mod metadata. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01VaWtp4Tu17FEE4AtHU9hRo --- README.md | 38 +++++++++++++--- gradle.properties | 2 +- .../forcerender/ForceRenderConfig.java | 11 +++-- .../forcerender/ForceRenderConfigScreen.java | 28 +++++++++--- .../forcerender/ForceRenderMod.java | 4 +- .../mixin/ItemTranslucencyMixin.java | 44 +++++++++++++++++++ src/main/resources/fabric.mod.json | 2 +- src/main/resources/forcerender.mixins.json | 3 +- 8 files changed, 111 insertions(+), 21 deletions(-) create mode 100644 src/main/java/net/reimaginedpixel/forcerender/mixin/ItemTranslucencyMixin.java diff --git a/README.md b/README.md index 1b4b1d1..65b5f55 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,14 @@ # ForceRender -A minimal **client-side** Fabric mod for **Minecraft 1.21.1** that prevents armor stands and item -frames from being frustum-culled when they are within a configurable range. No commands, no tags — -just open Mod Menu, tweak the slider, and your furniture stays visible. +A minimal **client-side** Fabric mod for **Minecraft 1.21.x** that keeps custom display models +looking right: + +- **Force render** — prevents armor stands and item frames from being frustum-culled when they are + within a configurable range, so large custom models stop popping out of view at the screen edge. +- **Fix item translucency** — stops translucent items (held, worn, or framed) from disappearing or + being clipped when they sit behind water and glass. + +No commands, no tags — just open Mod Menu, flip the toggles, and your furniture stays visible. ![Preview](assets/ON_AND_OFF.gif) @@ -24,14 +30,30 @@ ForceRender mixes into `EntityRenderer#shouldRender`. For every armor stand and the configured range, it returns `true` immediately — bypassing the frustum check. Entities outside that range fall back to vanilla behaviour, so performance is only affected near the player. +## Translucent Items Behind Water / Glass + +Minecraft renders translucent **entities** (armor stands and the items they hold or wear) in a +separate pass from translucent **blocks** (water, glass). Render layers are only depth-sorted +*within* each pass, never across them, so a translucent item and a translucent block have no defined +blend order relative to each other. The result: transparent items **vanish or get clipped** the +moment they sit behind or near water or glass. + +ForceRender fixes this by mixing into `RenderLayer#getItemEntityTranslucentCull` — the layer used to +draw items in the world — and returning the equivalent **cutout** layer instead. Cutout is +alpha-tested and writes depth like an opaque surface, so items resolve against translucent blocks +correctly. The only trade-off is the usual one for cutout: no soft alpha fade (each pixel is either +fully drawn or discarded), which is imperceptible for the vast majority of item textures. Toggle it +off if you specifically need soft transparency. + ## Settings (Mod Menu) Open **Mod Menu → ForceRender → (gear icon)** to access the config screen: | Setting | Description | Default | |---|---|---| -| **Force Render** | Enable or disable the mod entirely | Enabled | +| **Force Render** | Enable or disable the frustum-culling bypass | Enabled | | **Render Range** | Entities beyond this many blocks use vanilla culling | 32 blocks | +| **Fix Item Translucency** | Draw world items as cutout so they don't vanish behind water/glass | Enabled | Settings are saved to `.minecraft/config/forcerender.properties` and can also be edited by hand. @@ -81,9 +103,11 @@ on a dedicated server. ## Compatibility -| Minecraft | Fabric Loader | Fabric API | Mod Menu | -|-----------|---------------|-----------------|----------------| -| 1.21.1 | ≥ 0.16.0 | 0.102.0+1.21.1 | ≥ 11.0 (opt.) | +| Minecraft | Fabric Loader | Fabric API | Mod Menu | +|-------------|---------------|------------|---------------| +| 1.21.1 – 1.21.11 | ≥ 0.16.0 | `*` | ≥ 11.0 (opt.) | + +> Built against 1.21.11; the JAR also loads on 1.21.1 – 1.21.10. ## License diff --git a/gradle.properties b/gradle.properties index cb95a03..b2e4fde 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,6 +13,6 @@ fabric_version=0.141.4+1.21.11 modmenu_version=17.0.0-beta.1 # Mod metadata -mod_version=1.1.0 +mod_version=1.2.0 maven_group=net.reimaginedpixel.forcerender archives_base_name=forcerender diff --git a/src/main/java/net/reimaginedpixel/forcerender/ForceRenderConfig.java b/src/main/java/net/reimaginedpixel/forcerender/ForceRenderConfig.java index 7b12a99..7b28cdc 100644 --- a/src/main/java/net/reimaginedpixel/forcerender/ForceRenderConfig.java +++ b/src/main/java/net/reimaginedpixel/forcerender/ForceRenderConfig.java @@ -12,8 +12,9 @@ public final class ForceRenderConfig { private static final Path CONFIG_FILE = FabricLoader.getInstance().getConfigDir().resolve("forcerender.properties"); - public static boolean enabled = true; - public static int renderRange = 32; // blocks; 1–256 + public static boolean enabled = true; + public static int renderRange = 32; // blocks; 1–256 + public static boolean fixTranslucency = true; // cutout-swap for translucent items private ForceRenderConfig() {} @@ -26,6 +27,7 @@ public static void load() { try (var reader = Files.newBufferedReader(CONFIG_FILE)) { props.load(reader); enabled = Boolean.parseBoolean(props.getProperty("enabled", "true")); + fixTranslucency = Boolean.parseBoolean(props.getProperty("fixTranslucency", "true")); try { renderRange = clampRange(Integer.parseInt(props.getProperty("renderRange", "32"))); } catch (NumberFormatException e) { @@ -38,8 +40,9 @@ public static void load() { public static void save() { Properties props = new Properties(); - props.setProperty("enabled", String.valueOf(enabled)); - props.setProperty("renderRange", String.valueOf(renderRange)); + props.setProperty("enabled", String.valueOf(enabled)); + props.setProperty("renderRange", String.valueOf(renderRange)); + props.setProperty("fixTranslucency", String.valueOf(fixTranslucency)); try (var writer = Files.newBufferedWriter(CONFIG_FILE)) { props.store(writer, "ForceRender — edit here or use the in-game Mod Menu settings screen"); } catch (IOException e) { diff --git a/src/main/java/net/reimaginedpixel/forcerender/ForceRenderConfigScreen.java b/src/main/java/net/reimaginedpixel/forcerender/ForceRenderConfigScreen.java index 2812d84..69754df 100644 --- a/src/main/java/net/reimaginedpixel/forcerender/ForceRenderConfigScreen.java +++ b/src/main/java/net/reimaginedpixel/forcerender/ForceRenderConfigScreen.java @@ -23,14 +23,17 @@ public class ForceRenderConfigScreen extends Screen { // Working copies — only committed to config when Done is pressed private boolean pendingEnabled; private int pendingRange; + private boolean pendingFixTranslucency; private ButtonWidget toggleButton; + private ButtonWidget translucencyButton; public ForceRenderConfigScreen(Screen parent) { super(Text.literal("ForceRender Settings")); - this.parent = parent; - this.pendingEnabled = ForceRenderConfig.enabled; - this.pendingRange = ForceRenderConfig.renderRange; + this.parent = parent; + this.pendingEnabled = ForceRenderConfig.enabled; + this.pendingRange = ForceRenderConfig.renderRange; + this.pendingFixTranslucency = ForceRenderConfig.fixTranslucency; } @Override @@ -54,6 +57,15 @@ protected void init() { WIDGET_WIDTH, WIDGET_HEIGHT)); + // ── Fix translucency toggle ──────────────────────────────────────── + translucencyButton = ButtonWidget.builder(buildTranslucencyLabel(), btn -> { + pendingFixTranslucency = !pendingFixTranslucency; + translucencyButton.setMessage(buildTranslucencyLabel()); + }) + .dimensions(centerX - WIDGET_WIDTH / 2, startY + ROW_SPACING * 2, WIDGET_WIDTH, WIDGET_HEIGHT) + .build(); + addDrawableChild(translucencyButton); + // ── Done / Cancel ────────────────────────────────────────────────── int bottomY = height - BOTTOM_MARGIN; int halfWidth = WIDGET_WIDTH / 2 - 2; @@ -105,9 +117,15 @@ private Text buildToggleLabel() { return Text.literal("Force Render: " + state); } + private Text buildTranslucencyLabel() { + String state = pendingFixTranslucency ? COLOR_ON + "ON" : COLOR_OFF + "OFF"; + return Text.literal("Fix Item Translucency: " + state); + } + private void saveAndClose() { - ForceRenderConfig.enabled = pendingEnabled; - ForceRenderConfig.renderRange = pendingRange; + ForceRenderConfig.enabled = pendingEnabled; + ForceRenderConfig.renderRange = pendingRange; + ForceRenderConfig.fixTranslucency = pendingFixTranslucency; ForceRenderConfig.save(); client.setScreen(parent); } diff --git a/src/main/java/net/reimaginedpixel/forcerender/ForceRenderMod.java b/src/main/java/net/reimaginedpixel/forcerender/ForceRenderMod.java index daaf831..4c6df1e 100644 --- a/src/main/java/net/reimaginedpixel/forcerender/ForceRenderMod.java +++ b/src/main/java/net/reimaginedpixel/forcerender/ForceRenderMod.java @@ -14,7 +14,7 @@ public class ForceRenderMod implements ClientModInitializer { @Override public void onInitializeClient() { ForceRenderConfig.load(); - LOGGER.info("[ForceRender] Loaded — enabled={}, range={}", - ForceRenderConfig.enabled, ForceRenderConfig.renderRange); + LOGGER.info("[ForceRender] Loaded — enabled={}, range={}, fixTranslucency={}", + ForceRenderConfig.enabled, ForceRenderConfig.renderRange, ForceRenderConfig.fixTranslucency); } } diff --git a/src/main/java/net/reimaginedpixel/forcerender/mixin/ItemTranslucencyMixin.java b/src/main/java/net/reimaginedpixel/forcerender/mixin/ItemTranslucencyMixin.java new file mode 100644 index 0000000..f673219 --- /dev/null +++ b/src/main/java/net/reimaginedpixel/forcerender/mixin/ItemTranslucencyMixin.java @@ -0,0 +1,44 @@ +package net.reimaginedpixel.forcerender.mixin; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.render.RenderLayer; +import net.minecraft.util.Identifier; +import net.reimaginedpixel.forcerender.ForceRenderConfig; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +/** + * Fixes translucent items (held / worn / framed) that vanish or get clipped when + * they sit behind or near translucent blocks such as water and glass. + * + *

Vanilla renders translucent entities and translucent blocks in two separate + * passes and only depth-sorts render layers within each pass, never + * across them. A translucent item and a translucent block therefore have no + * defined blend order relative to one another, so the item's alpha pixels are + * composited incorrectly — most visibly they disappear behind water or glass. + * + *

The {@code getItemEntityTranslucentCull} render layer is the one Minecraft + * uses to draw items in the world. Swapping it for the equivalent + * {@code getEntityCutout} layer moves those items into the cutout pass, which is + * alpha-tested and writes depth like an opaque surface. Depth then resolves the + * item against translucent blocks correctly. The trade-off is the usual one for + * cutout: no soft alpha fade (a pixel is either fully drawn or discarded), which + * is imperceptible for the overwhelming majority of item textures. + */ +@Environment(EnvType.CLIENT) +@Mixin(RenderLayer.class) +public class ItemTranslucencyMixin { + + @Inject(method = "getItemEntityTranslucentCull", at = @At("HEAD"), cancellable = true) + private static void forceCutoutForItems( + Identifier texture, + CallbackInfoReturnable callbackInfo) { + + if (ForceRenderConfig.enabled && ForceRenderConfig.fixTranslucency) { + callbackInfo.setReturnValue(RenderLayer.getEntityCutout(texture)); + } + } +} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 9021423..623c662 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -4,7 +4,7 @@ "version": "${version}", "name": "ForceRender", - "description": "Prevents armor stands and item frames from being frustum-culled when they are within a configurable range, fixing large custom models that disappear at screen edges.", + "description": "Prevents armor stands and item frames from being frustum-culled when they are within a configurable range, and fixes translucent items that vanish behind water and glass. Keeps large custom models visible and correctly composited.", "authors": [ "reimaginedpixel" ], diff --git a/src/main/resources/forcerender.mixins.json b/src/main/resources/forcerender.mixins.json index 4e32398..b2e6992 100644 --- a/src/main/resources/forcerender.mixins.json +++ b/src/main/resources/forcerender.mixins.json @@ -4,7 +4,8 @@ "package": "net.reimaginedpixel.forcerender.mixin", "compatibilityLevel": "JAVA_21", "client": [ - "ForceRenderMixin" + "ForceRenderMixin", + "ItemTranslucencyMixin" ], "mixins": [], "injectors": { From d60a82eb246328a3ac4b4737aa7257dc311e838d Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 3 Jul 2026 13:39:24 +0000 Subject: [PATCH 2/4] CI: build with Gradle 9.4.0 to match wrapper and fabric-loom 1.16 The fabric-loom 1.16-SNAPSHOT plugin now resolves to a build that requires Gradle 9.4 (org.gradle.plugin.api-version=9.4.0), but the Build workflow pinned Gradle 8.8, so dependency resolution failed before any compilation. gradle-wrapper.properties already targets 9.4.0; align the CI workflow (and the README build note) with it. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01VaWtp4Tu17FEE4AtHU9hRo --- .github/workflows/build.yml | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d781b2d..079e295 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -25,7 +25,7 @@ jobs: - name: Setup Gradle uses: gradle/actions/setup-gradle@v3 with: - gradle-version: '8.8' + gradle-version: '9.4.0' - name: Build mod run: gradle build diff --git a/README.md b/README.md index 65b5f55..b8fbde7 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ Requirements: JDK 21 ```bash # One-time: generate the Gradle wrapper binary -gradle wrapper --gradle-version=8.8 +gradle wrapper --gradle-version=9.4.0 # Build ./gradlew build From e64fff93c5878ae2344984e438d9daf21520543a Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 3 Jul 2026 13:43:53 +0000 Subject: [PATCH 3/4] Use getEntityCutoutNoCull for the item translucency swap RenderLayer#getEntityCutout(Identifier) does not exist in the 1.21.11 mappings; the compile failed on it. Swap to getEntityCutoutNoCull(Identifier), a long-stable entity cutout layer. NoCull also keeps back faces of 3D display models visible, which suits the custom furniture models this targets. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01VaWtp4Tu17FEE4AtHU9hRo --- README.md | 6 +++--- .../forcerender/mixin/ItemTranslucencyMixin.java | 13 +++++++------ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index b8fbde7..be0cbbf 100644 --- a/README.md +++ b/README.md @@ -39,9 +39,9 @@ blend order relative to each other. The result: transparent items **vanish or g moment they sit behind or near water or glass. ForceRender fixes this by mixing into `RenderLayer#getItemEntityTranslucentCull` — the layer used to -draw items in the world — and returning the equivalent **cutout** layer instead. Cutout is -alpha-tested and writes depth like an opaque surface, so items resolve against translucent blocks -correctly. The only trade-off is the usual one for cutout: no soft alpha fade (each pixel is either +draw items in the world — and returning the equivalent **cutout** layer (`getEntityCutoutNoCull`) +instead. Cutout is alpha-tested and writes depth like an opaque surface, so items resolve against +translucent blocks correctly. The only trade-off is the usual one for cutout: no soft alpha fade (each pixel is either fully drawn or discarded), which is imperceptible for the vast majority of item textures. Toggle it off if you specifically need soft transparency. diff --git a/src/main/java/net/reimaginedpixel/forcerender/mixin/ItemTranslucencyMixin.java b/src/main/java/net/reimaginedpixel/forcerender/mixin/ItemTranslucencyMixin.java index f673219..8f110ee 100644 --- a/src/main/java/net/reimaginedpixel/forcerender/mixin/ItemTranslucencyMixin.java +++ b/src/main/java/net/reimaginedpixel/forcerender/mixin/ItemTranslucencyMixin.java @@ -22,11 +22,12 @@ * *

The {@code getItemEntityTranslucentCull} render layer is the one Minecraft * uses to draw items in the world. Swapping it for the equivalent - * {@code getEntityCutout} layer moves those items into the cutout pass, which is - * alpha-tested and writes depth like an opaque surface. Depth then resolves the - * item against translucent blocks correctly. The trade-off is the usual one for - * cutout: no soft alpha fade (a pixel is either fully drawn or discarded), which - * is imperceptible for the overwhelming majority of item textures. + * {@code getEntityCutoutNoCull} layer moves those items into the cutout pass, + * which is alpha-tested and writes depth like an opaque surface. Depth then + * resolves the item against translucent blocks correctly. The trade-off is the + * usual one for cutout: no soft alpha fade (a pixel is either fully drawn or + * discarded), which is imperceptible for the overwhelming majority of item + * textures. */ @Environment(EnvType.CLIENT) @Mixin(RenderLayer.class) @@ -38,7 +39,7 @@ private static void forceCutoutForItems( CallbackInfoReturnable callbackInfo) { if (ForceRenderConfig.enabled && ForceRenderConfig.fixTranslucency) { - callbackInfo.setReturnValue(RenderLayer.getEntityCutout(texture)); + callbackInfo.setReturnValue(RenderLayer.getEntityCutoutNoCull(texture)); } } } From 0964aaf7a228d5d11babbe4c28af7b149459330e Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 3 Jul 2026 13:50:13 +0000 Subject: [PATCH 4/4] Target the real 1.21.11 item render-layer factories In 1.21.11 the render-layer factory methods moved out of RenderLayer and were renamed. Intercept the two layers that actually draw items in the world: - TexturedRenderLayers#getItemTranslucentCull (block-atlas items) -> getEntityCutout - RenderLayers#itemEntityTranslucentCull(Identifier) (per-texture items) -> entityCutout Both swaps keep the same texture and backface culling, changing only the pass from translucent to depth-writing cutout so items composite correctly against water and glass. Method/class names verified against the yarn 1.21.11 mappings. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01VaWtp4Tu17FEE4AtHU9hRo --- README.md | 13 +++---- .../mixin/ItemAtlasTranslucencyMixin.java | 35 +++++++++++++++++++ .../mixin/ItemTranslucencyMixin.java | 24 +++++++------ src/main/resources/forcerender.mixins.json | 3 +- 4 files changed, 57 insertions(+), 18 deletions(-) create mode 100644 src/main/java/net/reimaginedpixel/forcerender/mixin/ItemAtlasTranslucencyMixin.java diff --git a/README.md b/README.md index be0cbbf..5369af9 100644 --- a/README.md +++ b/README.md @@ -38,12 +38,13 @@ separate pass from translucent **blocks** (water, glass). Render layers are onl blend order relative to each other. The result: transparent items **vanish or get clipped** the moment they sit behind or near water or glass. -ForceRender fixes this by mixing into `RenderLayer#getItemEntityTranslucentCull` — the layer used to -draw items in the world — and returning the equivalent **cutout** layer (`getEntityCutoutNoCull`) -instead. Cutout is alpha-tested and writes depth like an opaque surface, so items resolve against -translucent blocks correctly. The only trade-off is the usual one for cutout: no soft alpha fade (each pixel is either -fully drawn or discarded), which is imperceptible for the vast majority of item textures. Toggle it -off if you specifically need soft transparency. +ForceRender fixes this by intercepting the two render layers Minecraft uses to draw items in the +world — `TexturedRenderLayers#getItemTranslucentCull` (the block-atlas layer used by most items) and +`RenderLayers#itemEntityTranslucentCull` (the per-texture layer) — and returning the matching +**cutout** layer instead. Cutout is alpha-tested and writes depth like an opaque surface, so items +resolve against translucent blocks correctly. The only trade-off is the usual one for cutout: no +soft alpha fade (each pixel is either fully drawn or discarded), which is imperceptible for the vast +majority of item textures. Toggle it off if you specifically need soft transparency. ## Settings (Mod Menu) diff --git a/src/main/java/net/reimaginedpixel/forcerender/mixin/ItemAtlasTranslucencyMixin.java b/src/main/java/net/reimaginedpixel/forcerender/mixin/ItemAtlasTranslucencyMixin.java new file mode 100644 index 0000000..7397d33 --- /dev/null +++ b/src/main/java/net/reimaginedpixel/forcerender/mixin/ItemAtlasTranslucencyMixin.java @@ -0,0 +1,35 @@ +package net.reimaginedpixel.forcerender.mixin; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.render.RenderLayer; +import net.minecraft.client.render.TexturedRenderLayers; +import net.reimaginedpixel.forcerender.ForceRenderConfig; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +/** + * Companion to {@link ItemTranslucencyMixin} for standard items. + * + *

Most items in the world (dropped items, item-frame contents, and items held + * or worn by armor stands) are drawn from the block atlas via + * {@code TexturedRenderLayers.getItemTranslucentCull}, not the per-texture layer + * in {@link net.minecraft.client.render.RenderLayers}. Swapping that atlas layer + * for the matching {@code getEntityCutout} layer — same atlas texture, cutout + * instead of translucent — moves those items into the depth-writing cutout pass + * so they composite correctly against water and glass. See + * {@link ItemTranslucencyMixin} for the full rationale and trade-off. + */ +@Environment(EnvType.CLIENT) +@Mixin(TexturedRenderLayers.class) +public class ItemAtlasTranslucencyMixin { + + @Inject(method = "getItemTranslucentCull", at = @At("HEAD"), cancellable = true) + private static void forceCutoutForAtlasItems(CallbackInfoReturnable callbackInfo) { + if (ForceRenderConfig.enabled && ForceRenderConfig.fixTranslucency) { + callbackInfo.setReturnValue(TexturedRenderLayers.getEntityCutout()); + } + } +} diff --git a/src/main/java/net/reimaginedpixel/forcerender/mixin/ItemTranslucencyMixin.java b/src/main/java/net/reimaginedpixel/forcerender/mixin/ItemTranslucencyMixin.java index 8f110ee..40e7f56 100644 --- a/src/main/java/net/reimaginedpixel/forcerender/mixin/ItemTranslucencyMixin.java +++ b/src/main/java/net/reimaginedpixel/forcerender/mixin/ItemTranslucencyMixin.java @@ -3,6 +3,7 @@ import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.render.RenderLayer; +import net.minecraft.client.render.RenderLayers; import net.minecraft.util.Identifier; import net.reimaginedpixel.forcerender.ForceRenderConfig; import org.spongepowered.asm.mixin.Mixin; @@ -20,26 +21,27 @@ * defined blend order relative to one another, so the item's alpha pixels are * composited incorrectly — most visibly they disappear behind water or glass. * - *

The {@code getItemEntityTranslucentCull} render layer is the one Minecraft - * uses to draw items in the world. Swapping it for the equivalent - * {@code getEntityCutoutNoCull} layer moves those items into the cutout pass, - * which is alpha-tested and writes depth like an opaque surface. Depth then - * resolves the item against translucent blocks correctly. The trade-off is the - * usual one for cutout: no soft alpha fade (a pixel is either fully drawn or - * discarded), which is imperceptible for the overwhelming majority of item - * textures. + *

{@code RenderLayers.itemEntityTranslucentCull} builds the per-texture layer + * used to draw custom-textured items in the world. Swapping it for the matching + * {@code entityCutout} layer moves those items into the cutout pass, which is + * alpha-tested and writes depth like an opaque surface, so depth resolves the + * item against translucent blocks correctly. The only trade-off is the usual one + * for cutout: no soft alpha fade (a pixel is either fully drawn or discarded), + * which is imperceptible for the overwhelming majority of item textures. + * + * @see ItemAtlasTranslucencyMixin for the block-atlas item layer. */ @Environment(EnvType.CLIENT) -@Mixin(RenderLayer.class) +@Mixin(RenderLayers.class) public class ItemTranslucencyMixin { - @Inject(method = "getItemEntityTranslucentCull", at = @At("HEAD"), cancellable = true) + @Inject(method = "itemEntityTranslucentCull", at = @At("HEAD"), cancellable = true) private static void forceCutoutForItems( Identifier texture, CallbackInfoReturnable callbackInfo) { if (ForceRenderConfig.enabled && ForceRenderConfig.fixTranslucency) { - callbackInfo.setReturnValue(RenderLayer.getEntityCutoutNoCull(texture)); + callbackInfo.setReturnValue(RenderLayers.entityCutout(texture)); } } } diff --git a/src/main/resources/forcerender.mixins.json b/src/main/resources/forcerender.mixins.json index b2e6992..7e132b2 100644 --- a/src/main/resources/forcerender.mixins.json +++ b/src/main/resources/forcerender.mixins.json @@ -5,7 +5,8 @@ "compatibilityLevel": "JAVA_21", "client": [ "ForceRenderMixin", - "ItemTranslucencyMixin" + "ItemTranslucencyMixin", + "ItemAtlasTranslucencyMixin" ], "mixins": [], "injectors": {