XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Numerics;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text.Json;
using Vortice.Direct3D;
using Vortice.Direct3D11;
using Vortice.DXGI;
using Vortice.Mathematics;
using XFEEDToolBox.Core.Galaxy;
using XFEEDToolBox.Core.Rendering;
using static Vortice.Direct3D11.D3D11;

// Only the actual original VS/PS are executed. This probe intentionally keeps
// the producer's raw angle and never inserts sin(), clamp(), or another shader.
const int width=640,height=360;
var folder="artifacts/galaxy-query-research/power-outer-sources/authored-models/effects/";
var vertexBytes=File.ReadAllBytes(folder+"vs_DistantMilkyWayDust_Forward0_0_Win64_SM50.dxbc");
var pixelBytes=File.ReadAllBytes(folder+"ps_DistantMilkyWayDust_Forward0_0_Win64_SM50.dxbc");
if(Convert.ToHexStringLower(SHA256.HashData(vertexBytes))!="4c6e9cf094628f5c1300aaceb87e9915582fce6b7a8990977684ccea86034f90"||
    Convert.ToHexStringLower(SHA256.HashData(pixelBytes))!="1d7fe5579143e3b33c0ca8781dca4347f6a3210a2fe3e93f041d3f554fa1a4d6")
    throw new InvalidDataException("Original Dust shader changed");
D3D11CreateDevice(IntPtr.Zero,DriverType.Warp,DeviceCreationFlags.BgraSupport,[FeatureLevel.Level_11_0],out var device,out _,out var context).CheckError();
using var d=device;using var c=context;
using var vs=d.CreateVertexShader(vertexBytes);using var ps=d.CreatePixelShader(pixelBytes);
using var layout=d.CreateInputLayout([
    new InputElementDescription("POSITION",0,Format.R32G32B32A32_Float,0,1,InputClassification.PerInstanceData,1),
    new InputElementDescription("TEXCOORD",0,Format.R16G16B16A16_Float,0,0),
    new InputElementDescription("POSITION",1,Format.R16G16B16A16_Float,16,1,InputClassification.PerInstanceData,1),
    new InputElementDescription("POSITION",2,Format.R32G32B32A32_Float,24,1,InputClassification.PerInstanceData,1),
    new InputElementDescription("TEXCOORD",3,Format.R32G32B32A32_Float,40,1,InputClassification.PerInstanceData,1)],vertexBytes);
var corners=new Vector4[]{new(0,1,-1,-1),new(0,0,-1,1),new(1,0,1,1),new(1,0,1,1),new(1,1,1,-1),new(0,1,-1,-1)};
var packedQuad=new byte[72];
for(var i=0;i<6;i++)for(var channel=0;channel<4;channel++)
    BitConverter.GetBytes(BitConverter.HalfToInt16Bits((Half)corners[i][channel])).CopyTo(packedQuad,i*12+channel*2);
using var quad=d.CreateBuffer<byte>(packedQuad,BindFlags.VertexBuffer);
using var instances=d.CreateBuffer(4096*56,BindFlags.VertexBuffer,ResourceUsage.Dynamic,CpuAccessFlags.Write);
using var b0=d.CreateBuffer(8*16,BindFlags.ConstantBuffer);using var b1=d.CreateBuffer(276*16,BindFlags.ConstantBuffer);using var b2=d.CreateBuffer(2*16,BindFlags.ConstantBuffer);
using var targetTexture=d.CreateTexture2D(Format.R32G32B32A32_Float,width,height,mipLevels:1,bindFlags:BindFlags.RenderTarget);
using var target=d.CreateRenderTargetView(targetTexture);using var blend=d.CreateBlendState(new BlendDescription(Blend.Zero,Blend.SourceColor,Blend.Zero,Blend.SourceAlpha));
using var raster=d.CreateRasterizerState(new RasterizerDescription(CullMode.None,FillMode.Solid));
using var depth=d.CreateDepthStencilState(new DepthStencilDescription(false,DepthWriteMask.Zero,ComparisonFunction.Always));
using var sampler=d.CreateSamplerState(new SamplerDescription(Filter.MinMagMipLinear,TextureAddressMode.Clamp,TextureAddressMode.Clamp,TextureAddressMode.Clamp));
var source=GalaxyOriginalMilkyWay.Reference;var texture=source.Textures[0];
if(!MemoryMarshal.TryGetArray(source.Payload,out ArraySegment<byte> payload)||payload.Array is null)throw new InvalidDataException("Source atlas unavailable");
var pin=GCHandle.Alloc(payload.Array,GCHandleType.Pinned);ID3D11Texture2D atlas;
try{atlas=d.CreateTexture2D(new Texture2DDescription{Width=(uint)texture.Width,Height=(uint)texture.Height,ArraySize=1,MipLevels=(uint)texture.Mips.Count,
    Format=Format.BC1_UNorm,SampleDescription=new(1,0),Usage=ResourceUsage.Immutable,BindFlags=BindFlags.ShaderResource},
    texture.Mips.Select(m=>new SubresourceData(pin.AddrOfPinnedObject()+payload.Offset+texture.PayloadOffset+m.Offset,(uint)m.RowPitch,(uint)m.DepthPitch)).ToArray());}
