Get updates ↗

3D & rendering

Z-fighting in game development

two surfaces fighting for pixels

Interactive example · scroll or point here to play
08

two surfaces fighting for pixels

Z-fighting is the flicker you get when two surfaces sit at the same depth, so rounding in the depth buffer picks the visible one pixel by pixel. The depth buffer spends most of its precision close to the near plane, so a near plane at 0.01 instead of 0.1 leaves distant surfaces with ten times less room. On the left the yellow decal lies exactly on the ground and breaks into flickering stripes, while on the right polygon offset pulls it toward the camera and it stays solid.

prompt bit
Set the camera near plane as far out as the game allows, about 0.1, and the far plane as close as the view distance allows, never put two visible surfaces in the same plane, and lift decals about 1 cm along the surface normal or draw them with polygon offset, factor -1 and units -4.

When to use it

Use polygon offset or a small geometric separation for decals drawn on an existing surface. Tighten the camera’s near and far planes to improve depth precision where possible.

Implementation example

Engine-neutral pseudocode. Adapt the functions and coordinate conventions to your engine.

camera.near = 0.1
camera.far = requiredViewDistance
decal.position = hit.point + hit.normal * smallOffset
// Alternatively configure the material’s depth/polygon offset.

Common mistakes

Pushing the near plane extremely close to zero can waste depth precision. Large offsets make decals float; tune offsets for the renderer and check from grazing angles.

Further reading

Three.js manual ↗

Maintained by Nicolas Zullo · Follow on X ↗