Preventing Z-Fighting on Coplanar glTF Surfaces

Z-fighting occurs when two or more overlapping surfaces share near-identical depth values, causing the graphics hardware to rapidly alternate between them and produce distracting visual flicker. In glTF architectural models, this issue is common across large coplanar surfaces such as layered walls, flush window frames, and floor finishes. Eliminating these artifacts requires a combination of geometry-level optimizations during the 3D modeling phase and depth-buffer adjustments within the runtime rendering engine.

Optimize Depth Buffer Precision

The primary engine-level cause of z-fighting is a poorly configured camera frustum. Modern perspective projections concentrate most 24-bit depth buffer precision near the camera's near clipping plane.

  • Increase the Near Plane: Set the camera’s near plane value as high as feasible (e.g., changing from 0.01 to 0.5 meters). This dramatically improves depth precision across mid-to-far ranges where large building planes sit.
  • Decrease the Far Plane: Bring the far clipping plane closer to the actual boundaries of the scene rather than leaving it at arbitrarily large values.
  • Implement Reverse-Z or Logarithmic Depth: If you are rendering massive architectural or GIS datasets, configure your WebGL or native engine to use a floating-point logarithmic depth buffer or a reversed floating-point depth buffer (mapping near to 1.0 and far to 0.0), which virtually eliminates depth precision loss over large distances.

Geometry Cleanup and Coplanar Removal

The most effective strategy is removing duplicate geometry entirely inside your Digital Content Creation (DCC) software before exporting to glTF.

  • Boolean Cutouts: Do not place door frames, windows, or signage directly over solid wall meshes. Cut the underlying wall geometry using boolean operations so the two objects do not share the exact same spatial plane.
  • Strip Backing Faces: For architectural trim, baseboards, and structural cladding, delete the back-facing polygons that rest directly against other structural elements. If a surface is never visible, removing it eliminates the possibility of co-planar conflict while reducing the file size.

Geometric Offsetting (Micro-Spacing)

When two surfaces must remain layered (such as road markings on asphalt or rugs on interior floors), apply a slight physical displacement along the surface normal.

  • Offset the top geometry along its local Z/normal axis by a small margin, typically between 1 millimeter and 5 millimeters depending on the scene's scale and viewing distance.
  • Ensure the offset distance is greater than the depth resolution limit at maximum viewing distance to prevent the planes from collapsing together when viewed from afar.

Depth Bias and Polygon Offset

If geometry cannot be modified or separated, runtime depth biasing forces the GPU to render one surface in front of another.

  • Polygon Offset: In engines like Three.js or Babylon.js, enable polygonOffset on the material of the foreground object. This applies a small runtime depth slope factor and units bias during the depth test, artificially moving the pixels closer to the camera during rasterization without changing their world coordinates.
  • Draw Order and Depth Masking: Set explicit render orders for co-planar details like decals. Disabling depth writing (depthWrite: false) on semi-transparent overlays can also prevent them from fighting with the opaque structures beneath them.