finally{pin.Free();}
using var atlasOwner=atlas;using var view=d.CreateShaderResourceView(atlas);
var reports=new List<object>();
var camera=GalaxyCamera.Create(new(0,0,0),width,height,-.3,.45,.05);
var eye=new Vector3((float)camera.Eye.X+49985,(float)camera.Eye.Y+40985,(float)camera.Eye.Z+24105);
var centre=eye+new Vector3((float)camera.Forward.X,(float)camera.Forward.Y,(float)camera.Forward.Z)*10000;
foreach(var angle in new[]{0f,.5f,1f,2f,6.2831855f})
foreach(var tint in new[]{Vector3.Zero,Vector3.One})
{
    var bytes=Record(centre,1,angle,2000,3,0,300000,10,true);var values=Draw(camera,bytes,tint);
    var changed=Changed(values);var nonfinite=values.Count(v=>!float.IsFinite(v));
    if(nonfinite!=0||tint==Vector3.Zero&&changed!=0||angle>1&&changed!=0||angle==.5f&&tint==Vector3.One&&changed<100)
        throw new InvalidOperationException($"Unexpected original Dust output angle{angle}/tint{tint}:changed{changed},nonfinite{nonfinite}");
    reports.Add(new{test="original-angle-domain",angle,controlledTint=tint.X,changedRgbPixels=changed,nonfinite,
        sourceDefaultTint=tint==Vector3.Zero,rawProducerAngleKept=true});
}
var layer=GalaxyOriginalClouds.Generate(GalaxyOriginalClouds.Window(new(0,0,0),0,true));
var all=layer.Clouds.SelectMany(cloud=>Record(cloud.AbsolutePosition,cloud.Alpha*.5f*2.6589999198913574f,cloud.Rotation,
    cloud.Size*103.56600189208984f*32,cloud.AtlasIndex,200,300000,106600,true)).ToArray();
var valid=layer.Clouds.Where(cloud=>(float)(Half)cloud.Rotation<=1).SelectMany(cloud=>Record(cloud.AbsolutePosition,cloud.Alpha*.5f*2.6589999198913574f,
    cloud.Rotation,cloud.Size*103.56600189208984f*32,cloud.AtlasIndex,200,300000,106600,true)).ToArray();
var above=GalaxyCamera.Create(new(15,20000,25895),width,height,-.3,1.1,.02);
var defaults=Draw(above,all,Vector3.Zero);if(Changed(defaults)!=0)throw new InvalidOperationException("Original default zero Dust tint changed background RGB");
var raw=Draw(above,all,Vector3.One);var subset=Draw(above,valid,Vector3.One);var max=0f;
for(var i=0;i<raw.Length;i++)if(i%4<3)max=Math.Max(max,Math.Abs(raw[i]-subset[i]));
if(max!=0||raw.Any(v=>!float.IsFinite(v)))throw new InvalidOperationException("Original out-of-domain Dust emitted unexpected RGB");
reports.Add(new{test="real-original-coarse-dust-records",sourceRecordCount=layer.Clouds.Count,validHalfRotationRecords=valid.Length/56,
    outOfDomainHalfRotationRecords=(all.Length-valid.Length)/56,zeroTintChangedPixels=Changed(defaults),controlledTintChangedPixels=Changed(raw),
    allVersusValidSubsetMaximumRgbDifference=max,frameFadeExplicitlyControlled=true,gameCalls=0,productionDustEnabled=false});
var output=Path.GetFullPath("artifacts/galaxy-dust-shader-validation");Directory.CreateDirectory(output);
SaveImage("default-zero-tint",defaults);SaveImage("controlled-nonzero-tint",raw);
File.WriteAllText(Path.Combine(output,"report.json"),JsonSerializer.Serialize(reports,new JsonSerializerOptions{WriteIndented=true}));Console.WriteLine(JsonSerializer.Serialize(reports));

void SaveImage(string name,float[] values)
{
    var bytes=new byte[width*height*4];for(var i=0;i<values.Length;i+=4){bytes[i]=(byte)(Math.Clamp(values[i+2],0,1)*255);bytes[i+1]=(byte)(Math.Clamp(values[i+1],0,1)*255);bytes[i+2]=(byte)(Math.Clamp(values[i],0,1)*255);bytes[i+3]=255;}
    File.WriteAllBytes(Path.Combine(output,name+".bgra"),bytes);
}

