Blended decal layers flicker against near-coplanar surfaces under TAA / FSR jitter (metric depth tolerance) #731

Closed
opened 2026-10-12 19:06:47 +00:00 by sky_line · 2 comments
Owner

Seen (owner + user video): an alpha-blended "onion skin" layer on a road mesh (mostly baked AO, less than 1 mm above the road) flickers against the road. With the camera still it flashes every frame; turning TAA / FSR off stops it. It doesn't happen in Alchemy (GL), and the asset owner reports it on every Slipstream version.

Cause (confirmed by test): the layer is so close to the road that the two are effectively tied in depth. SL's mesh format quantizes positions to a per-face 16-bit lattice, and the two layers are triangulated differently. Our blended pass tests "nearer or equal" against the opaque pre-pass depth, the same as LL's GL_LEQUAL. LL renders without camera jitter, so its result is stable. TAA / FSR jitter moves the raster sample points every frame, so near-ties flip pixel by pixel and the layer flashes.

  • LL does NOT use glPolygonOffset for alpha (checked in the GL-era source). It uses polygon offset only for redraws of the same geometry: glow, legacy bump, terrain detail, overlays, shadow bias.
  • Not caused by draw order (blended surfaces use order-independent WBOIT), not depth precision (reversed-Z float), not the depth pre-pass (turning it off doesn't help).

Fix (option 2, chosen): a metric depth tolerance in the blended fragment shaders. The blended pass reads the opaque depth from the pre-pass and treats any blended fragment within a small world-space distance of the opaque surface as in front. Beyond the tolerance it is discarded as hidden.

  • The tolerance is a few mm, growing slightly with distance, plus a grazing-angle term. Settings for the base tolerance and distance scale, plus a debug view.
  • Blended surfaces don't write depth, so doing the test in the shader costs only a depth-texture read per blended fragment.
  • Check how the blended pipelines currently depth-test (hardware compare against the pre-pass depth) and replace or relax that consistently, including the rigged / particle / water-adjacent blended variants that should get it. Don't apply it where it would let blended surfaces leak through thin walls beyond the tolerance.

Test: the road asset with TAA / FSR on, camera still and moving; blended windows and particles just behind walls (no leaks); glass and water edges; HUD unaffected; snapshots.

**Seen (owner + user video):** an alpha-blended "onion skin" layer on a road mesh (mostly baked AO, less than 1 mm above the road) flickers against the road. With the camera still it flashes every frame; turning TAA / FSR off stops it. It doesn't happen in Alchemy (GL), and the asset owner reports it on every Slipstream version. **Cause (confirmed by test):** the layer is so close to the road that the two are effectively tied in depth. SL's mesh format quantizes positions to a per-face 16-bit lattice, and the two layers are triangulated differently. Our blended pass tests "nearer or equal" against the opaque pre-pass depth, the same as LL's GL_LEQUAL. LL renders without camera jitter, so its result is stable. TAA / FSR jitter moves the raster sample points every frame, so near-ties flip pixel by pixel and the layer flashes. - LL does NOT use glPolygonOffset for alpha (checked in the GL-era source). It uses polygon offset only for redraws of the same geometry: glow, legacy bump, terrain detail, overlays, shadow bias. - Not caused by draw order (blended surfaces use order-independent WBOIT), not depth precision (reversed-Z float), not the depth pre-pass (turning it off doesn't help). **Fix (option 2, chosen):** a metric depth tolerance in the blended fragment shaders. The blended pass reads the opaque depth from the pre-pass and treats any blended fragment within a small world-space distance of the opaque surface as in front. Beyond the tolerance it is discarded as hidden. - The tolerance is a few mm, growing slightly with distance, plus a grazing-angle term. Settings for the base tolerance and distance scale, plus a debug view. - Blended surfaces don't write depth, so doing the test in the shader costs only a depth-texture read per blended fragment. - Check how the blended pipelines currently depth-test (hardware compare against the pre-pass depth) and replace or relax that consistently, including the rigged / particle / water-adjacent blended variants that should get it. Don't apply it where it would let blended surfaces leak through thin walls beyond the tolerance. **Test:** the road asset with TAA / FSR on, camera still and moving; blended windows and particles just behind walls (no leaks); glass and water edges; HUD unaffected; snapshots.
sky_line added this to the Slipstream project 2026-10-12 19:06:47 +00:00
Author
Owner

Fixed on main: a metric depth tolerance for alpha-blended surfaces (RenderVKBlendDepthTol*, default 4 mm + 0.1 mm/m, grazing-angle scaled). Confirmed by the owner on the reported road asset with TAA / FSR on. Closes when the next beta ships.

Fixed on main: a metric depth tolerance for alpha-blended surfaces (RenderVKBlendDepthTol*, default 4 mm + 0.1 mm/m, grazing-angle scaled). Confirmed by the owner on the reported road asset with TAA / FSR on. Closes when the next beta ships.
Author
Owner

Fixed in 1.3.0 Beta 8 (v1.3.0-beta.8). Thanks for the report!

Fixed in **1.3.0 Beta 8** (`v1.3.0-beta.8`). Thanks for the report!
sky_line 2026-10-13 00:26:19 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
sky_line/Slipstream#731
No description provided.