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,Pack=1)]
internal readonly record struct GalaxyBlackHoleInstance(Vector3 World,Vector4 WeightsLayer,Half A,Half B,Half Size,Half D,Vector4 Colour)
{
internal static GalaxyBlackHoleInstance Create(Vector3 world,float size)=>new(world,new(1,1,0,0),(Half)1,(Half).1f,(Half)size,(Half)10,Vector4.One);
}
internal sealed partial class GalaxyGraphics
{
private ID3D11VertexShader blackHoleVs=null!;
private ID3D11PixelShader blackHolePs=null!;
private ID3D11InputLayout blackHoleLayout=null!;
private ID3D11Buffer blackHoleBuffer=null!,blackHoleConstants=null!;
private ID3D11BlendState blackHoleBlend=null!;
private ID3D11Texture2D blackHoleTexture=null!;
private ID3D11ShaderResourceView blackHoleView=null!;
private GalaxyBlackHoleInstance[] blackHoleInstances=new GalaxyBlackHoleInstance[64];
internal int OriginalBlackHolesDrawn {get;private set;}
private void InitializeOriginalBlackHoles(string shader)
{
var vs=Compiler.CompileFromFile(shader,"VSOriginalBlackHole","vs_5_0");blackHoleVs=device.CreateVertexShader(vs.Span);
blackHolePs=device.CreatePixelShader(Compiler.CompileFromFile(shader,"PSOriginalBlackHole","ps_5_0").Span);
blackHoleLayout=device.CreateInputLayout([
new InputElementDescription("POSITION",0,Format.R32G32B32_Float,0,0,InputClassification.PerInstanceData,1),
new InputElementDescription("POSITION",2,Format.R32G32B32A32_Float,12,0,InputClassification.PerInstanceData,1),
new InputElementDescription("TEXCOORD",3,Format.R16G16B16A16_Float,28,0,InputClassification.PerInstanceData,1),
new InputElementDescription("POSITION",4,Format.R32G32B32A32_Float,36,0,InputClassification.PerInstanceData,1)],vs.Span);
blackHoleBuffer=device.CreateBuffer(StarCapacity*52,BindFlags.VertexBuffer,ResourceUsage.Dynamic,CpuAccessFlags.Write);
blackHoleConstants=device.CreateBuffer(6*16,BindFlags.ConstantBuffer);
// The actual generic publisher overrides authored pDestBlend7 with1.
// Signed source RGB darkens the scene through its original additive state.
blackHoleBlend=device.CreateBlendState(new BlendDescription(Blend.SourceAlpha,Blend.One));
if(!MemoryMarshal.TryGetArray(GalaxyOriginalBlackHole.Payload,out ArraySegment<byte> bytes)||bytes.Array is null)throw new InvalidDataException("原黑洞纹理不可用。");
var pin=GCHandle.Alloc(bytes.Array,GCHandleType.Pinned);
try
{
var slices=GalaxyOriginalBlackHole.Mips.Select(m=>new SubresourceData(pin.AddrOfPinnedObject()+bytes.Offset+m.Offset,(uint)m.RowPitch,(uint)m.SliceBytes)).ToArray();
blackHoleTexture=device.CreateTexture2D(new Texture2DDescription{Width=512,Height=512,ArraySize=1,MipLevels=10,Format=Format.BC1_UNorm,
SampleDescription=new(1,0),Usage=ResourceUsage.Immutable,BindFlags=BindFlags.ShaderResource},slices);
blackHoleView=device.CreateShaderResourceView(blackHoleTexture);
}
finally{pin.Free();}
}
private void DrawOriginalBlackHoles(ReadOnlySpan<GalaxyStar> stars,GalaxyCamera camera,bool realistic,bool navigationMarkers,float hdrWrite)
{
OriginalBlackHolesDrawn=0;if(!realistic||!navigationMarkers)return;
foreach(var star in stars)
{
var colour=star.OriginalColour??star.Colour;
if(!star.OriginalBlackHole||star.Radius<=0||colour.W<=0||!float.IsFinite(colour.X+colour.Y+colour.Z+colour.W)||GalaxyOriginalBlackHole.HalfExtent(star.OriginalSize)<=0)continue;
var position=new XFEEDToolBox.Core.Models.Coordinates(star.World.X,star.World.Y,star.World.Z);
// Main already supplied only retained, strictly queried catalogue
// objects. Its whole-cell/D50 envelope is not this rebuilt lens's
// fallback4D boundary; apply only the actual source projection here.
if(!camera.Project(position).IsVisible)continue;
if(OriginalBlackHolesDrawn==blackHoleInstances.Length)Array.Resize(ref blackHoleInstances,Math.Min(StarCapacity,blackHoleInstances.Length*2));
blackHoleInstances[OriginalBlackHolesDrawn++]=GalaxyBlackHoleInstance.Create(new(star.World.X,star.World.Y,star.World.Z),star.OriginalSize);
}
if(OriginalBlackHolesDrawn==0)return;
var eye=camera.Eye;var r=camera.Right;var up=camera.Up;var f=camera.Forward;
Vector4[] values=[new((float)eye.X,(float)eye.Y,(float)eye.Z,(float)camera.FocalLength),
new((float)r.X,(float)r.Y,(float)r.Z,(float)camera.Width),new((float)up.X,(float)up.Y,(float)up.Z,(float)camera.Height),
new((float)f.X,(float)f.Y,(float)f.Z,(float)camera.Near),GalaxyOriginalBlackHole.Material(),new(hdrWrite,0,0,0)];
context.UpdateSubresource<Vector4>(values,blackHoleConstants);
Upload<GalaxyBlackHoleInstance>(blackHoleBuffer,blackHoleInstances.AsSpan(0,OriginalBlackHolesDrawn));
context.IASetInputLayout(blackHoleLayout);context.IASetPrimitiveTopology(PrimitiveTopology.TriangleList);context.IASetVertexBuffer(0,blackHoleBuffer,52);
context.VSSetShader(blackHoleVs);context.PSSetShader(blackHolePs);context.VSSetConstantBuffer(9,blackHoleConstants);context.PSSetConstantBuffer(9,blackHoleConstants);
context.OMSetBlendState(blackHoleBlend);context.PSSetShaderResource(18,blackHoleView);context.PSSetSampler(0,sampler);
context.DrawInstanced(6,(uint)OriginalBlackHolesDrawn,0,0);DrawCalls++;context.PSSetShaderResource(18,null!);
}
private void DisposeOriginalBlackHoles()
{
blackHoleVs.Dispose();blackHolePs.Dispose();blackHoleLayout.Dispose();blackHoleBuffer.Dispose();blackHoleConstants.Dispose();
blackHoleBlend.Dispose();blackHoleView.Dispose();blackHoleTexture.Dispose();
}
}
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,Pack=1)]
internal readonly record struct GalaxyBlackHoleInstance(Vector3 World,Vector4 WeightsLayer,Half A,Half B,Half Size,Half D,Vector4 Colour)
{
internal static GalaxyBlackHoleInstance Create(Vector3 world,float size)=>new(world,new(1,1,0,0),(Half)1,(Half).1f,(Half)size,(Half)10,Vector4.One);
}
internal sealed partial class GalaxyGraphics
{
private ID3D11VertexShader blackHoleVs=null!;
private ID3D11PixelShader blackHolePs=null!;
private ID3D11InputLayout blackHoleLayout=null!;
private ID3D11Buffer blackHoleBuffer=null!,blackHoleConstants=null!;
private ID3D11BlendState blackHoleBlend=null!;
private ID3D11Texture2D blackHoleTexture=null!;
private ID3D11ShaderResourceView blackHoleView=null!;
private GalaxyBlackHoleInstance[] blackHoleInstances=new GalaxyBlackHoleInstance[64];
internal int OriginalBlackHolesDrawn {get;private set;}
private void InitializeOriginalBlackHoles(string shader)
{
var vs=Compiler.CompileFromFile(shader,"VSOriginalBlackHole","vs_5_0");blackHoleVs=device.CreateVertexShader(vs.Span);
blackHolePs=device.CreatePixelShader(Compiler.CompileFromFile(shader,"PSOriginalBlackHole","ps_5_0").Span);
blackHoleLayout=device.CreateInputLayout([
new InputElementDescription("POSITION",0,Format.R32G32B32_Float,0,0,InputClassification.PerInstanceData,1),
new InputElementDescription("POSITION",2,Format.R32G32B32A32_Float,12,0,InputClassification.PerInstanceData,1),
new InputElementDescription("TEXCOORD",3,Format.R16G16B16A16_Float,28,0,InputClassification.PerInstanceData,1),
new InputElementDescription("POSITION",4,Format.R32G32B32A32_Float,36,0,InputClassification.PerInstanceData,1)],vs.Span);
blackHoleBuffer=device.CreateBuffer(StarCapacity*52,BindFlags.VertexBuffer,ResourceUsage.Dynamic,CpuAccessFlags.Write);
blackHoleConstants=device.CreateBuffer(6*16,BindFlags.ConstantBuffer);
// The actual generic publisher overrides authored pDestBlend7 with1.
// Signed source RGB darkens the scene through its original additive state.
blackHoleBlend=device.CreateBlendState(new BlendDescription(Blend.SourceAlpha,Blend.One));
if(!MemoryMarshal.TryGetArray(GalaxyOriginalBlackHole.Payload,out ArraySegment<byte> bytes)||bytes.Array is null)throw new InvalidDataException("原黑洞纹理不可用。");
var pin=GCHandle.Alloc(bytes.Array,GCHandleType.Pinned);
try
{
var slices=GalaxyOriginalBlackHole.Mips.Select(m=>new SubresourceData(pin.AddrOfPinnedObject()+bytes.Offset+m.Offset,(uint)m.RowPitch,(uint)m.SliceBytes)).ToArray();
blackHoleTexture=device.CreateTexture2D(new Texture2DDescription{Width=512,Height=512,ArraySize=1,MipLevels=10,Format=Format.BC1_UNorm,
SampleDescription=new(1,0),Usage=ResourceUsage.Immutable,BindFlags=BindFlags.ShaderResource},slices);
blackHoleView=device.CreateShaderResourceView(blackHoleTexture);
}
finally{pin.Free();}
}
private void DrawOriginalBlackHoles(ReadOnlySpan<GalaxyStar> stars,GalaxyCamera camera,bool realistic,bool navigationMarkers,float hdrWrite)
{
OriginalBlackHolesDrawn=0;if(!realistic||!navigationMarkers)return;
foreach(var star in stars)
{
var colour=star.OriginalColour??star.Colour;
if(!star.OriginalBlackHole||star.Radius<=0||colour.W<=0||!float.IsFinite(colour.X+colour.Y+colour.Z+colour.W)||GalaxyOriginalBlackHole.HalfExtent(star.OriginalSize)<=0)continue;
var position=new XFEEDToolBox.Core.Models.Coordinates(star.World.X,star.World.Y,star.World.Z);
// Main already supplied only retained, strictly queried catalogue
// objects. Its whole-cell/D50 envelope is not this rebuilt lens's
// fallback4D boundary; apply only the actual source projection here.
if(!camera.Project(position).IsVisible)continue;
if(OriginalBlackHolesDrawn==blackHoleInstances.Length)Array.Resize(ref blackHoleInstances,Math.Min(StarCapacity,blackHoleInstances.Length*2));
blackHoleInstances[OriginalBlackHolesDrawn++]=GalaxyBlackHoleInstance.Create(new(star.World.X,star.World.Y,star.World.Z),star.OriginalSize);
}
if(OriginalBlackHolesDrawn==0)return;
var eye=camera.Eye;var r=camera.Right;var up=camera.Up;var f=camera.Forward;
Vector4[] values=[new((float)eye.X,(float)eye.Y,(float)eye.Z,(float)camera.FocalLength),
new((float)r.X,(float)r.Y,(float)r.Z,(float)camera.Width),new((float)up.X,(float)up.Y,(float)up.Z,(float)camera.Height),
new((float)f.X,(float)f.Y,(float)f.Z,(float)camera.Near),GalaxyOriginalBlackHole.Material(),new(hdrWrite,0,0,0)];
context.UpdateSubresource<Vector4>(values,blackHoleConstants);
Upload<GalaxyBlackHoleInstance>(blackHoleBuffer,blackHoleInstances.AsSpan(0,OriginalBlackHolesDrawn));
context.IASetInputLayout(blackHoleLayout);context.IASetPrimitiveTopology(PrimitiveTopology.TriangleList);context.IASetVertexBuffer(0,blackHoleBuffer,52);
context.VSSetShader(blackHoleVs);context.PSSetShader(blackHolePs);context.VSSetConstantBuffer(9,blackHoleConstants);context.PSSetConstantBuffer(9,blackHoleConstants);
context.OMSetBlendState(blackHoleBlend);context.PSSetShaderResource(18,blackHoleView);context.PSSetSampler(0,sampler);
context.DrawInstanced(6,(uint)OriginalBlackHolesDrawn,0,0);DrawCalls++;context.PSSetShaderResource(18,null!);
}
private void DisposeOriginalBlackHoles()
{
blackHoleVs.Dispose();blackHolePs.Dispose();blackHoleLayout.Dispose();blackHoleBuffer.Dispose();blackHoleConstants.Dispose();
blackHoleBlend.Dispose();blackHoleView.Dispose();blackHoleTexture.Dispose();
}
}