Skip to content

26.3 Sign and Hanging Sign Culling

Dasik edited this page Aug 20, 2026 · 1 revision

πŸͺ§ 2-Sided Sign & Hanging Sign Text Culling (Minecraft 26.3)

In Minecraft 26.3, signs and hanging signs feature two-sided text capabilities (SignTextSlot.FRONT and SignTextSlot.BACK). By default, the game's font rendering engine parses, kerns, and renders text quads, dyes, and glowing outlines for both sides simultaneouslyβ€”even when the player is looking directly at the front of a wall-mounted sign.

Camera Culling solves this by calculating normal vector dot products ($\vec{N} \cdot \vec{V}$) and empty-text fast passes to unrender unviewed or blank sign text faces.


πŸ“‹ Sign Culling Infobox

Property Value
Target Pipeline BlockEntityRenderDispatcher.tryExtractRenderState @At("RETURN")
API Hook signState.frontText = null; / signState.backText = null;
Supported Types Wall Signs, Standing Signs, Wall Hanging Signs, Ceiling Hanging Signs
Empty Fast-Pass Automatically skips blank faces with zero non-whitespace characters
Dot Product Margin Tolerance of $\pm 0.05$ prevents edge-angle pop-in

πŸ“ Vector Normal Dot-Product Mathematics

To determine whether the front or back face of a sign is pointing towards the camera, Camera Culling calculates the dot product between the sign face normal vector $\vec{N} = (N_x, N_z)$ and the vector from sign center to camera $\vec{V} = (V_x, V_z)$:

$$V_x = X_{\text{cam}} - (X_{\text{sign}} + 0.5), \quad V_z = Z_{\text{cam}} - (Z_{\text{sign}} + 0.5)$$

1. Wall Signs (WallSignBlock.FACING) & Wall Hanging Signs (WallHangingSignBlock.FACING)

The normal vector is derived directly from the block's Direction step offsets: $$N_x = \text{facing.getStepX()}, \quad N_z = \text{facing.getStepZ()}$$

2. Standing Signs (StandingSignBlock.ROTATION) & Ceiling Hanging Signs (CeilingHangingSignBlock.ROTATION)

Rotation is represented as an integer $0 \dots 15$. The angle $\theta$ in radians is computed: $$\theta = \left(\frac{\text{rotation} \times 360^\circ}{16}\right) \times \frac{\pi}{180}$$ $$N_x = -\sin\theta, \quad N_z = \cos\theta$$

3. Visibility Determination

The dot product $D$ evaluates the angle of observation: $$D = N_x V_x + N_z V_z$$

  • Front Face Evaluation: Culled when $D < -0.05$ (Camera is behind the sign face).
  • Back Face Evaluation: Culled when $D > 0.05$ (Camera is in front of the sign face).

⚑ Empty-Side Fast-Pass

If a player has only written text on one side of a sign (or placed a sign without text as a barrier/decoration), Camera Culling inspects the 4 text lines:

public static boolean isTextEmpty(SignText text) {
    if (text == null) return true;
    for (Component msg : text.getMessages(false)) {
        if (msg != null && !msg.getString().trim().isEmpty()) {
            return false;
        }
    }
    return true;
}

Blank faces are nulled out immediately without running trigonometry or vector dot products.


πŸ”— Related Pages

Clone this wiki locally