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 powerActivityRingVs=null!;
private ID3D11PixelShader powerActivityRingPs=null!;
private ID3D11InputLayout powerActivityRingLayout=null!;
private ID3D11Buffer powerActivityRingInstance=null!,powerActivityRingConstants=null!;
private ID3D11BlendState powerActivityRingBlend=null!;
private GalaxyOriginalPowerActivityRing? powerActivityRing;
private float? powerActivityRingEmissive;
private bool powerActivityRingDefaultKnown;
private bool powerActivityRingInvalidSource;
internal int PreparedPowerActivityRings=>powerActivityRing is null?0:1;
internal int SubmittedPowerActivityRings {get;private set;}
internal bool PowerActivityRingSourceUnknown=>powerActivityRing is not null&&(powerActivityRingInvalidSource||powerActivityRingEmissive is null&&!OriginalExposureReady);
internal bool PowerActivityRingSourceDefaultKnown=>powerActivityRing is not null&&(powerActivityRingDefaultKnown||
!powerActivityRingInvalidSource&&powerActivityRingEmissive is null&&OriginalExposureState==GalaxyOriginalExposureState.DefaultCreated);
internal bool PowerActivityRingUsesToolManualExposure=>powerActivityRing is not null&&!powerActivityRingInvalidSource&&powerActivityRingEmissive is null&&OriginalExposureIsToolManual;
internal bool OriginalPowerActivityRingGeometryRestored=>true;
internal bool OriginalPowerActivityRingFullRestored=>false;
// No guessed unity exposure in production. A source-space probe may pass
// an explicitly labelled synthetic scalar; unknown runtime input hides it.
internal void SetOriginalPowerActivityRing(GalaxyOriginalPowerActivityRing? ring,float? emissiveRescaling,bool originalDefaultBoundKnown=false)
{
powerActivityRing=ring is{} value&&GalaxyOriginalPowerActivityRingGeometry.IsValid(value)?value:null;
// The flag means the original six-texel zero resource is actually
// created/bound and ready in this view. Static bytes alone are not a
// runtime readiness signal. Explicit invalid inputs remain unknown.
powerActivityRingDefaultKnown=originalDefaultBoundKnown&&emissiveRescaling is null;
powerActivityRingEmissive=powerActivityRingDefaultKnown?0:emissiveRescaling is{} scalar&&float.IsFinite(scalar)&&scalar>=0?scalar:null;
powerActivityRingInvalidSource=emissiveRescaling is{} supplied&&(!float.IsFinite(supplied)||supplied<0);
SubmittedPowerActivityRings=0;
}
private void InitializeOriginalPowerActivityRing(string shader)
{
if(Marshal.SizeOf<GalaxyOriginalPowerActivityRing>()!=64)throw new InvalidDataException("原活动范围实例格式无效。");
var path=Path.Combine(Path.GetDirectoryName(shader)!,"GalaxyPowerActivityRing.hlsl");
var vs=Compiler.CompileFromFile(path,"VSOriginalPowerActivityRing","vs_5_0");powerActivityRingVs=device.CreateVertexShader(vs.Span);
powerActivityRingPs=device.CreatePixelShader(Compiler.CompileFromFile(path,"PSOriginalPowerActivityRing","ps_5_0").Span);
powerActivityRingLayout=device.CreateInputLayout([
new InputElementDescription("POSITION",0,Format.R32G32B32A32_Float,0,0,InputClassification.PerInstanceData,1),
new InputElementDescription("UAXISINNER",0,Format.R32G32B32A32_Float,16,0,InputClassification.PerInstanceData,1),
new InputElementDescription("VAXISOUTER",0,Format.R32G32B32A32_Float,32,0,InputClassification.PerInstanceData,1),
new InputElementDescription("USERDATA",0,Format.R32G32B32A32_Float,48,0,InputClassification.PerInstanceData,1)],vs.Span);
powerActivityRingInstance=device.CreateBuffer(64,BindFlags.VertexBuffer,ResourceUsage.Dynamic,CpuAccessFlags.Write);
powerActivityRingConstants=device.CreateBuffer(96,BindFlags.ConstantBuffer);
// Actual FocusRing kind5 effect bytecode:One/InverseSourceAlpha/Add.
// Original range record's source alpha0 makes the RGB additive.
powerActivityRingBlend=device.CreateBlendState(new BlendDescription(Blend.One,Blend.InverseSourceAlpha));
}
private void DrawOriginalPowerActivityRing(GalaxyCamera camera,float hdrWrite)
{
SubmittedPowerActivityRings=0;
if(powerActivityRing is not{} ring||powerActivityRingInvalidSource)return;
var useTexture=powerActivityRingEmissive is null&&OriginalExposureReady;
if(powerActivityRingEmissive is null&&!useTexture)return;
var emissive=powerActivityRingEmissive??OriginalManualExposureResult?.Type2EmissiveRescaling??0;
if(emissive==0&&ring.Colour.W==0)return;
if(!float.IsFinite(hdrWrite)||hdrWrite<=0)return;
var eye=camera.Eye;var right=camera.Right;var up=camera.Up;var forward=camera.Forward;
var frame=new PowerActivityRingCamera(new((float)eye.X,(float)eye.Y,(float)eye.Z,(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(GalaxyOriginalPowerActivityRingGeometry.QuadCount,GalaxyOriginalPowerActivityRingGeometry.RadialFeather,GalaxyOriginalPowerActivityRingGeometry.SegmentFeather,GalaxyOriginalPowerActivityRingGeometry.SolidRatio),
new(GalaxyOriginalPowerActivityRingGeometry.SegmentCount,emissive,hdrWrite,useTexture?1:0));
Upload<GalaxyOriginalPowerActivityRing>(powerActivityRingInstance,new[]{ring});context.UpdateSubresource(in frame,powerActivityRingConstants);
context.VSSetConstantBuffer(11,powerActivityRingConstants);context.PSSetConstantBuffer(11,powerActivityRingConstants);
context.IASetInputLayout(powerActivityRingLayout);context.IASetPrimitiveTopology(PrimitiveTopology.TriangleStrip);
context.IASetVertexBuffer(0,powerActivityRingInstance,64);context.VSSetShader(powerActivityRingVs);context.PSSetShader(powerActivityRingPs);
context.PSSetShaderResource(20,useTexture?originalExposureView!:null!);
context.OMSetBlendState(powerActivityRingBlend);context.DrawInstanced(GalaxyOriginalPowerActivityRingGeometry.VertexCount,1,0,0);
context.PSSetShaderResource(20,null!);
DrawCalls++;SubmittedPowerActivityRings=1;
}
private void DisposeOriginalPowerActivityRing()
{
powerActivityRingVs.Dispose();powerActivityRingPs.Dispose();powerActivityRingLayout.Dispose();
powerActivityRingInstance.Dispose();powerActivityRingConstants.Dispose();powerActivityRingBlend.Dispose();
}
[StructLayout(LayoutKind.Sequential)]
private readonly record struct PowerActivityRingCamera(Vector4 EyeFocal,Vector4 RightWidth,Vector4 UpHeight,Vector4 ForwardNear,Vector4 Material,Vector4 Output);
}
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 powerActivityRingVs=null!;
private ID3D11PixelShader powerActivityRingPs=null!;
private ID3D11InputLayout powerActivityRingLayout=null!;
private ID3D11Buffer powerActivityRingInstance=null!,powerActivityRingConstants=null!;
private ID3D11BlendState powerActivityRingBlend=null!;
private GalaxyOriginalPowerActivityRing? powerActivityRing;
private float? powerActivityRingEmissive;
private bool powerActivityRingDefaultKnown;
private bool powerActivityRingInvalidSource;
internal int PreparedPowerActivityRings=>powerActivityRing is null?0:1;
internal int SubmittedPowerActivityRings {get;private set;}
internal bool PowerActivityRingSourceUnknown=>powerActivityRing is not null&&(powerActivityRingInvalidSource||powerActivityRingEmissive is null&&!OriginalExposureReady);
internal bool PowerActivityRingSourceDefaultKnown=>powerActivityRing is not null&&(powerActivityRingDefaultKnown||
!powerActivityRingInvalidSource&&powerActivityRingEmissive is null&&OriginalExposureState==GalaxyOriginalExposureState.DefaultCreated);
internal bool PowerActivityRingUsesToolManualExposure=>powerActivityRing is not null&&!powerActivityRingInvalidSource&&powerActivityRingEmissive is null&&OriginalExposureIsToolManual;
internal bool OriginalPowerActivityRingGeometryRestored=>true;
internal bool OriginalPowerActivityRingFullRestored=>false;
// No guessed unity exposure in production. A source-space probe may pass
// an explicitly labelled synthetic scalar; unknown runtime input hides it.
internal void SetOriginalPowerActivityRing(GalaxyOriginalPowerActivityRing? ring,float? emissiveRescaling,bool originalDefaultBoundKnown=false)
{
powerActivityRing=ring is{} value&&GalaxyOriginalPowerActivityRingGeometry.IsValid(value)?value:null;
// The flag means the original six-texel zero resource is actually
// created/bound and ready in this view. Static bytes alone are not a
// runtime readiness signal. Explicit invalid inputs remain unknown.
powerActivityRingDefaultKnown=originalDefaultBoundKnown&&emissiveRescaling is null;
powerActivityRingEmissive=powerActivityRingDefaultKnown?0:emissiveRescaling is{} scalar&&float.IsFinite(scalar)&&scalar>=0?scalar:null;
powerActivityRingInvalidSource=emissiveRescaling is{} supplied&&(!float.IsFinite(supplied)||supplied<0);
SubmittedPowerActivityRings=0;
}
private void InitializeOriginalPowerActivityRing(string shader)
{
if(Marshal.SizeOf<GalaxyOriginalPowerActivityRing>()!=64)throw new InvalidDataException("原活动范围实例格式无效。");
var path=Path.Combine(Path.GetDirectoryName(shader)!,"GalaxyPowerActivityRing.hlsl");
var vs=Compiler.CompileFromFile(path,"VSOriginalPowerActivityRing","vs_5_0");powerActivityRingVs=device.CreateVertexShader(vs.Span);
powerActivityRingPs=device.CreatePixelShader(Compiler.CompileFromFile(path,"PSOriginalPowerActivityRing","ps_5_0").Span);
powerActivityRingLayout=device.CreateInputLayout([
new InputElementDescription("POSITION",0,Format.R32G32B32A32_Float,0,0,InputClassification.PerInstanceData,1),
new InputElementDescription("UAXISINNER",0,Format.R32G32B32A32_Float,16,0,InputClassification.PerInstanceData,1),
new InputElementDescription("VAXISOUTER",0,Format.R32G32B32A32_Float,32,0,InputClassification.PerInstanceData,1),
new InputElementDescription("USERDATA",0,Format.R32G32B32A32_Float,48,0,InputClassification.PerInstanceData,1)],vs.Span);
powerActivityRingInstance=device.CreateBuffer(64,BindFlags.VertexBuffer,ResourceUsage.Dynamic,CpuAccessFlags.Write);
powerActivityRingConstants=device.CreateBuffer(96,BindFlags.ConstantBuffer);
// Actual FocusRing kind5 effect bytecode:One/InverseSourceAlpha/Add.
// Original range record's source alpha0 makes the RGB additive.
powerActivityRingBlend=device.CreateBlendState(new BlendDescription(Blend.One,Blend.InverseSourceAlpha));
}
private void DrawOriginalPowerActivityRing(GalaxyCamera camera,float hdrWrite)
{
SubmittedPowerActivityRings=0;
if(powerActivityRing is not{} ring||powerActivityRingInvalidSource)return;
var useTexture=powerActivityRingEmissive is null&&OriginalExposureReady;
if(powerActivityRingEmissive is null&&!useTexture)return;
var emissive=powerActivityRingEmissive??OriginalManualExposureResult?.Type2EmissiveRescaling??0;
if(emissive==0&&ring.Colour.W==0)return;
if(!float.IsFinite(hdrWrite)||hdrWrite<=0)return;
var eye=camera.Eye;var right=camera.Right;var up=camera.Up;var forward=camera.Forward;
var frame=new PowerActivityRingCamera(new((float)eye.X,(float)eye.Y,(float)eye.Z,(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(GalaxyOriginalPowerActivityRingGeometry.QuadCount,GalaxyOriginalPowerActivityRingGeometry.RadialFeather,GalaxyOriginalPowerActivityRingGeometry.SegmentFeather,GalaxyOriginalPowerActivityRingGeometry.SolidRatio),
new(GalaxyOriginalPowerActivityRingGeometry.SegmentCount,emissive,hdrWrite,useTexture?1:0));
Upload<GalaxyOriginalPowerActivityRing>(powerActivityRingInstance,new[]{ring});context.UpdateSubresource(in frame,powerActivityRingConstants);
context.VSSetConstantBuffer(11,powerActivityRingConstants);context.PSSetConstantBuffer(11,powerActivityRingConstants);
context.IASetInputLayout(powerActivityRingLayout);context.IASetPrimitiveTopology(PrimitiveTopology.TriangleStrip);
context.IASetVertexBuffer(0,powerActivityRingInstance,64);context.VSSetShader(powerActivityRingVs);context.PSSetShader(powerActivityRingPs);
context.PSSetShaderResource(20,useTexture?originalExposureView!:null!);
context.OMSetBlendState(powerActivityRingBlend);context.DrawInstanced(GalaxyOriginalPowerActivityRingGeometry.VertexCount,1,0,0);
context.PSSetShaderResource(20,null!);
DrawCalls++;SubmittedPowerActivityRings=1;
}
private void DisposeOriginalPowerActivityRing()
{
powerActivityRingVs.Dispose();powerActivityRingPs.Dispose();powerActivityRingLayout.Dispose();
powerActivityRingInstance.Dispose();powerActivityRingConstants.Dispose();powerActivityRingBlend.Dispose();
}
[StructLayout(LayoutKind.Sequential)]
private readonly record struct PowerActivityRingCamera(Vector4 EyeFocal,Vector4 RightWidth,Vector4 UpHeight,Vector4 ForwardNear,Vector4 Material,Vector4 Output);
}