Repository: neoforged/NeoForge (Java)

Issue:
[1.21] Registering too many GUI layers causes some to be invisible
**Minecraft Version:** 1.21

**NeoForge Version:** 21.0.112-beta

**Description of issue:**

Presumably due to the `LayeredDraw` system using a fixed Z separation of 200 units between layers, adding enough layers causes the top ones to become invisible.

To reproduce, add a loop like below to any mod that renders a custom GUI layer and run it standalone. The modded layer will be invisible.

```java
private void onRegisterGuiLayers(RegisterGuiLayersEvent event) {
    // Register some placeholder layers
    for(int i = 0; i < 50; i++) {
        event.registerAboveAll(ResourceLocation.fromNamespaceAndPath(MOD_ID, "fake_" + i), new LayeredDraw.Layer() {
            @Override
	    public void render(GuiGraphics guiGraphics, DeltaTracker deltaTracker) {
					
	    }
        });
    }
    // Register the real layer
    event.registerAboveAll(ResourceLocation.fromNamespaceAndPath(MOD_ID, "hud"), new ModdedHUDRenderLayer());
}
```



Fix (patch):
diff --git a/patches/net/minecraft/client/gui/Gui.java.patch b/patches/net/minecraft/client/gui/Gui.java.patch
index 9b693c2a911..dc1055a5824 100644
--- a/patches/net/minecraft/client/gui/Gui.java.patch
+++ b/patches/net/minecraft/client/gui/Gui.java.patch
@@ -390,7 +390,7 @@
                  this.toolHighlightTimer = (int)(40.0 * this.minecraft.options.notificationDisplayTime().get());
              } else if (this.toolHighlightTimer > 0) {
                  this.toolHighlightTimer--;
-@@ -1292,8 +_,13 @@
+@@ -1292,8 +_,17 @@
          }
      }
  
@@ -398,6 +398,10 @@
 +    public void initModdedOverlays() {
 +        this.layerManager.initModdedLayers();
 +    }
++
++    public int getLayerCount() {
++        return this.layerManager.getLayerCount();
++    }
 +
      @OnlyIn(Dist.CLIENT)
 -    public static enum HeartType {
diff --git a/patches/net/minecraft/client/renderer/PanoramaRenderer.java.patch b/patches/net/minecraft/client/renderer/PanoramaRenderer.java.patch
new file mode 100644
index 00000000000..4111b68d7da
--- /dev/null
+++ b/patches/net/minecraft/client/renderer/PanoramaRenderer.java.patch
@@ -0,0 +1,11 @@
+--- a/net/minecraft/client/renderer/PanoramaRenderer.java
++++ b/net/minecraft/client/renderer/PanoramaRenderer.java
+@@ -30,6 +_,8 @@
+         p_334063_.blit(PANORAMA_OVERLAY, 0, 0, p_333839_, p_333923_, 0.0F, 0.0F, 16, 128, 16, 128);
+         p_334063_.setColor(1.0F, 1.0F, 1.0F, 1.0F);
+         RenderSystem.disableBlend();
++        // Neo: disable depth test again to prevent issues with extended far plane values for screen layers and HUD layers
++        RenderSystem.disableDepthTest();
+     }
+ 
+     private static float wrap(float p_249058_, float p_249548_) {
diff --git a/src/main/java/net/neoforged/neoforge/client/ClientHooks.java b/src/main/java/net/neoforged/neoforge/client/ClientHooks.java
index ce8133f7414..23499774646 100644
--- a/src/main/java/net/neoforged/neoforge/client/ClientHooks.java
+++ b/src/main/java/net/neoforged/neoforge/client/ClientHooks.java
@@ -179,6 +179,7 @@
 import net.neoforged.neoforge.client.extensions.common.IClientItemExtensions;
 import net.neoforged.neoforge.client.extensions.common.IClientMobEffectExtensions;
 import net.neoforged.neoforge.client.gui.ClientTooltipComponentManager;
+import net.neoforged.neoforge.client.gui.GuiLayerManager;
 import net.neoforged.neoforge.client.gui.map.MapDecorationRendererManager;
 import net.neoforged.neoforge.client.model.data.ModelData;
 import net.neoforged.neoforge.common.NeoForge;
@@ -245,10 +246,13 @@ public static void popGuiLayer(Minecraft minecraft) {
     }
 
     public static float getGuiFarPlane() {
-        // 11000 units for the overlay background,
-        // and 10000 units for each layered Screen,
+        // 11000 units for the overlay background and 10000 units for each layered Screen or 200 units for each HUD layer, whichever ends up higher
 
-        return 11000.0F + 10000.0F * (1 + guiLayers.size());
+        float depth = 10_000F * (1 + guiLayers.size());
+        if (Minecraft.getInstance().level != null) {
+            depth = Math.max(depth, GuiLayerManager.Z_SEPARATION * Minecraft.getInstance().gui.getLayerCount());
+        }
+        return 11_000F + depth;
     }
 
     public static ResourceLocation getArmorTexture(Entity entity, ItemStack armor, ArmorMaterial.Layer layer, boolean innerModel, EquipmentSlot slot) {
diff --git a/src/main/java/net/neoforged/neoforge/client/gui/GuiLayerManager.java b/src/main/java/net/neoforged/neoforge/client/gui/GuiLayerManager.java
index 0953e32805a..8d391520002 100644
--- a/src/main/java/net/neoforged/neoforge/client/gui/GuiLayerManager.java
+++ b/src/main/java/net/neoforged/neoforge/client/gui/GuiLayerManager.java
@@ -83,4 +83,8 @@ public void initModdedLayers() {
         initialized = true;
         ModLoader.postEvent(new RegisterGuiLayersEvent(this.layers));
     }
+
+    public int getLayerCount() {
+        return this.layers.size();
+    }
 }