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 originalCoreVs=null!;
    private ID3D11PixelShader originalCorePs=null!;
    private ID3D11InputLayout originalCoreLayout=null!;
    private ID3D11Buffer originalCoreVertices=null!,originalCoreIndices=null!,originalCoreConstants=null!;
    private ID3D11Texture2D originalCoreTexture=null!;
    private ID3D11ShaderResourceView originalCoreView=null!;
    private ID3D11SamplerState originalCoreSampler=null!;
    private ID3D11BlendState originalCoreBlend=null!;
    internal bool OriginalCoreReady=>originalCoreView is not null;
    internal bool OriginalCoreFullRestored=>false;

    private void InitializeOriginalCore(string shader)
    {
        var source=GalaxyOriginalCore.Reference;
        var vertex=Compiler.CompileFromFile(shader,"VSOriginalCore","vs_5_0");originalCoreVs=device.CreateVertexShader(vertex.Span);
        originalCorePs=device.CreatePixelShader(Compiler.CompileFromFile(shader,"PSOriginalCore","ps_5_0").Span);
        originalCoreLayout=device.CreateInputLayout([new InputElementDescription("POSITION",0,Format.R32G32B32_Float,0,0)],vertex.Span);
        originalCoreVertices=device.CreateBuffer<Vector3>(source.Positions.ToArray(),BindFlags.VertexBuffer);
        originalCoreIndices=device.CreateBuffer<ushort>(source.Indices.ToArray(),BindFlags.IndexBuffer);
        originalCoreConstants=device.CreateBuffer(13*16,BindFlags.ConstantBuffer);
        originalCoreSampler=device.CreateSamplerState(new SamplerDescription(Filter.MinMagMipLinear,TextureAddressMode.Wrap,TextureAddressMode.Wrap,TextureAddressMode.Wrap));
        // Original513D70/table4E2E460 maps enum2 to RGBSourceColor and
        // AlphaSourceAlpha; enum1 maps both to One. The complete original
        // FGM flag/layer pipeline remains a separate restoration stage.
        originalCoreBlend=device.CreateBlendState(new BlendDescription(Blend.SourceColor,Blend.One,Blend.SourceAlpha,Blend.One));
        if(!MemoryMarshal.TryGetArray(source.NoisePayload,out ArraySegment<byte> bytes)||bytes.Array is null)
            throw new InvalidDataException("原银河核心纹理缓冲区不可用。");
        var pin=GCHandle.Alloc(bytes.Array,GCHandleType.Pinned);
        try
        {
            var slices=source.NoiseMips.Select(m=>new SubresourceData(pin.AddrOfPinnedObject()+bytes.Offset+m.Offset,(uint)m.RowPitch,(uint)m.DepthPitch)).ToArray();
            originalCoreTexture=device.CreateTexture2D(new Texture2DDescription{Width=16,Height=16,ArraySize=1,MipLevels=5,
                Format=Format.BC1_UNorm,SampleDescription=new(1,0),Usage=ResourceUsage.Immutable,BindFlags=BindFlags.ShaderResource},slices);
            originalCoreView=device.CreateShaderResourceView(originalCoreTexture);
        }
        finally{pin.Free();}
    }
    private void DrawOriginalCore(GalaxyCamera camera,bool showBackground,float hdrWrite=1,float hdrRead=1)
    {
        if(!showBackground||!OriginalCoreReady)return;
        var eye=camera.Eye;var right=camera.Right;var up=camera.Up;var forward=camera.Forward;
        var values=GalaxyOriginalCore.Reference.MaterialConstants;
        var frame=new OriginalCoreFrame(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),
            // Explicit shared HDR inputs. Defaults retain the independent
            // source-space probe; the final-HDR path supplies verified ctor
            // defaults Write1/256,Read256 without an arbitrary gain.
            new(0,hdrWrite,hdrRead,0),values[0],values[1],values[2],values[3],values[4],values[5],values[6],values[7]);
        context.UpdateSubresource(in frame,originalCoreConstants);context.VSSetConstantBuffer(6,originalCoreConstants);context.PSSetConstantBuffer(6,originalCoreConstants);
        context.IASetInputLayout(originalCoreLayout);context.IASetPrimitiveTopology(PrimitiveTopology.TriangleList);
        context.IASetVertexBuffer(0,originalCoreVertices,12);context.IASetIndexBuffer(originalCoreIndices,Format.R16_UInt,0);
        context.VSSetShader(originalCoreVs);context.PSSetShader(originalCorePs);context.PSSetShaderResource(16,originalCoreView);context.PSSetSampler(1,originalCoreSampler);
        context.OMSetBlendState(originalCoreBlend);context.DrawIndexed(576,0,0);DrawCalls++;
        context.PSSetShaderResource(16,null!);context.PSSetSampler(1,null!);context.OMSetBlendState(additive);
    }
    private void DisposeOriginalCore()
    {
        originalCoreVs.Dispose();originalCorePs.Dispose();originalCoreLayout.Dispose();originalCoreVertices.Dispose();originalCoreIndices.Dispose();
        originalCoreConstants.Dispose();originalCoreView.Dispose();originalCoreTexture.Dispose();originalCoreSampler.Dispose();originalCoreBlend.Dispose();
    }
    [StructLayout(LayoutKind.Sequential)]
    private readonly record struct OriginalCoreFrame(Vector4 EyeFocal,Vector4 RightWidth,Vector4 UpHeight,Vector4 ForwardNear,Vector4 Output,
        Vector4 InnerColour,Vector4 OuterColour,Vector4 ColourScalePower,Vector4 CentreRadius,Vector4 RadiusShape,Vector4 OuterShape,Vector4 DitherInternal,Vector4 MinMax);
}