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;

internal sealed partial class GalaxyGraphics
{
    private ID3D11VertexShader powerActivityBillboardVs=null!;
    private ID3D11PixelShader powerActivityBillboardPs=null!;
    private ID3D11InputLayout powerActivityBillboardLayout=null!;
    private ID3D11Buffer powerActivityBillboardInstance=null!,powerActivityBillboardConstants=null!;
    private ID3D11BlendState powerActivityBillboardBlend=null!;
    private GalaxyOriginalPowerActivityBillboard? powerActivityBillboard;
    private float? powerActivityBillboardEmissive;
    private bool powerActivityBillboardInvalid;
    internal int SubmittedPowerActivityBillboards {get;private set;}
    internal bool PowerActivityBillboardSourceUnknown=>powerActivityBillboard is not null&&(powerActivityBillboardInvalid||powerActivityBillboardEmissive is null&&!OriginalExposureReady);
    internal bool OriginalPowerActivityBillboardGeometryRestored=>true;
    internal bool OriginalPowerActivityBillboardFullRestored=>false;
    internal void SetOriginalPowerActivityBillboard(GalaxyOriginalPowerActivityBillboard? value,float? emissiveRescaling=null)
    {
        powerActivityBillboard=value is {} record&&GalaxyOriginalPowerActivityBillboardGeometry.IsValid(record)?record:null;
        powerActivityBillboardEmissive=emissiveRescaling;
        powerActivityBillboardInvalid=emissiveRescaling is {} scalar&&(!float.IsFinite(scalar)||scalar<0);
        SubmittedPowerActivityBillboards=0;
    }
    private void InitializeOriginalPowerActivityBillboard(string shader)
    {
        if(Marshal.SizeOf<GalaxyOriginalPowerActivityBillboard>()!=64)throw new InvalidDataException("原活动轮廓实例格式无效。");
        var path=Path.Combine(Path.GetDirectoryName(shader)!,"GalaxyPowerActivityBillboard.hlsl");
        var vs=Compiler.CompileFromFile(path,"VSOriginalPowerActivityBillboard","vs_5_0");powerActivityBillboardVs=device.CreateVertexShader(vs.Span);
        powerActivityBillboardPs=device.CreatePixelShader(Compiler.CompileFromFile(path,"PSOriginalPowerActivityBillboard","ps_5_0").Span);
        powerActivityBillboardLayout=device.CreateInputLayout([
            new InputElementDescription("POSITION",0,Format.R32G32B32A32_Float,0,0,InputClassification.PerInstanceData,1),
            new InputElementDescription("UAXISEXTENT",0,Format.R32G32B32A32_Float,16,0,InputClassification.PerInstanceData,1),
            new InputElementDescription("VAXISEXTENT",0,Format.R32G32B32A32_Float,32,0,InputClassification.PerInstanceData,1),
            new InputElementDescription("USERDATA",0,Format.R32G32B32A32_Float,48,0,InputClassification.PerInstanceData,1)],vs.Span);
        powerActivityBillboardInstance=device.CreateBuffer(64,BindFlags.VertexBuffer,ResourceUsage.Dynamic,CpuAccessFlags.Write);
        powerActivityBillboardConstants=device.CreateBuffer(112,BindFlags.ConstantBuffer);
        powerActivityBillboardBlend=device.CreateBlendState(new BlendDescription(Blend.One,Blend.InverseSourceAlpha));
    }
    private void DrawOriginalPowerActivityBillboard(GalaxyCamera camera,float hdrWrite)
    {
        SubmittedPowerActivityBillboards=0;
        if(powerActivityBillboard is not{} value||powerActivityBillboardInvalid||!float.IsFinite(hdrWrite)||hdrWrite<=0)return;
        var useTexture=powerActivityBillboardEmissive is null&&OriginalExposureReady;
        if(powerActivityBillboardEmissive is null&&!useTexture)return;
        var emissive=powerActivityBillboardEmissive??OriginalManualExposureResult?.Type2EmissiveRescaling??0;
        if(emissive==0&&value.Colour.W==0)return;
        var eye=camera.Eye;var right=camera.Right;var up=camera.Up;var forward=camera.Forward;
        var frame=new PowerActivityBillboardFrame(new((float)eye.X,(float)eye.Y,(float)eye.Z,(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(.8999999761581421f,.75f,.9200000166893005f,.17499999701976776f),
            new(1.5f,.004999999888241291f,width,height),new(emissive,hdrWrite,useTexture?1:0,0));
        Upload<GalaxyOriginalPowerActivityBillboard>(powerActivityBillboardInstance,new[]{value});context.UpdateSubresource(in frame,powerActivityBillboardConstants);
        context.VSSetConstantBuffer(12,powerActivityBillboardConstants);context.PSSetConstantBuffer(12,powerActivityBillboardConstants);
        context.IASetInputLayout(powerActivityBillboardLayout);context.IASetPrimitiveTopology(PrimitiveTopology.TriangleStrip);
        context.IASetVertexBuffer(0,powerActivityBillboardInstance,64);context.VSSetShader(powerActivityBillboardVs);context.PSSetShader(powerActivityBillboardPs);
        context.PSSetShaderResource(20,useTexture?originalExposureView!:null!);context.OMSetBlendState(powerActivityBillboardBlend);
        context.DrawInstanced(GalaxyOriginalPowerActivityBillboardGeometry.VertexCount,1,0,0);context.PSSetShaderResource(20,null!);
        DrawCalls++;SubmittedPowerActivityBillboards=1;
    }
    private void DisposeOriginalPowerActivityBillboard()
    {
        powerActivityBillboardVs.Dispose();powerActivityBillboardPs.Dispose();powerActivityBillboardLayout.Dispose();
        powerActivityBillboardInstance.Dispose();powerActivityBillboardConstants.Dispose();powerActivityBillboardBlend.Dispose();
    }
    [StructLayout(LayoutKind.Sequential)]
    private readonly record struct PowerActivityBillboardFrame(Vector4 EyeFocal,Vector4 RightWidth,Vector4 UpHeight,Vector4 ForwardNear,Vector4 Material,Vector4 Highlight,Vector4 Output);
}