using System.IO.Compression;
using System.Numerics;
using System.Security.Cryptography;
using System.Text.Json;
namespace XFEEDToolBox.Core.Rendering;
/// Actual separate BackgroundBlackHole source material and its copied BC1 array.
public static class GalaxyOriginalBlackHole
{
public const int Width=512,Height=512,MipCount=10,PayloadBytes=181248;
public const string PayloadSha256="0d8ddcc7b1a303234a8a4385c6dc3e195c176704dcfbfe40c9ea35e0e6deb18a";
public const string VertexShaderSha256="fb5c6e57697c6e6620f3ca0166b9cb5b639dcc3ec63198e9911b2627e712943c";
public const string PixelShaderSha256="30d4e80799f9da2263e12089e1a2d50f99d0445c5c8efedfd937bd5fe68f5b4a";
// 3AB44E0 overrides this fifth stellar publisher as well as the ordinary four.
public static Vector4 Material(bool alternateGlow=false)=>alternateGlow?new(1,4,1,0):new(1,2.75f,.17f,1.903f);
public static bool IsSpecial(ushort classification)=>(classification&63) is 41 or 42;
// The original param7 is Settings5 (NavigationMarkers), independent of the
// tool's general icon switch. special itself is forced only in RealisticView0.
public static bool Enabled(ushort classification,bool realistic,bool navigationMarkers)=>
realistic&&navigationMarkers&&IsSpecial(classification);
public static float HalfExtent(float styleSize)
{
if(!float.IsFinite(styleSize)||styleSize<=0)return 0;
var half=(float)(Half)styleSize;return float.IsFinite(half)?half:0;
}
/// Independent per-channel pixel arithmetic, not the summed BackgroundStars mask.
public static Vector4 SourcePixel(Vector3 mask,float normalizedRadius,Vector4 material,float hdrWrite)
{
var radial=material.Y-normalizedRadius/material.Z+1;
var gain=radial*material.W+1-Math.Clamp(material.W,0,1);
var colour=Vector3.Clamp(new(MathF.Pow(Math.Max(0,mask.X),1.2f)*gain,
MathF.Pow(Math.Max(0,mask.Y),1.2f)*gain,MathF.Pow(Math.Max(0,mask.Z),1.2f)*gain),Vector3.Zero,new(100));
return new((Vector3.One-colour)*hdrWrite,colour.Length()*(1f/3));
}
private static readonly Lazy<(byte[] Payload,IReadOnlyList Mips)> source=new(Read);
public static ReadOnlyMemory Payload=>source.Value.Payload;
public static IReadOnlyList Mips=>source.Value.Mips;
private static (byte[],IReadOnlyList) Read()
{
var assembly=typeof(GalaxyOriginalBlackHole).Assembly;
using var metadata=assembly.GetManifestResourceStream("XFEEDToolBox.Core.Rendering.original-black-hole.json")!;
using var json=JsonDocument.Parse(metadata);var root=json.RootElement;
if(root.GetProperty("width").GetInt32()!=Width||root.GetProperty("height").GetInt32()!=Height||
root.GetProperty("layers").GetInt32()!=1||root.GetProperty("mipCount").GetInt32()!=MipCount||
root.GetProperty("payloadSha256").GetString()!=PayloadSha256)throw new InvalidDataException("原黑洞纹理描述无效。");
using var compressed=assembly.GetManifestResourceStream("XFEEDToolBox.Core.Rendering.original-black-hole.bc1.gz")!;
using var gzip=new GZipStream(compressed,CompressionMode.Decompress);var data=new byte[PayloadBytes];gzip.ReadExactly(data);
if(gzip.ReadByte()!=-1||Convert.ToHexStringLower(SHA256.HashData(data))!=PayloadSha256)throw new InvalidDataException("原黑洞纹理字节校验失败。");
var mips=root.GetProperty("mips").EnumerateArray().Select(m=>new GalaxyOriginalSpriteMip(m.GetProperty("offset").GetInt32(),
m.GetProperty("sliceBytes").GetInt32(),m.GetProperty("size").GetInt32(),m.GetProperty("rowPitch").GetInt32(),m.GetProperty("depthPitch").GetInt32())).ToArray();
var end=0;
for(var level=0;level>level)+3)/4)*8||
mip.SliceBytes>level)+3)/4))throw new InvalidDataException("原黑洞纹理层级布局无效。");
end=checked(end+mip.Size);
}
if(mips.Length!=MipCount||end!=data.Length)throw new InvalidDataException("原黑洞纹理层级数量无效。");
return(data,Array.AsReadOnly(mips));
}
}