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 Vortice.D3DCompiler;
using Vortice.Direct3D;
using Vortice.Direct3D11;
using Vortice.DXGI;
using XFEEDToolBox.Core.Galaxy;
using XFEEDToolBox.Core.Rendering;

namespace XFEEDToolBox.Rendering;

[StructLayout(LayoutKind.Sequential)]
internal readonly record struct GalaxyGridHalfFields(Half X,Half Y,Half Z,Half W);
[StructLayout(LayoutKind.Sequential)]
internal readonly record struct GalaxyGridPrimitive(Vector3 From,Vector3 To,GalaxyGridHalfFields Shape,Vector4 Colour,Vector4 Pattern);

internal sealed partial class GalaxyGraphics
{
    private readonly GalaxyGridPrimitive[] originalGridPrimitives=new GalaxyGridPrimitive[GalaxyOriginalGrid.MaximumLines];
    private readonly GalaxyGridPrimitive[] originalConstellationPrimitives=new GalaxyGridPrimitive[GalaxyOriginalConstellations.MaximumSegments];
    private ID3D11VertexShader originalGridVs=null!;
    private ID3D11PixelShader originalGridPs=null!;
    private ID3D11InputLayout originalGridLayout=null!;
    private ID3D11Buffer originalGridBuffer=null!,originalGridConstants=null!;
    private ID3D11Buffer originalConstellationBuffer=null!;
    private ID3D11Texture2D originalGridTexture=null!;
    private ID3D11ShaderResourceView originalGridView=null!;
    private ID3D11SamplerState originalGridSampler=null!;
    private ID3D11Buffer originalSourceOutputConstants=null!;
    private ID3D11BlendState originalSourceAlphaBlend=null!;
    private int originalGridCount;
    private int originalConstellationCount;
    internal int SubmittedOriginalGridLines=>originalGridCount;
    internal int SubmittedOriginalConstellationLines=>originalConstellationCount;
    internal bool OriginalGridWorldWidthRestored=>true;
    internal bool OriginalConstellationWorldStyleRestored=>true;
    // The world quad, half-precision width and actual texture are restored.
    // The actual shared RGB Write multiplier and SrcAlpha/One blend are
    // explicit inputs. Final output and sampler quality remain separate.
    internal bool OriginalGridFullRestored=>false;