byte[] Record(Vector3 p,float alpha,float rotation,float size,int atlasIndex,float near,float far,float fade,bool first)
{
    var b=new byte[56];void F(int offset,float value)=>BitConverter.GetBytes(value).CopyTo(b,offset);
    F(0,p.X);F(4,p.Y);F(8,p.Z);F(12,alpha);
    for(var i=0;i<3;i++)BitConverter.GetBytes(BitConverter.HalfToInt16Bits((Half)rotation)).CopyTo(b,16+i*2);
    BitConverter.GetBytes(BitConverter.HalfToInt16Bits((Half)(first?1:0))).CopyTo(b,22);
    F(24,near);F(28,far);F(32,fade);F(36,size);var tile=source.AtlasTiles[atlasIndex];F(40,tile>>8);F(44,tile&255);F(48,3);F(52,5);return b;
}
float[] Draw(GalaxyCamera cam,byte[] bytes,Vector3 tint)
{
    var e=new Vector3((float)cam.Eye.X+49985,(float)cam.Eye.Y+40985,(float)cam.Eye.Z+24105);
    var right=new Vector3((float)cam.Right.X,(float)cam.Right.Y,(float)cam.Right.Z);var up=new Vector3((float)cam.Up.X,(float)cam.Up.Y,(float)cam.Up.Z);
    var forward=new Vector3((float)cam.Forward.X,(float)cam.Forward.Y,(float)cam.Forward.Z);
    var rows=new Vector4[8];rows[4]=new(right*(float)(cam.FocalLength*2/width),-Vector3.Dot(e,right)*(float)(cam.FocalLength*2/width));
    rows[5]=new(up*(float)(cam.FocalLength*2/height),-Vector3.Dot(e,up)*(float)(cam.FocalLength*2/height));rows[6]=new(0,0,0,(float)cam.Near);rows[7]=new(forward,-Vector3.Dot(e,forward));
    var shared=new Vector4[276];shared[90]=new(0,GalaxyOriginalHdr.WriteScale,GalaxyOriginalHdr.ReadScale,0);shared[118]=new(up,0);shared[275]=new(e,0);
    c.UpdateSubresource<Vector4>(rows,b0);c.UpdateSubresource<Vector4>(shared,b1);c.UpdateSubresource<Vector4>([new(1,tint.X,tint.Y,tint.Z),new(1.96f,44902.8f,.644f,0)],b2);
    var upload=c.Map(instances,0,MapMode.WriteDiscard);
    try{Marshal.Copy(bytes,0,upload.DataPointer,bytes.Length);}finally{c.Unmap(instances,0);}
    c.OMSetRenderTargets(target);c.ClearRenderTargetView(target,new Color4(.2f,.3f,.4f,1));
    c.RSSetViewport(new Viewport(width,height));c.RSSetState(raster);c.OMSetDepthStencilState(depth);c.OMSetBlendState(blend);
    c.IASetInputLayout(layout);c.IASetPrimitiveTopology(PrimitiveTopology.TriangleList);c.IASetVertexBuffer(0,quad,12);c.IASetVertexBuffer(1,instances,56);
    c.VSSetShader(vs);c.PSSetShader(ps);c.VSSetConstantBuffer(0,b0);c.VSSetConstantBuffer(1,b1);c.VSSetConstantBuffer(2,b2);c.PSSetConstantBuffer(1,b1);c.PSSetConstantBuffer(2,b2);
    c.PSSetShaderResource(0,view);c.PSSetSampler(0,sampler);c.DrawInstanced(6,(uint)(bytes.Length/56),0,0);c.PSSetShaderResource(0,null!);
    c.OMSetRenderTargets(Array.Empty<ID3D11RenderTargetView>());var desc=targetTexture.Description;desc.Usage=ResourceUsage.Staging;desc.CPUAccessFlags=CpuAccessFlags.Read;desc.BindFlags=BindFlags.None;
    using var staging=d.CreateTexture2D(desc);c.CopyResource(staging,targetTexture);var mapped=c.Map(staging,0,MapMode.Read);var data=new float[width*height*4];
    for(var y=0;y<height;y++)Marshal.Copy(mapped.DataPointer+(int)(y*mapped.RowPitch),data,y*width*4,width*4);c.Unmap(staging,0);return data;
}
int Changed(float[] data)
{
    var n=0;for(var i=0;i<data.Length;i+=4)if(Math.Abs(data[i]-.2f)>.000001f||Math.Abs(data[i+1]-.3f)>.000001f||Math.Abs(data[i+2]-.4f)>.000001f)n++;return n;
}