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);
}
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);
}