#1419: Near-opaque alpha-blend texels are lit as opaque surfaces (RenderVKBlendOpaqueGBuffer) #1420

Merged
sky_line merged 1 commit from TheSlowly/Slipstream:blend-opaque-1419 into main 2026-11-04 07:48:23 +00:00
Collaborator

Fixes #1419.

Blended texels at alpha >= 0.99 now draw in the depth pre-pass and the G-buffer, so the deferred lighting lights them like any opaque surface (AO, the RT shadow mask, projector shadows, SSR, GI). Pass 2 skips those texels; the soft fringe below the threshold blends as before. One rule decides for every pass (clean_blend_depth_rule.glsl). Forward frames keep the old path, and RenderVKBlendOpaqueGBuffer 0 restores it live.

Checked in world: blended content now lights like masked content.

Fixes #1419. Blended texels at alpha >= 0.99 now draw in the depth pre-pass and the G-buffer, so the deferred lighting lights them like any opaque surface (AO, the RT shadow mask, projector shadows, SSR, GI). Pass 2 skips those texels; the soft fringe below the threshold blends as before. One rule decides for every pass (`clean_blend_depth_rule.glsl`). Forward frames keep the old path, and `RenderVKBlendOpaqueGBuffer` 0 restores it live. Checked in world: blended content now lights like masked content.
Alpha-blend surfaces looked brighter and flatter than everything around
them: pass 2's forward FS gets no ambient occlusion, traces one hard sun
ray instead of the denoised mask, skips ray-traced projector shadows and
has no SSR / GI. That hit every blended mesh body, clothing layer and
solid prim set to blend -- surfaces that are opaque almost everywhere and
only want a soft edge.

Deferred frames now treat a blended texel at alpha >= 0.99 as the opaque
surface it is. The alpha lists draw in the depth pre-pass through a blend
flavour of each attachment variant (depth + normal, + motion, motion
only; the depth-only one is the existing alpha-depth FS), then EQUAL into
the G-buffer through a blend G-buffer FS, so AO, the RT shadow mask, the
Hi-Z, the RT terminator pass, the motion vectors and the deferred
lighting see them like any masked surface. Pass 2's lit FS skips those texels (a push-word bit, set
only on frames whose G-buffer took the lists) before any lighting; the
fringe below 0.99 blends exactly as before. One function decides for all
five users (clean_blend_depth_rule.glsl), so no pass keeps its own copy
of the threshold; the skip carries a 0.005 margin so a texel the G-buffer
rounded just under the threshold is shaded here rather than left as a
hole. The late alpha-depth pass stands down for the lists the pre-pass
drew (it still serves the cluster path's alpha meshes). Forward frames,
overdraw-atomic frames and a transparent avatar layer's sequence (#1328)
keep the old path, as the late pass does.

Cost should fall, not rise: per-pixel deferred lighting replaces the
per-fragment forward lighting of exactly the blended texels that cost the
most, and their depth now also culls what they hide for the whole frame.

Test-Plan:
    python3 indra/newview/tests/blend_opaque_gbuffer_checks.py --source-root . --compile --out /tmp/bog
      (the wiring + every affected FS variant through glslc)
    python3 indra/vkclean/regen_world_spv.py --out-dir /tmp/bog-out --cache-dir /tmp/bog-cache
      (all 440 world variants build)
    clang-cl /Zs on llcleanrenderervk.cpp and gmdxrezfxvk.cpp against the regenerated header
    In world (deferred, RT shadows on): a mesh body / clothing / a prim set to
      alpha blend next to the same content set to alpha mask -- identical look
      (AO under the arms and in creases, the same soft shadow edges), a soft
      edge where the texture fades. RenderVKBlendOpaqueGBuffer 0 restores the
      old look live. Hair cards: the solid cores take AO and shadows, the
      fringe blends. Foliage, glass, 50 % transparent prims: unchanged.
      Highlight Transparent: everything shows through as before. GPU sub ms:
      g_gbuf_static / g_gbuf_rigged up a little, g_p2_* down, g_alpha_depth
      gone (cluster LOD off).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign in to join this conversation.
No reviewers
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!1420
No description provided.