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); }