From d467c4cf24b92cc110481a2884eeb2157ca6e684 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 8 May 2026 11:34:32 +0200 Subject: [PATCH] test(N.3): update SurfaceDecoderTests to match isAdditive split Decode_A8_ExpandsSingleByteToRgbaWithAlphaInAllChannels renamed to Decode_A8_NonAdditive_ProducesWhitePlusAlpha with updated expectations (R=G=B=255, A=val) matching the new default isAdditive:false WB semantics. Decode_CustomLscapeAlpha_TreatedIdenticallyToA8 updated to the same non-additive expectation (255,255,255,val). New test Decode_A8_Additive_ReplicatesByteToAllChannels documents the isAdditive:true path (R=G=B=A=val) used by TerrainAtlas alpha maps. 8 pre-existing failures unchanged. 883 pass. Co-Authored-By: Claude Opus 4.6 --- .../Textures/SurfaceDecoderTests.cs | 47 ++++++++++++++----- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/tests/AcDream.Core.Tests/Textures/SurfaceDecoderTests.cs b/tests/AcDream.Core.Tests/Textures/SurfaceDecoderTests.cs index 8110bfc..7a440e0 100644 --- a/tests/AcDream.Core.Tests/Textures/SurfaceDecoderTests.cs +++ b/tests/AcDream.Core.Tests/Textures/SurfaceDecoderTests.cs @@ -56,12 +56,10 @@ public class SurfaceDecoderTests } [Fact] - public void Decode_A8_ExpandsSingleByteToRgbaWithAlphaInAllChannels() + public void Decode_A8_NonAdditive_ProducesWhitePlusAlpha() { - // PFID_A8 is single-byte-per-pixel alpha. AC terrain blending alpha maps - // are stored this way. WorldBuilder's GetExpandedAlphaTexture replicates - // the byte into all four RGBA channels so fragment shaders can read the - // blend value from any channel (convention: the alpha channel). + // Default (isAdditive: false) = WB FillA8 semantics: R=G=B=255, A=val. + // Used for non-additive entity surfaces where A8 is a pure alpha channel. var src = new byte[] { 0x00, 0x40, 0x80, 0xFF }; // 2x2 image var rs = new RenderSurface { @@ -76,7 +74,34 @@ public class SurfaceDecoderTests Assert.Equal(2, decoded.Width); Assert.Equal(2, decoded.Height); Assert.Equal(16, decoded.Rgba8.Length); - // Each input byte expands to (b, b, b, b) in RGBA output + // Each input byte expands to (255, 255, 255, val) — white with varying alpha + Assert.Equal(new byte[] + { + 255, 255, 255, 0x00, + 255, 255, 255, 0x40, + 255, 255, 255, 0x80, + 255, 255, 255, 0xFF, + }, decoded.Rgba8); + } + + [Fact] + public void Decode_A8_Additive_ReplicatesByteToAllChannels() + { + // isAdditive=true = WB FillA8Additive semantics: R=G=B=A=val. + // Used for terrain blending alpha masks (TerrainAtlas always passes isAdditive:true). + var src = new byte[] { 0x00, 0x40, 0x80, 0xFF }; // 2x2 image + var rs = new RenderSurface + { + Width = 2, + Height = 2, + Format = PixelFormat.PFID_A8, + SourceData = src, + }; + + var decoded = SurfaceDecoder.DecodeRenderSurface(rs, palette: null, isClipMap: false, isAdditive: true); + + Assert.Equal(16, decoded.Rgba8.Length); + // Each input byte fans out to all four channels Assert.Equal(new byte[] { 0x00, 0x00, 0x00, 0x00, @@ -92,7 +117,7 @@ public class SurfaceDecoderTests // PFID_CUSTOM_LSCAPE_ALPHA (0xF4) is AC's custom format for terrain // blending alpha maps. Pixel layout is identical to PFID_A8 — one // byte of alpha per pixel — so the decoder routes both through the - // same DecodeA8 implementation. + // same DecodeA8 implementation. Default (isAdditive:false) → R=G=B=255, A=val. var src = new byte[] { 0x10, 0x20, 0x30, 0x40 }; // 2x2 var rs = new RenderSurface { @@ -107,10 +132,10 @@ public class SurfaceDecoderTests Assert.Equal(16, decoded.Rgba8.Length); Assert.Equal(new byte[] { - 0x10, 0x10, 0x10, 0x10, - 0x20, 0x20, 0x20, 0x20, - 0x30, 0x30, 0x30, 0x30, - 0x40, 0x40, 0x40, 0x40, + 255, 255, 255, 0x10, + 255, 255, 255, 0x20, + 255, 255, 255, 0x30, + 255, 255, 255, 0x40, }, decoded.Rgba8); }