    internal void SetOriginalGrid(ReadOnlySpan<GalaxyOriginalGridLine> lines)
    {
        originalGridCount=0;
        var colour=GalaxyOriginalGrid.Colour;
        foreach(var line in lines)
        {
            if(originalGridCount==originalGridPrimitives.Length)break;
            if(!double.IsFinite(line.FromX+line.FromY+line.FromZ+line.ToX+line.ToY+line.ToZ)||
               !float.IsFinite(line.WidthMultiplier)||line.WidthMultiplier<=0)continue;
            var halfWidth=(Half)(GalaxyOriginalGrid.BaseWidth*line.WidthMultiplier);
            if(!Half.IsFinite(halfWidth)||halfWidth<=Half.Zero)continue;
            // Original3A1EDE0 snaps in Sol coordinates, then adds the original
            // origin before3C11750 stores both absolute float XYZ endpoints.
            var from=new Vector3((float)(line.FromX+49985),(float)(line.FromY+40985),(float)(line.FromZ+24105));
            var to=new Vector3((float)(line.ToX+49985),(float)(line.ToY+40985),(float)(line.ToZ+24105));
            if(from==to)continue;
            originalGridPrimitives[originalGridCount++]=new(from,to,new((Half)10,(Half).1f,halfWidth,(Half)10),
                new(colour.R,colour.G,colour.B,colour.A),new(0,8,1,0));
        }
    }
    internal void SetOriginalConstellations(IReadOnlyList<GalaxyResolvedConstellation> groups,GalaxyCamera camera)
    {
        originalConstellationCount=0;
        foreach(var group in groups)
        {
            var alpha=(float)GalaxyOriginalConstellations.Alpha(group,camera.Eye,camera.Focus);
            if(alpha<=GalaxyOriginalConstellations.SubmissionAlpha)continue;
            foreach(var line in group.Lines)
            {
                if(originalConstellationCount==originalConstellationPrimitives.Length)return;
                if(!line.From.IsValid||!line.To.IsValid)continue;
                var from=new Vector3((float)(line.From.X+49985),(float)(line.From.Y+40985),(float)(line.From.Z+24105));
                var to=new Vector3((float)(line.To.X+49985),(float)(line.To.Y+40985),(float)(line.To.Z+24105));
                if(from==to)continue;
                originalConstellationPrimitives[originalConstellationCount++]=new(from,to,
                    new((Half)10,(Half).1f,(Half)GalaxyOriginalConstellations.WorldHalfWidth,(Half)10),new(1,1,1,alpha),
                    new(0,8,GalaxyOriginalConstellations.TextureRepeatPerLightYear,0));
            }
        }
    }
    private void InitializeOriginalGrid(string shader)
    {
        if(Marshal.SizeOf<GalaxyGridPrimitive>()!=64)throw new InvalidDataException("原银河网格顶点格式无效。");
        var vertex=Compiler.CompileFromFile(shader,"VSOriginalGrid","vs_5_0");originalGridVs=device.CreateVertexShader(vertex.Span);
        originalGridPs=device.CreatePixelShader(Compiler.CompileFromFile(shader,"PSOriginalGrid","ps_5_0").Span);
        originalGridLayout=device.CreateInputLayout([
            new InputElementDescription("POSITION",0,Format.R32G32B32_Float,0,0,InputClassification.PerInstanceData,1),
            new InputElementDescription("POSITION",1,Format.R32G32B32_Float,12,0,InputClassification.PerInstanceData,1),
            new InputElementDescription("SHAPE",0,Format.R16G16B16A16_Float,24,0,InputClassification.PerInstanceData,1),
            new InputElementDescription("COLOR",0,Format.R32G32B32A32_Float,32,0,InputClassification.PerInstanceData,1),
            new InputElementDescription("PATTERN",0,Format.R32G32B32A32_Float,48,0,InputClassification.PerInstanceData,1)],vertex.Span);
        originalGridBuffer=device.CreateBuffer(GalaxyOriginalGrid.MaximumLines*64,BindFlags.VertexBuffer,ResourceUsage.Dynamic,CpuAccessFlags.Write);
        originalConstellationBuffer=device.CreateBuffer(GalaxyOriginalConstellations.MaximumSegments*64,BindFlags.VertexBuffer,ResourceUsage.Dynamic,CpuAccessFlags.Write);
        originalGridConstants=device.CreateBuffer(96,BindFlags.ConstantBuffer);
        originalSourceOutputConstants=device.CreateBuffer(16,BindFlags.ConstantBuffer);
        // Actual kind-5 StarMapLine/BackgroundStars effect state, followed by
        // 516980 -> 513D70: RGB and alpha both SrcAlpha/One/Add.
        originalSourceAlphaBlend=device.CreateBlendState(new BlendDescription(Blend.SourceAlpha,Blend.One));
        originalGridSampler=device.CreateSamplerState(new SamplerDescription(Filter.MinMagMipLinear,TextureAddressMode.Wrap,TextureAddressMode.Wrap,TextureAddressMode.Wrap));
        var source=GalaxyOriginalGridTexture.Reference;
        if(!MemoryMarshal.TryGetArray(source.Payload,out ArraySegment<byte> bytes)||bytes.Array is null)throw new InvalidDataException("原银河网格线条缓冲区不可用。");
        var pin=GCHandle.Alloc(bytes.Array,GCHandleType.Pinned);
        try
        {
            var slices=source.Mips.Select(m=>new SubresourceData(pin.AddrOfPinnedObject()+bytes.Offset+m.Offset,(uint)m.RowPitch,(uint)m.DepthPitch)).ToArray();
            originalGridTexture=device.CreateTexture2D(new Texture2DDescription{Width=GalaxyOriginalGridTexture.Width,Height=GalaxyOriginalGridTexture.Height,
                ArraySize=1,MipLevels=GalaxyOriginalGridTexture.MipCount,Format=Format.BC7_UNorm,SampleDescription=new(1,0),
                Usage=ResourceUsage.Immutable,BindFlags=BindFlags.ShaderResource},slices);
            originalGridView=device.CreateShaderResourceView(originalGridTexture);
        }
        finally{pin.Free();}
    }
    /// <summary>
    /// Bind original source output independently of the scene target. A value
    /// of one is intentional for source-space probes; production supplies the
    /// recovered shared HDR Write. Alpha is never multiplied by Write.
    /// </summary>
    private void BindOriginalSourceOutput(float hdrWrite=1,bool applySourceAlphaBlend=true)
    {
        if(!float.IsFinite(hdrWrite)||hdrWrite<=0)throw new ArgumentOutOfRangeException(nameof(hdrWrite));
        var output=new Vector4(hdrWrite,1,0,0);
        context.UpdateSubresource(in output,originalSourceOutputConstants);
        context.PSSetConstantBuffer(8,originalSourceOutputConstants);
        if(applySourceAlphaBlend)context.OMSetBlendState(originalSourceAlphaBlend);
    }
    private void DrawOriginalGrid(GalaxyCamera camera,float hdrWrite=1)
    {
        if(originalGridCount==0&&originalConstellationCount==0)return;
        BindOriginalSourceOutput(hdrWrite);
        var eye=camera.Eye;var right=camera.Right;var up=camera.Up;var forward=camera.Forward;
        var frame=new OriginalGridCamera(new((float)(eye.X+49985),(float)(eye.Y+40985),(float)(eye.Z+24105),(float)camera.FocalLength),
            new((float)right.X,(float)right.Y,(float)right.Z,(float)camera.Width),new((float)up.X,(float)up.Y,(float)up.Z,(float)camera.Height),
            new((float)forward.X,(float)forward.Y,(float)forward.Z,(float)camera.Near),new((float)camera.ProjectionFar,1,0,0),
            GalaxyOriginalGridTexture.Reference.AuthoredFade);
        context.UpdateSubresource(in frame,originalGridConstants);context.VSSetConstantBuffer(4,originalGridConstants);context.PSSetConstantBuffer(4,originalGridConstants);
        context.IASetInputLayout(originalGridLayout);context.IASetPrimitiveTopology(PrimitiveTopology.TriangleList);
        context.VSSetShader(originalGridVs);context.PSSetShader(originalGridPs);context.PSSetShaderResource(12,originalGridView);context.PSSetSampler(0,originalGridSampler);
        if(originalGridCount>0)
        {
            Upload<GalaxyGridPrimitive>(originalGridBuffer,originalGridPrimitives.AsSpan(0,originalGridCount));
            context.IASetVertexBuffer(0,originalGridBuffer,64);context.DrawInstanced(6,(uint)originalGridCount,0,0);DrawCalls++;
        }
        if(originalConstellationCount>0)
        {
            Upload<GalaxyGridPrimitive>(originalConstellationBuffer,originalConstellationPrimitives.AsSpan(0,originalConstellationCount));
            context.IASetVertexBuffer(0,originalConstellationBuffer,64);context.DrawInstanced(6,(uint)originalConstellationCount,0,0);DrawCalls++;
        }
        context.PSSetShaderResource(12,null!);context.PSSetSampler(0,sampler);
        context.OMSetBlendState(additive);
    }
    private void DisposeOriginalGrid()
    {
        originalGridVs.Dispose();originalGridPs.Dispose();originalGridLayout.Dispose();originalGridBuffer.Dispose();originalGridConstants.Dispose();
        originalGridView.Dispose();originalGridTexture.Dispose();originalGridSampler.Dispose();
        originalSourceOutputConstants.Dispose();originalSourceAlphaBlend.Dispose();
        originalConstellationBuffer.Dispose();
    }
    [StructLayout(LayoutKind.Sequential)]
    private readonly record struct OriginalGridCamera(Vector4 EyeFocal,Vector4 RightWidth,Vector4 UpHeight,Vector4 ForwardNear,Vector4 Projection,Vector4 Fade);
}