namespace AcDream.Core.Terrain; /// /// Per-cell terrain blending recipe derived from a palette code. Holds atlas /// layer indices (terrain atlas + alpha atlas) and rotation values for a base /// texture plus up to three terrain overlays and two road overlays. Layer /// indices use the sentinel 255 for "not present" — the fragment shader /// skips any layer with index 255. /// /// Ported from WorldBuilder's TMI structure with the field set adapted to /// acdream's atlas layout: where WorldBuilder stores TerrainTex /// pointers, we store resolved byte atlas layers so the shader never has to /// resolve anything at render time. /// public readonly record struct SurfaceInfo( byte BaseLayer, byte Ovl0Layer, byte Ovl0AlphaLayer, byte Ovl0Rotation, byte Ovl1Layer, byte Ovl1AlphaLayer, byte Ovl1Rotation, byte Ovl2Layer, byte Ovl2AlphaLayer, byte Ovl2Rotation, byte RoadLayer, byte Road0AlphaLayer, byte Road0Rotation, byte Road1AlphaLayer, byte Road1Rotation) { public const byte None = 255; /// An empty recipe where only the base is present and all overlays are None. public static SurfaceInfo BaseOnly(byte baseLayer) => new( baseLayer, None, None, 0, None, None, 0, None, None, 0, None, None, 0, None, 0); } /// /// Read-only inputs to sourced from /// the Region dat / TerrainAtlas at load time. Lets BuildSurface stay pure /// (no dat or GL dependencies) so it can be unit-tested with synthetic data. /// /// /// Fields: /// /// TerrainTypeToLayer: map from (uint)TerrainTextureType → terrain-atlas layer. /// RoadLayer: atlas layer for TerrainTextureType.RoadType, or 255 if missing. /// CornerAlphaLayers: alpha-atlas layer indices for TexMerge.CornerTerrainMaps, in original order. /// SideAlphaLayers: alpha-atlas layer indices for TexMerge.SideTerrainMaps. /// RoadAlphaLayers: alpha-atlas layer indices for TexMerge.RoadMaps. /// CornerAlphaTCodes: parallel to CornerAlphaLayers — each alpha map's TCode. /// SideAlphaTCodes: parallel to SideAlphaLayers. /// RoadAlphaRCodes: parallel to RoadAlphaLayers — each road map's RCode. /// /// The *Codes arrays let pick /// which alpha map to use for a given terrain/road code via the rotation loop /// lifted from WorldBuilder. /// /// public sealed record TerrainBlendingContext( IReadOnlyDictionary TerrainTypeToLayer, byte RoadLayer, IReadOnlyList CornerAlphaLayers, IReadOnlyList SideAlphaLayers, IReadOnlyList RoadAlphaLayers, IReadOnlyList CornerAlphaTCodes, IReadOnlyList SideAlphaTCodes, IReadOnlyList RoadAlphaRCodes);