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 originalPlaneVs=null!;
    private ID3D11PixelShader originalPlanePs=null!;
    private ID3D11InputLayout originalPlaneLayout=null!;
    private ID3D11Buffer originalPlaneVertices=null!,originalPlaneIndices=null!,originalPlaneConstants=null!;
    private ID3D11Texture2D originalPlaneTexture=null!;
    private ID3D11ShaderResourceView originalPlaneView=null!;
    private ID3D11SamplerState originalPlaneSampler=null!;
    private ID3D11BlendState originalPlaneBlend=null!;
    internal bool OriginalPlaneReady=>originalPlaneView is not null;
    internal bool OriginalPlaneEnabled {get;set;}=true;
    internal bool OriginalPlaneFullRestored=>false;
    private void InitializeOriginalPlane(string shader)
    {
        var source=GalaxyOriginalPlane.Reference;
        var vertex=Compiler.CompileFromFile(shader,"VSOriginalPlane","vs_5_0");originalPlaneVs=device.CreateVertexShader(vertex.Span);
        originalPlanePs=device.CreatePixelShader(Compiler.CompileFromFile(shader,"PSOriginalPlane","ps_5_0").Span);
        originalPlaneLayout=device.CreateInputLayout([new InputElementDescription("POSITION",0,Format.R32G32B32_Float,0,0),
            new InputElementDescription("NORMAL",0,Format.R32G32B32_Float,12,0),new InputElementDescription("TEXCOORD",0,Format.R32G32_Float,24,0)],vertex.Span);
        originalPlaneVertices=device.CreateBuffer<GalaxyOriginalPlaneVertex>(source.Vertices.ToArray(),BindFlags.VertexBuffer);
        originalPlaneIndices=device.CreateBuffer<ushort>(source.Indices.ToArray(),BindFlags.IndexBuffer);
        originalPlaneConstants=device.CreateBuffer(8*16,BindFlags.ConstantBuffer);
        originalPlaneSampler=device.CreateSamplerState(new SamplerDescription(Filter.MinMagMipLinear,TextureAddressMode.Wrap,TextureAddressMode.Wrap,TextureAddressMode.Wrap));
        // Actual compiled effect copies these material Src4/Dest5/Op0 fields.
        // Later runtime material overrides remain independently unobserved.
        originalPlaneBlend=device.CreateBlendState(new BlendDescription(Blend.SourceAlpha,Blend.InverseSourceAlpha));
        if(!MemoryMarshal.TryGetArray(source.TexturePayload,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();
            originalPlaneTexture=device.CreateTexture2D(new Texture2DDescription{Width=2048,Height=2048,ArraySize=1,MipLevels=12,
                Format=Format.BC7_UNorm_SRgb,SampleDescription=new(1,0),Usage=ResourceUsage.Immutable,BindFlags=BindFlags.ShaderResource},slices);
            originalPlaneView=device.CreateShaderResourceView(originalPlaneTexture);
        }
        finally{pin.Free();}
    }
    private void DrawOriginalPlane(GalaxyCamera camera,bool showBackground,float hdrWrite=1)
    {
        if(!showBackground||!OriginalPlaneEnabled||!OriginalPlaneReady)return;
        var eye=camera.Eye;var right=camera.Right;var up=camera.Up;var forward=camera.Forward;var source=GalaxyOriginalPlane.Reference;
        var frame=new OriginalPlaneFrame(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(hdrWrite,0,0,0),source.Material0,source.Material1,GalaxyOriginalPlaneResources.Quaternion);
        context.UpdateSubresource(in frame,originalPlaneConstants);context.VSSetConstantBuffer(9,originalPlaneConstants);context.PSSetConstantBuffer(9,originalPlaneConstants);
        context.IASetInputLayout(originalPlaneLayout);context.IASetPrimitiveTopology(PrimitiveTopology.TriangleList);
        context.IASetVertexBuffer(0,originalPlaneVertices,32);context.IASetIndexBuffer(originalPlaneIndices,Format.R16_UInt,0);
        context.VSSetShader(originalPlaneVs);context.PSSetShader(originalPlanePs);context.PSSetShaderResource(18,originalPlaneView);context.PSSetSampler(3,originalPlaneSampler);
        context.OMSetBlendState(originalPlaneBlend);context.DrawIndexed(6,0,0);DrawCalls++;
        context.PSSetShaderResource(18,null!);context.PSSetSampler(3,null!);context.OMSetBlendState(additive);
    }
    private void DisposeOriginalPlane()
    {
        originalPlaneVs.Dispose();originalPlanePs.Dispose();originalPlaneLayout.Dispose();originalPlaneVertices.Dispose();originalPlaneIndices.Dispose();
        originalPlaneConstants.Dispose();originalPlaneView.Dispose();originalPlaneTexture.Dispose();originalPlaneSampler.Dispose();originalPlaneBlend.Dispose();
    }
    [StructLayout(LayoutKind.Sequential)]
    private readonly record struct OriginalPlaneFrame(Vector4 EyeFocal,Vector4 RightWidth,Vector4 UpHeight,Vector4 ForwardNear,
        Vector4 Output,Vector4 Material0,Vector4 Material1,Vector4 Quaternion);
}