feat(render): add GpuBlendMode.InverseAlpha and re-scope Campaign V4c

A scouting pass over V4c stopped before writing code and reported two structural blockers. Both verified against source.

The pinned V0 contract was missing a blend mode. WbDrawDispatcher.ApplyRetailBlend selects three blend functions from each DAT surface's TranslucencyKind, and InvAlpha - OneMinusSrcAlpha over SrcAlpha - had no representation. Blend is baked into the pipeline and is not dynamic, so it could not be handled at the encoder, and folding it onto StraightAlpha would have silently changed how every inverse-alpha surface composites. ParticleRenderer needs it too. The contract grows here, in one reviewed commit, rather than a slice inventing a workaround for it.

Retiring V2's interim handle table turns out to be its own slice. The renderers only intern bindless handles; the raw ulong is produced by the texture caches, baked into ObjectRenderBatch, and carried by GroupKey - the bucketing key V4c is forbidden to change - and by CachedBatch, where it gates cache validity. That is now V4t, with its own pixel gate. Until it lands, the world renderers bind their existing interim tables through the encoder as ordinary storage buffers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-07-27 20:20:33 +02:00
parent a475732587
commit 111e72362f
4 changed files with 65 additions and 1 deletions

View file

@ -76,6 +76,7 @@ internal static class GlEnumMapping
{
GpuBlendMode.StraightAlpha => (BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha),
GpuBlendMode.Additive => (BlendingFactor.SrcAlpha, BlendingFactor.One),
GpuBlendMode.InverseAlpha => (BlendingFactor.OneMinusSrcAlpha, BlendingFactor.SrcAlpha),
// GpuBlendMode.None never reaches glBlendFunc — blending is disabled instead.
_ => throw new NotSupportedException($"No GL blend factors for {blend}."),
};

View file

@ -120,6 +120,18 @@ internal enum GpuBlendMode
/// <summary>Additive: <c>SrcAlpha, One</c>.</summary>
Additive,
/// <summary>
/// Retail's inverse-alpha translucency: <c>OneMinusSrcAlpha, SrcAlpha</c>.
///
/// Added at slice V4c, which found that `WbDrawDispatcher.ApplyRetailBlend`
/// selects three blend functions from each DAT surface's `TranslucencyKind`,
/// and this third one had no representation in the V0 contract. Mapping it
/// onto <see cref="StraightAlpha"/> would have been a retail-fidelity
/// regression, not a simplification, so the contract grew instead.
/// `ParticleRenderer` needs it too (slice V4e).
/// </summary>
InverseAlpha,
}
internal enum GpuCompareOp