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.Rendering;

namespace XFEEDToolBox.Rendering;

internal sealed partial class GalaxyGraphics
{
    private ID3D11PixelShader zonesPs=null!;
    private ID3D11Buffer zonesConstants=null!;
    private ID3D11Texture2D? zoneIdTexture,zoneBoundaryTexture;
    private ID3D11ShaderResourceView? zoneIds,zoneBoundaries;
    private Task<GalaxyZoneRaster>? zoneRasterTask;
    internal bool ShowGalacticZonesPlane {get;set;}
    internal bool GalacticZonesPlaneReady=>zoneIds is not null&&zoneBoundaries is not null;
    internal bool GalacticZonesPlaneDrawn {get;private set;}

    private void InitializeGalacticZones(string shader)
    {
        zonesPs=device.CreatePixelShader(Compiler.CompileFromFile(shader,"PSGalacticZones","ps_5_0").Span);
        zonesConstants=device.CreateBuffer(48,BindFlags.ConstantBuffer);
    }
    private bool PrepareGalacticZones()
    {
        if(GalacticZonesPlaneReady)return true;
        if(zoneRasterTask is null)
        {
            zoneRasterTask=Task.Run(()=>GalaxyZoneRaster.Create(GalaxyOriginalZones.Reference));
            _=zoneRasterTask.ContinueWith(task=>App.MainWindow.DispatcherQueue.TryEnqueue(()=>
            {
                if(disposed)return;
                if(task.IsFaulted)App.Runtime.Log("银河区域",task.Exception!.GetBaseException().Message);
                ResourcesChanged?.Invoke();
            }),TaskScheduler.Default);
            return false;
        }
        if(!zoneRasterTask.IsCompletedSuccessfully)return false;
        var raster=zoneRasterTask.Result;var pins=new GCHandle[raster.BoundaryMips.Length+1];
        try
        {
            pins[0]=GCHandle.Alloc(raster.Ids,GCHandleType.Pinned);
            zoneIdTexture=device.CreateTexture2D(new Texture2DDescription{Width=(uint)raster.Map.Width,Height=(uint)raster.Map.Height,MipLevels=1,ArraySize=1,
                Format=Format.R8_UInt,SampleDescription=new(1,0),Usage=ResourceUsage.Immutable,BindFlags=BindFlags.ShaderResource},
                [new SubresourceData(pins[0].AddrOfPinnedObject(),(uint)raster.Map.Width,0)]);
            var mipData=new SubresourceData[raster.BoundaryMips.Length];
            for(var index=0;index<mipData.Length;index++)
            {
                var mip=raster.BoundaryMips[index];pins[index+1]=GCHandle.Alloc(mip.Pixels,GCHandleType.Pinned);
                mipData[index]=new(pins[index+1].AddrOfPinnedObject(),(uint)mip.Width,0);
            }
            zoneBoundaryTexture=device.CreateTexture2D(new Texture2DDescription{Width=(uint)raster.Map.Width,Height=(uint)raster.Map.Height,
                MipLevels=(uint)mipData.Length,ArraySize=1,Format=Format.R8_UNorm,SampleDescription=new(1,0),Usage=ResourceUsage.Immutable,BindFlags=BindFlags.ShaderResource},mipData);
            zoneIds=device.CreateShaderResourceView(zoneIdTexture);zoneBoundaries=device.CreateShaderResourceView(zoneBoundaryTexture);
            var map=raster.Map;
            var data=new GalacticZoneCamera(new(map.ScaleX/4096f,map.ScaleZ/4096f,(float)map.OriginX,(float)map.OriginZ),
                new(map.Width,map.Height,0,0),new(.14f,1.05f,0,0));
            context.UpdateSubresource(in data,zonesConstants);zoneRasterTask=null;return true;
        }
        finally{foreach(var pin in pins)if(pin.IsAllocated)pin.Free();}
    }
    private void DrawGalacticZones()
    {
        GalacticZonesPlaneDrawn=false;
        if(!ShowGalacticZonesPlane||!PrepareGalacticZones())return;
        // Y=0 is this tool's geographic annotation plane. Original raster and
        // transforms are proven; the original GZM GPU material is not restored.
        // Only its boundaries are shown, before stars and navigation overlays.
        context.IASetInputLayout(null);context.IASetPrimitiveTopology(PrimitiveTopology.TriangleList);
        context.VSSetShader(skyVs);context.PSSetShader(zonesPs);context.PSSetConstantBuffer(2,zonesConstants);
        context.PSSetShaderResource(5,zoneIds!);context.PSSetShaderResource(6,zoneBoundaries!);context.PSSetSampler(0,sampler);
        context.Draw(3,0);context.PSSetShaderResource(5,null!);context.PSSetShaderResource(6,null!);
        DrawCalls++;GalacticZonesPlaneDrawn=true;
    }
    private void DisposeGalacticZones()
    {
        zoneIds?.Dispose();zoneBoundaries?.Dispose();zoneIdTexture?.Dispose();zoneBoundaryTexture?.Dispose();
        zonesPs.Dispose();zonesConstants.Dispose();zoneRasterTask=null;
    }
    [StructLayout(LayoutKind.Sequential)] private readonly record struct GalacticZoneCamera(Vector4 Transform,Vector4 Dimensions,Vector4 Settings);
}