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;
[StructLayout(LayoutKind.Sequential)]
internal readonly record struct GalaxyGridHalfFields(Half X,Half Y,Half Z,Half W);
[StructLayout(LayoutKind.Sequential)]
internal readonly record struct GalaxyGridPrimitive(Vector3 From,Vector3 To,GalaxyGridHalfFields Shape,Vector4 Colour,Vector4 Pattern);
internal sealed partial class GalaxyGraphics
{
private readonly GalaxyGridPrimitive[] originalGridPrimitives=new GalaxyGridPrimitive[GalaxyOriginalGrid.MaximumLines];
private readonly GalaxyGridPrimitive[] originalConstellationPrimitives=new GalaxyGridPrimitive[GalaxyOriginalConstellations.MaximumSegments];
private ID3D11VertexShader originalGridVs=null!;
private ID3D11PixelShader originalGridPs=null!;
private ID3D11InputLayout originalGridLayout=null!;
private ID3D11Buffer originalGridBuffer=null!,originalGridConstants=null!;
private ID3D11Buffer originalConstellationBuffer=null!;
private ID3D11Texture2D originalGridTexture=null!;
private ID3D11ShaderResourceView originalGridView=null!;
private ID3D11SamplerState originalGridSampler=null!;
private ID3D11Buffer originalSourceOutputConstants=null!;
private ID3D11BlendState originalSourceAlphaBlend=null!;
private int originalGridCount;
private int originalConstellationCount;
internal int SubmittedOriginalGridLines=>originalGridCount;
internal int SubmittedOriginalConstellationLines=>originalConstellationCount;
internal bool OriginalGridWorldWidthRestored=>true;
internal bool OriginalConstellationWorldStyleRestored=>true;
// The world quad, half-precision width and actual texture are restored.
// The actual shared RGB Write multiplier and SrcAlpha/One blend are
// explicit inputs. Final output and sampler quality remain separate.
internal bool OriginalGridFullRestored=>false;
internal void SetOriginalGrid(ReadOnlySpan<GalaxyOriginalGridLine> lines)
{
originalGridCount=0;
var colour=GalaxyOriginalGrid.Colour;
foreach(var line in lines)
{
if(originalGridCount==originalGridPrimitives.Length)break;
if(!double.IsFinite(line.FromX+line.FromY+line.FromZ+line.ToX+line.ToY+line.ToZ)||
!float.IsFinite(line.WidthMultiplier)||line.WidthMultiplier<=0)continue;
var halfWidth=(Half)(GalaxyOriginalGrid.BaseWidth*line.WidthMultiplier);
if(!Half.IsFinite(halfWidth)||halfWidth<=Half.Zero)continue;
// Original3A1EDE0 snaps in Sol coordinates, then adds the original
// origin before3C11750 stores both absolute float XYZ endpoints.
var from=new Vector3((float)(line.FromX+49985),(float)(line.FromY+40985),(float)(line.FromZ+24105));
var to=new Vector3((float)(line.ToX+49985),(float)(line.ToY+40985),(float)(line.ToZ+24105));
if(from==to)continue;
originalGridPrimitives[originalGridCount++]=new(from,to,new((Half)10,(Half).1f,halfWidth,(Half)10),
new(colour.R,colour.G,colour.B,colour.A),new(0,8,1,0));
}
}
internal void SetOriginalConstellations(IReadOnlyList<GalaxyResolvedConstellation> groups,GalaxyCamera camera)
{
originalConstellationCount=0;
foreach(var group in groups)
{
var alpha=(float)GalaxyOriginalConstellations.Alpha(group,camera.Eye,camera.Focus);
if(alpha<=GalaxyOriginalConstellations.SubmissionAlpha)continue;
foreach(var line in group.Lines)
{
if(originalConstellationCount==originalConstellationPrimitives.Length)return;
if(!line.From.IsValid||!line.To.IsValid)continue;
var from=new Vector3((float)(line.From.X+49985),(float)(line.From.Y+40985),(float)(line.From.Z+24105));
var to=new Vector3((float)(line.To.X+49985),(float)(line.To.Y+40985),(float)(line.To.Z+24105));
if(from==to)continue;
originalConstellationPrimitives[originalConstellationCount++]=new(from,to,
new((Half)10,(Half).1f,(Half)GalaxyOriginalConstellations.WorldHalfWidth,(Half)10),new(1,1,1,alpha),
new(0,8,GalaxyOriginalConstellations.TextureRepeatPerLightYear,0));
}
}
}
private void InitializeOriginalGrid(string shader)
{
if(Marshal.SizeOf<GalaxyGridPrimitive>()!=64)throw new InvalidDataException("原银河网格顶点格式无效。");
var vertex=Compiler.CompileFromFile(shader,"VSOriginalGrid","vs_5_0");originalGridVs=device.CreateVertexShader(vertex.Span);
originalGridPs=device.CreatePixelShader(Compiler.CompileFromFile(shader,"PSOriginalGrid","ps_5_0").Span);
originalGridLayout=device.CreateInputLayout([
new InputElementDescription("POSITION",0,Format.R32G32B32_Float,0,0,InputClassification.PerInstanceData,1),
new InputElementDescription("POSITION",1,Format.R32G32B32_Float,12,0,InputClassification.PerInstanceData,1),
new InputElementDescription("SHAPE",0,Format.R16G16B16A16_Float,24,0,InputClassification.PerInstanceData,1),
new InputElementDescription("COLOR",0,Format.R32G32B32A32_Float,32,0,InputClassification.PerInstanceData,1),
new InputElementDescription("PATTERN",0,Format.R32G32B32A32_Float,48,0,InputClassification.PerInstanceData,1)],vertex.Span);
originalGridBuffer=device.CreateBuffer(GalaxyOriginalGrid.MaximumLines*64,BindFlags.VertexBuffer,ResourceUsage.Dynamic,CpuAccessFlags.Write);
originalConstellationBuffer=device.CreateBuffer(GalaxyOriginalConstellations.MaximumSegments*64,BindFlags.VertexBuffer,ResourceUsage.Dynamic,CpuAccessFlags.Write);
originalGridConstants=device.CreateBuffer(96,BindFlags.ConstantBuffer);
originalSourceOutputConstants=device.CreateBuffer(16,BindFlags.ConstantBuffer);
// Actual kind-5 StarMapLine/BackgroundStars effect state, followed by
// 516980 -> 513D70: RGB and alpha both SrcAlpha/One/Add.
originalSourceAlphaBlend=device.CreateBlendState(new BlendDescription(Blend.SourceAlpha,Blend.One));
originalGridSampler=device.CreateSamplerState(new SamplerDescription(Filter.MinMagMipLinear,TextureAddressMode.Wrap,TextureAddressMode.Wrap,TextureAddressMode.Wrap));
var source=GalaxyOriginalGridTexture.Reference;
if(!MemoryMarshal.TryGetArray(source.Payload,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();
originalGridTexture=device.CreateTexture2D(new Texture2DDescription{Width=GalaxyOriginalGridTexture.Width,Height=GalaxyOriginalGridTexture.Height,
ArraySize=1,MipLevels=GalaxyOriginalGridTexture.MipCount,Format=Format.BC7_UNorm,SampleDescription=new(1,0),
Usage=ResourceUsage.Immutable,BindFlags=BindFlags.ShaderResource},slices);
originalGridView=device.CreateShaderResourceView(originalGridTexture);
}
finally{pin.Free();}
}
/// <summary>
/// Bind original source output independently of the scene target. A value
/// of one is intentional for source-space probes; production supplies the
/// recovered shared HDR Write. Alpha is never multiplied by Write.
/// </summary>
private void BindOriginalSourceOutput(float hdrWrite=1,bool applySourceAlphaBlend=true)
{
if(!float.IsFinite(hdrWrite)||hdrWrite<=0)throw new ArgumentOutOfRangeException(nameof(hdrWrite));
var output=new Vector4(hdrWrite,1,0,0);
context.UpdateSubresource(in output,originalSourceOutputConstants);
context.PSSetConstantBuffer(8,originalSourceOutputConstants);
if(applySourceAlphaBlend)context.OMSetBlendState(originalSourceAlphaBlend);
}
private void DrawOriginalGrid(GalaxyCamera camera,float hdrWrite=1)
{
if(originalGridCount==0&&originalConstellationCount==0)return;
BindOriginalSourceOutput(hdrWrite);
var eye=camera.Eye;var right=camera.Right;var up=camera.Up;var forward=camera.Forward;
var frame=new OriginalGridCamera(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((float)camera.ProjectionFar,1,0,0),
GalaxyOriginalGridTexture.Reference.AuthoredFade);
context.UpdateSubresource(in frame,originalGridConstants);context.VSSetConstantBuffer(4,originalGridConstants);context.PSSetConstantBuffer(4,originalGridConstants);
context.IASetInputLayout(originalGridLayout);context.IASetPrimitiveTopology(PrimitiveTopology.TriangleList);
context.VSSetShader(originalGridVs);context.PSSetShader(originalGridPs);context.PSSetShaderResource(12,originalGridView);context.PSSetSampler(0,originalGridSampler);
if(originalGridCount>0)
{
Upload<GalaxyGridPrimitive>(originalGridBuffer,originalGridPrimitives.AsSpan(0,originalGridCount));
context.IASetVertexBuffer(0,originalGridBuffer,64);context.DrawInstanced(6,(uint)originalGridCount,0,0);DrawCalls++;
}
if(originalConstellationCount>0)
{
Upload<GalaxyGridPrimitive>(originalConstellationBuffer,originalConstellationPrimitives.AsSpan(0,originalConstellationCount));
context.IASetVertexBuffer(0,originalConstellationBuffer,64);context.DrawInstanced(6,(uint)originalConstellationCount,0,0);DrawCalls++;
}
context.PSSetShaderResource(12,null!);context.PSSetSampler(0,sampler);
context.OMSetBlendState(additive);
}
private void DisposeOriginalGrid()
{
originalGridVs.Dispose();originalGridPs.Dispose();originalGridLayout.Dispose();originalGridBuffer.Dispose();originalGridConstants.Dispose();
originalGridView.Dispose();originalGridTexture.Dispose();originalGridSampler.Dispose();
originalSourceOutputConstants.Dispose();originalSourceAlphaBlend.Dispose();
originalConstellationBuffer.Dispose();
}
[StructLayout(LayoutKind.Sequential)]
private readonly record struct OriginalGridCamera(Vector4 EyeFocal,Vector4 RightWidth,Vector4 UpHeight,Vector4 ForwardNear,Vector4 Projection,Vector4 Fade);
}
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;
[StructLayout(LayoutKind.Sequential)]
internal readonly record struct GalaxyGridHalfFields(Half X,Half Y,Half Z,Half W);
[StructLayout(LayoutKind.Sequential)]
internal readonly record struct GalaxyGridPrimitive(Vector3 From,Vector3 To,GalaxyGridHalfFields Shape,Vector4 Colour,Vector4 Pattern);
internal sealed partial class GalaxyGraphics
{
private readonly GalaxyGridPrimitive[] originalGridPrimitives=new GalaxyGridPrimitive[GalaxyOriginalGrid.MaximumLines];
private readonly GalaxyGridPrimitive[] originalConstellationPrimitives=new GalaxyGridPrimitive[GalaxyOriginalConstellations.MaximumSegments];
private ID3D11VertexShader originalGridVs=null!;
private ID3D11PixelShader originalGridPs=null!;
private ID3D11InputLayout originalGridLayout=null!;
private ID3D11Buffer originalGridBuffer=null!,originalGridConstants=null!;
private ID3D11Buffer originalConstellationBuffer=null!;
private ID3D11Texture2D originalGridTexture=null!;
private ID3D11ShaderResourceView originalGridView=null!;
private ID3D11SamplerState originalGridSampler=null!;
private ID3D11Buffer originalSourceOutputConstants=null!;
private ID3D11BlendState originalSourceAlphaBlend=null!;
private int originalGridCount;
private int originalConstellationCount;
internal int SubmittedOriginalGridLines=>originalGridCount;
internal int SubmittedOriginalConstellationLines=>originalConstellationCount;
internal bool OriginalGridWorldWidthRestored=>true;
internal bool OriginalConstellationWorldStyleRestored=>true;
// The world quad, half-precision width and actual texture are restored.
// The actual shared RGB Write multiplier and SrcAlpha/One blend are
// explicit inputs. Final output and sampler quality remain separate.
internal bool OriginalGridFullRestored=>false;
internal void SetOriginalGrid(ReadOnlySpan<GalaxyOriginalGridLine> lines)
{
originalGridCount=0;
var colour=GalaxyOriginalGrid.Colour;
foreach(var line in lines)
{
if(originalGridCount==originalGridPrimitives.Length)break;
if(!double.IsFinite(line.FromX+line.FromY+line.FromZ+line.ToX+line.ToY+line.ToZ)||
!float.IsFinite(line.WidthMultiplier)||line.WidthMultiplier<=0)continue;
var halfWidth=(Half)(GalaxyOriginalGrid.BaseWidth*line.WidthMultiplier);
if(!Half.IsFinite(halfWidth)||halfWidth<=Half.Zero)continue;
// Original3A1EDE0 snaps in Sol coordinates, then adds the original
// origin before3C11750 stores both absolute float XYZ endpoints.
var from=new Vector3((float)(line.FromX+49985),(float)(line.FromY+40985),(float)(line.FromZ+24105));
var to=new Vector3((float)(line.ToX+49985),(float)(line.ToY+40985),(float)(line.ToZ+24105));
if(from==to)continue;
originalGridPrimitives[originalGridCount++]=new(from,to,new((Half)10,(Half).1f,halfWidth,(Half)10),
new(colour.R,colour.G,colour.B,colour.A),new(0,8,1,0));
}
}
internal void SetOriginalConstellations(IReadOnlyList<GalaxyResolvedConstellation> groups,GalaxyCamera camera)
{
originalConstellationCount=0;
foreach(var group in groups)
{
var alpha=(float)GalaxyOriginalConstellations.Alpha(group,camera.Eye,camera.Focus);
if(alpha<=GalaxyOriginalConstellations.SubmissionAlpha)continue;
foreach(var line in group.Lines)
{
if(originalConstellationCount==originalConstellationPrimitives.Length)return;
if(!line.From.IsValid||!line.To.IsValid)continue;
var from=new Vector3((float)(line.From.X+49985),(float)(line.From.Y+40985),(float)(line.From.Z+24105));
var to=new Vector3((float)(line.To.X+49985),(float)(line.To.Y+40985),(float)(line.To.Z+24105));
if(from==to)continue;
originalConstellationPrimitives[originalConstellationCount++]=new(from,to,
new((Half)10,(Half).1f,(Half)GalaxyOriginalConstellations.WorldHalfWidth,(Half)10),new(1,1,1,alpha),
new(0,8,GalaxyOriginalConstellations.TextureRepeatPerLightYear,0));
}
}
}
private void InitializeOriginalGrid(string shader)
{
if(Marshal.SizeOf<GalaxyGridPrimitive>()!=64)throw new InvalidDataException("原银河网格顶点格式无效。");
var vertex=Compiler.CompileFromFile(shader,"VSOriginalGrid","vs_5_0");originalGridVs=device.CreateVertexShader(vertex.Span);
originalGridPs=device.CreatePixelShader(Compiler.CompileFromFile(shader,"PSOriginalGrid","ps_5_0").Span);
originalGridLayout=device.CreateInputLayout([
new InputElementDescription("POSITION",0,Format.R32G32B32_Float,0,0,InputClassification.PerInstanceData,1),
new InputElementDescription("POSITION",1,Format.R32G32B32_Float,12,0,InputClassification.PerInstanceData,1),
new InputElementDescription("SHAPE",0,Format.R16G16B16A16_Float,24,0,InputClassification.PerInstanceData,1),
new InputElementDescription("COLOR",0,Format.R32G32B32A32_Float,32,0,InputClassification.PerInstanceData,1),
new InputElementDescription("PATTERN",0,Format.R32G32B32A32_Float,48,0,InputClassification.PerInstanceData,1)],vertex.Span);
originalGridBuffer=device.CreateBuffer(GalaxyOriginalGrid.MaximumLines*64,BindFlags.VertexBuffer,ResourceUsage.Dynamic,CpuAccessFlags.Write);
originalConstellationBuffer=device.CreateBuffer(GalaxyOriginalConstellations.MaximumSegments*64,BindFlags.VertexBuffer,ResourceUsage.Dynamic,CpuAccessFlags.Write);
originalGridConstants=device.CreateBuffer(96,BindFlags.ConstantBuffer);
originalSourceOutputConstants=device.CreateBuffer(16,BindFlags.ConstantBuffer);
// Actual kind-5 StarMapLine/BackgroundStars effect state, followed by
// 516980 -> 513D70: RGB and alpha both SrcAlpha/One/Add.
originalSourceAlphaBlend=device.CreateBlendState(new BlendDescription(Blend.SourceAlpha,Blend.One));
originalGridSampler=device.CreateSamplerState(new SamplerDescription(Filter.MinMagMipLinear,TextureAddressMode.Wrap,TextureAddressMode.Wrap,TextureAddressMode.Wrap));
var source=GalaxyOriginalGridTexture.Reference;
if(!MemoryMarshal.TryGetArray(source.Payload,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();
originalGridTexture=device.CreateTexture2D(new Texture2DDescription{Width=GalaxyOriginalGridTexture.Width,Height=GalaxyOriginalGridTexture.Height,
ArraySize=1,MipLevels=GalaxyOriginalGridTexture.MipCount,Format=Format.BC7_UNorm,SampleDescription=new(1,0),
Usage=ResourceUsage.Immutable,BindFlags=BindFlags.ShaderResource},slices);
originalGridView=device.CreateShaderResourceView(originalGridTexture);
}
finally{pin.Free();}
}
/// <summary>
/// Bind original source output independently of the scene target. A value
/// of one is intentional for source-space probes; production supplies the
/// recovered shared HDR Write. Alpha is never multiplied by Write.
/// </summary>
private void BindOriginalSourceOutput(float hdrWrite=1,bool applySourceAlphaBlend=true)
{
if(!float.IsFinite(hdrWrite)||hdrWrite<=0)throw new ArgumentOutOfRangeException(nameof(hdrWrite));
var output=new Vector4(hdrWrite,1,0,0);
context.UpdateSubresource(in output,originalSourceOutputConstants);
context.PSSetConstantBuffer(8,originalSourceOutputConstants);
if(applySourceAlphaBlend)context.OMSetBlendState(originalSourceAlphaBlend);
}
private void DrawOriginalGrid(GalaxyCamera camera,float hdrWrite=1)
{
if(originalGridCount==0&&originalConstellationCount==0)return;
BindOriginalSourceOutput(hdrWrite);
var eye=camera.Eye;var right=camera.Right;var up=camera.Up;var forward=camera.Forward;
var frame=new OriginalGridCamera(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((float)camera.ProjectionFar,1,0,0),
GalaxyOriginalGridTexture.Reference.AuthoredFade);
context.UpdateSubresource(in frame,originalGridConstants);context.VSSetConstantBuffer(4,originalGridConstants);context.PSSetConstantBuffer(4,originalGridConstants);
context.IASetInputLayout(originalGridLayout);context.IASetPrimitiveTopology(PrimitiveTopology.TriangleList);
context.VSSetShader(originalGridVs);context.PSSetShader(originalGridPs);context.PSSetShaderResource(12,originalGridView);context.PSSetSampler(0,originalGridSampler);
if(originalGridCount>0)
{
Upload<GalaxyGridPrimitive>(originalGridBuffer,originalGridPrimitives.AsSpan(0,originalGridCount));
context.IASetVertexBuffer(0,originalGridBuffer,64);context.DrawInstanced(6,(uint)originalGridCount,0,0);DrawCalls++;
}
if(originalConstellationCount>0)
{
Upload<GalaxyGridPrimitive>(originalConstellationBuffer,originalConstellationPrimitives.AsSpan(0,originalConstellationCount));
context.IASetVertexBuffer(0,originalConstellationBuffer,64);context.DrawInstanced(6,(uint)originalConstellationCount,0,0);DrawCalls++;
}
context.PSSetShaderResource(12,null!);context.PSSetSampler(0,sampler);
context.OMSetBlendState(additive);
}
private void DisposeOriginalGrid()
{
originalGridVs.Dispose();originalGridPs.Dispose();originalGridLayout.Dispose();originalGridBuffer.Dispose();originalGridConstants.Dispose();
originalGridView.Dispose();originalGridTexture.Dispose();originalGridSampler.Dispose();
originalSourceOutputConstants.Dispose();originalSourceAlphaBlend.Dispose();
originalConstellationBuffer.Dispose();
}
[StructLayout(LayoutKind.Sequential)]
private readonly record struct OriginalGridCamera(Vector4 EyeFocal,Vector4 RightWidth,Vector4 UpHeight,Vector4 ForwardNear,Vector4 Projection,Vector4 Fade);
}