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,Pack=1)]
internal readonly record struct GalaxyBlackHoleInstance(Vector3 World,Vector4 WeightsLayer,Half A,Half B,Half Size,Half D,Vector4 Colour)
{
    internal static GalaxyBlackHoleInstance Create(Vector3 world,float size)=>new(world,new(1,1,0,0),(Half)1,(Half).1f,(Half)size,(Half)10,Vector4.One);
}

internal sealed partial class GalaxyGraphics
{
    private ID3D11VertexShader blackHoleVs=null!;
    private ID3D11PixelShader blackHolePs=null!;
    private ID3D11InputLayout blackHoleLayout=null!;
    private ID3D11Buffer blackHoleBuffer=null!,blackHoleConstants=null!;
    private ID3D11BlendState blackHoleBlend=null!;
    private ID3D11Texture2D blackHoleTexture=null!;
    private ID3D11ShaderResourceView blackHoleView=null!;
    private GalaxyBlackHoleInstance[] blackHoleInstances=new GalaxyBlackHoleInstance[64];
    internal int OriginalBlackHolesDrawn {get;private set;}

    private void InitializeOriginalBlackHoles(string shader)
    {
        var vs=Compiler.CompileFromFile(shader,"VSOriginalBlackHole","vs_5_0");blackHoleVs=device.CreateVertexShader(vs.Span);
        blackHolePs=device.CreatePixelShader(Compiler.CompileFromFile(shader,"PSOriginalBlackHole","ps_5_0").Span);
        blackHoleLayout=device.CreateInputLayout([
            new InputElementDescription("POSITION",0,Format.R32G32B32_Float,0,0,InputClassification.PerInstanceData,1),
            new InputElementDescription("POSITION",2,Format.R32G32B32A32_Float,12,0,InputClassification.PerInstanceData,1),
            new InputElementDescription("TEXCOORD",3,Format.R16G16B16A16_Float,28,0,InputClassification.PerInstanceData,1),
            new InputElementDescription("POSITION",4,Format.R32G32B32A32_Float,36,0,InputClassification.PerInstanceData,1)],vs.Span);
        blackHoleBuffer=device.CreateBuffer(StarCapacity*52,BindFlags.VertexBuffer,ResourceUsage.Dynamic,CpuAccessFlags.Write);
        blackHoleConstants=device.CreateBuffer(6*16,BindFlags.ConstantBuffer);
        // The actual generic publisher overrides authored pDestBlend7 with1.
        // Signed source RGB darkens the scene through its original additive state.
        blackHoleBlend=device.CreateBlendState(new BlendDescription(Blend.SourceAlpha,Blend.One));
        if(!MemoryMarshal.TryGetArray(GalaxyOriginalBlackHole.Payload,out ArraySegment<byte> bytes)||bytes.Array is null)throw new InvalidDataException("原黑洞纹理不可用。");
        var pin=GCHandle.Alloc(bytes.Array,GCHandleType.Pinned);
        try
        {
            var slices=GalaxyOriginalBlackHole.Mips.Select(m=>new SubresourceData(pin.AddrOfPinnedObject()+bytes.Offset+m.Offset,(uint)m.RowPitch,(uint)m.SliceBytes)).ToArray();
            blackHoleTexture=device.CreateTexture2D(new Texture2DDescription{Width=512,Height=512,ArraySize=1,MipLevels=10,Format=Format.BC1_UNorm,
                SampleDescription=new(1,0),Usage=ResourceUsage.Immutable,BindFlags=BindFlags.ShaderResource},slices);
            blackHoleView=device.CreateShaderResourceView(blackHoleTexture);
        }
        finally{pin.Free();}
    }
    private void DrawOriginalBlackHoles(ReadOnlySpan<GalaxyStar> stars,GalaxyCamera camera,bool realistic,bool navigationMarkers,float hdrWrite)
    {
        OriginalBlackHolesDrawn=0;if(!realistic||!navigationMarkers)return;
        foreach(var star in stars)
        {
            var colour=star.OriginalColour??star.Colour;
            if(!star.OriginalBlackHole||star.Radius<=0||colour.W<=0||!float.IsFinite(colour.X+colour.Y+colour.Z+colour.W)||GalaxyOriginalBlackHole.HalfExtent(star.OriginalSize)<=0)continue;
            var position=new XFEEDToolBox.Core.Models.Coordinates(star.World.X,star.World.Y,star.World.Z);
            // Main already supplied only retained, strictly queried catalogue
            // objects. Its whole-cell/D50 envelope is not this rebuilt lens's
            // fallback4D boundary; apply only the actual source projection here.
            if(!camera.Project(position).IsVisible)continue;
            if(OriginalBlackHolesDrawn==blackHoleInstances.Length)Array.Resize(ref blackHoleInstances,Math.Min(StarCapacity,blackHoleInstances.Length*2));
            blackHoleInstances[OriginalBlackHolesDrawn++]=GalaxyBlackHoleInstance.Create(new(star.World.X,star.World.Y,star.World.Z),star.OriginalSize);
        }
        if(OriginalBlackHolesDrawn==0)return;
        var eye=camera.Eye;var r=camera.Right;var up=camera.Up;var f=camera.Forward;
        Vector4[] values=[new((float)eye.X,(float)eye.Y,(float)eye.Z,(float)camera.FocalLength),
            new((float)r.X,(float)r.Y,(float)r.Z,(float)camera.Width),new((float)up.X,(float)up.Y,(float)up.Z,(float)camera.Height),
            new((float)f.X,(float)f.Y,(float)f.Z,(float)camera.Near),GalaxyOriginalBlackHole.Material(),new(hdrWrite,0,0,0)];
        context.UpdateSubresource<Vector4>(values,blackHoleConstants);
        Upload<GalaxyBlackHoleInstance>(blackHoleBuffer,blackHoleInstances.AsSpan(0,OriginalBlackHolesDrawn));
        context.IASetInputLayout(blackHoleLayout);context.IASetPrimitiveTopology(PrimitiveTopology.TriangleList);context.IASetVertexBuffer(0,blackHoleBuffer,52);
        context.VSSetShader(blackHoleVs);context.PSSetShader(blackHolePs);context.VSSetConstantBuffer(9,blackHoleConstants);context.PSSetConstantBuffer(9,blackHoleConstants);
        context.OMSetBlendState(blackHoleBlend);context.PSSetShaderResource(18,blackHoleView);context.PSSetSampler(0,sampler);
        context.DrawInstanced(6,(uint)OriginalBlackHolesDrawn,0,0);DrawCalls++;context.PSSetShaderResource(18,null!);
    }
    private void DisposeOriginalBlackHoles()
    {
        blackHoleVs.Dispose();blackHolePs.Dispose();blackHoleLayout.Dispose();blackHoleBuffer.Dispose();blackHoleConstants.Dispose();
        blackHoleBlend.Dispose();blackHoleView.Dispose();blackHoleTexture.Dispose();
    }
}