refactor(N.3): thread isAdditive + substitute 5 decode methods with WB TextureHelpers

Task 2 — isAdditive threading:
SurfaceDecoder.DecodeRenderSurface now accepts isAdditive parameter.
A8/CUSTOM_LSCAPE_ALPHA format splits:
- isAdditive=true:  R=G=B=A=val (terrain alpha, additive entity textures)
- isAdditive=false: R=G=B=255, A=val (non-additive entity textures)
TextureCache passes surface.Type.HasFlag(SurfaceType.Additive).
TerrainAtlas passes isAdditive:true (alpha masks always replicate).
Aligns with WB ObjectMeshManager dispatch logic.

Task 3 — WB body substitution + new formats:
INDEX16, P8, A8R8G8B8, R8G8B8, A8 now delegate to
TextureHelpers.FillIndex16/FillP8/FillA8R8G8B8/FillR8G8B8/
FillA8/FillA8Additive. Validation + DecodedTexture wrapping stays ours.
X8R8G8B8, DXT1/3/5, SolidColor remain our implementations (no WB equiv).

Bonus: R5G6B5 + A4R4G4B4 formats now handled (previously fell to magenta).

9 conformance tests pass. Build 0 errors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-05-08 11:32:37 +02:00
parent 2a491c6f92
commit 0a67254c5e
3 changed files with 50 additions and 94 deletions

View file

@ -316,10 +316,10 @@ public sealed unsafe class TerrainAtlas : IDisposable
return false;
// Alpha maps ship as PFID_CUSTOM_LSCAPE_ALPHA (AC's landscape-alpha
// format) or the more generic PFID_A8; SurfaceDecoder routes both
// through the same "replicate single byte to RGBA" path. Palette is
// not used.
var d = SurfaceDecoder.DecodeRenderSurface(rs, palette: null);
// format) or the more generic PFID_A8; terrain blending alpha masks
// MUST use isAdditive=true so R=G=B=A=val — the terrain fragment shader
// reads .r for the blend weight. Palette is not used.
var d = SurfaceDecoder.DecodeRenderSurface(rs, palette: null, isClipMap: false, isAdditive: true);
if (ReferenceEquals(d, DecodedTexture.Magenta))
return false;

View file

@ -199,8 +199,9 @@ public sealed unsafe class TextureCache : IDisposable
// Clipmap surfaces use palette indices 0..7 as transparent sentinels.
bool isClipMap = surface.Type.HasFlag(SurfaceType.Base1ClipMap);
bool isAdditive = surface.Type.HasFlag(SurfaceType.Additive);
return SurfaceDecoder.DecodeRenderSurface(rs, effectivePalette, isClipMap);
return SurfaceDecoder.DecodeRenderSurface(rs, effectivePalette, isClipMap, isAdditive);
}
/// <summary>