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 powerActivityBillboardVs=null!;
private ID3D11PixelShader powerActivityBillboardPs=null!;
private ID3D11InputLayout powerActivityBillboardLayout=null!;
private ID3D11Buffer powerActivityBillboardInstance=null!,powerActivityBillboardConstants=null!;
private ID3D11BlendState powerActivityBillboardBlend=null!;
private GalaxyOriginalPowerActivityBillboard? powerActivityBillboard;
private float? powerActivityBillboardEmissive;
private bool powerActivityBillboardInvalid;
internal int SubmittedPowerActivityBillboards {get;private set;}
internal bool PowerActivityBillboardSourceUnknown=>powerActivityBillboard is not null&&(powerActivityBillboardInvalid||powerActivityBillboardEmissive is null&&!OriginalExposureReady);
internal bool OriginalPowerActivityBillboardGeometryRestored=>true;
internal bool OriginalPowerActivityBillboardFullRestored=>false;
internal void SetOriginalPowerActivityBillboard(GalaxyOriginalPowerActivityBillboard? value,float? emissiveRescaling=null)
{
powerActivityBillboard=value is {} record&&GalaxyOriginalPowerActivityBillboardGeometry.IsValid(record)?record:null;
powerActivityBillboardEmissive=emissiveRescaling;
powerActivityBillboardInvalid=emissiveRescaling is {} scalar&&(!float.IsFinite(scalar)||scalar<0);
SubmittedPowerActivityBillboards=0;
}
private void InitializeOriginalPowerActivityBillboard(string shader)
{
if(Marshal.SizeOf<GalaxyOriginalPowerActivityBillboard>()!=64)throw new InvalidDataException("原活动轮廓实例格式无效。");
var path=Path.Combine(Path.GetDirectoryName(shader)!,"GalaxyPowerActivityBillboard.hlsl");
var vs=Compiler.CompileFromFile(path,"VSOriginalPowerActivityBillboard","vs_5_0");powerActivityBillboardVs=device.CreateVertexShader(vs.Span);
powerActivityBillboardPs=device.CreatePixelShader(Compiler.CompileFromFile(path,"PSOriginalPowerActivityBillboard","ps_5_0").Span);
powerActivityBillboardLayout=device.CreateInputLayout([
new InputElementDescription("POSITION",0,Format.R32G32B32A32_Float,0,0,InputClassification.PerInstanceData,1),
new InputElementDescription("UAXISEXTENT",0,Format.R32G32B32A32_Float,16,0,InputClassification.PerInstanceData,1),
new InputElementDescription("VAXISEXTENT",0,Format.R32G32B32A32_Float,32,0,InputClassification.PerInstanceData,1),
new InputElementDescription("USERDATA",0,Format.R32G32B32A32_Float,48,0,InputClassification.PerInstanceData,1)],vs.Span);
powerActivityBillboardInstance=device.CreateBuffer(64,BindFlags.VertexBuffer,ResourceUsage.Dynamic,CpuAccessFlags.Write);
powerActivityBillboardConstants=device.CreateBuffer(112,BindFlags.ConstantBuffer);
powerActivityBillboardBlend=device.CreateBlendState(new BlendDescription(Blend.One,Blend.InverseSourceAlpha));
}
private void DrawOriginalPowerActivityBillboard(GalaxyCamera camera,float hdrWrite)
{
SubmittedPowerActivityBillboards=0;
if(powerActivityBillboard is not{} value||powerActivityBillboardInvalid||!float.IsFinite(hdrWrite)||hdrWrite<=0)return;
var useTexture=powerActivityBillboardEmissive is null&&OriginalExposureReady;
if(powerActivityBillboardEmissive is null&&!useTexture)return;
var emissive=powerActivityBillboardEmissive??OriginalManualExposureResult?.Type2EmissiveRescaling??0;
if(emissive==0&&value.Colour.W==0)return;
var eye=camera.Eye;var right=camera.Right;var up=camera.Up;var forward=camera.Forward;
var frame=new PowerActivityBillboardFrame(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(.8999999761581421f,.75f,.9200000166893005f,.17499999701976776f),
new(1.5f,.004999999888241291f,width,height),new(emissive,hdrWrite,useTexture?1:0,0));
Upload<GalaxyOriginalPowerActivityBillboard>(powerActivityBillboardInstance,new[]{value});context.UpdateSubresource(in frame,powerActivityBillboardConstants);
context.VSSetConstantBuffer(12,powerActivityBillboardConstants);context.PSSetConstantBuffer(12,powerActivityBillboardConstants);
context.IASetInputLayout(powerActivityBillboardLayout);context.IASetPrimitiveTopology(PrimitiveTopology.TriangleStrip);
context.IASetVertexBuffer(0,powerActivityBillboardInstance,64);context.VSSetShader(powerActivityBillboardVs);context.PSSetShader(powerActivityBillboardPs);
context.PSSetShaderResource(20,useTexture?originalExposureView!:null!);context.OMSetBlendState(powerActivityBillboardBlend);
context.DrawInstanced(GalaxyOriginalPowerActivityBillboardGeometry.VertexCount,1,0,0);context.PSSetShaderResource(20,null!);
DrawCalls++;SubmittedPowerActivityBillboards=1;
}
private void DisposeOriginalPowerActivityBillboard()
{
powerActivityBillboardVs.Dispose();powerActivityBillboardPs.Dispose();powerActivityBillboardLayout.Dispose();
powerActivityBillboardInstance.Dispose();powerActivityBillboardConstants.Dispose();powerActivityBillboardBlend.Dispose();
}
[StructLayout(LayoutKind.Sequential)]
private readonly record struct PowerActivityBillboardFrame(Vector4 EyeFocal,Vector4 RightWidth,Vector4 UpHeight,Vector4 ForwardNear,Vector4 Material,Vector4 Highlight,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 powerActivityBillboardVs=null!;
private ID3D11PixelShader powerActivityBillboardPs=null!;
private ID3D11InputLayout powerActivityBillboardLayout=null!;
private ID3D11Buffer powerActivityBillboardInstance=null!,powerActivityBillboardConstants=null!;
private ID3D11BlendState powerActivityBillboardBlend=null!;
private GalaxyOriginalPowerActivityBillboard? powerActivityBillboard;
private float? powerActivityBillboardEmissive;
private bool powerActivityBillboardInvalid;
internal int SubmittedPowerActivityBillboards {get;private set;}
internal bool PowerActivityBillboardSourceUnknown=>powerActivityBillboard is not null&&(powerActivityBillboardInvalid||powerActivityBillboardEmissive is null&&!OriginalExposureReady);
internal bool OriginalPowerActivityBillboardGeometryRestored=>true;
internal bool OriginalPowerActivityBillboardFullRestored=>false;
internal void SetOriginalPowerActivityBillboard(GalaxyOriginalPowerActivityBillboard? value,float? emissiveRescaling=null)
{
powerActivityBillboard=value is {} record&&GalaxyOriginalPowerActivityBillboardGeometry.IsValid(record)?record:null;
powerActivityBillboardEmissive=emissiveRescaling;
powerActivityBillboardInvalid=emissiveRescaling is {} scalar&&(!float.IsFinite(scalar)||scalar<0);
SubmittedPowerActivityBillboards=0;
}
private void InitializeOriginalPowerActivityBillboard(string shader)
{
if(Marshal.SizeOf<GalaxyOriginalPowerActivityBillboard>()!=64)throw new InvalidDataException("原活动轮廓实例格式无效。");
var path=Path.Combine(Path.GetDirectoryName(shader)!,"GalaxyPowerActivityBillboard.hlsl");
var vs=Compiler.CompileFromFile(path,"VSOriginalPowerActivityBillboard","vs_5_0");powerActivityBillboardVs=device.CreateVertexShader(vs.Span);
powerActivityBillboardPs=device.CreatePixelShader(Compiler.CompileFromFile(path,"PSOriginalPowerActivityBillboard","ps_5_0").Span);
powerActivityBillboardLayout=device.CreateInputLayout([
new InputElementDescription("POSITION",0,Format.R32G32B32A32_Float,0,0,InputClassification.PerInstanceData,1),
new InputElementDescription("UAXISEXTENT",0,Format.R32G32B32A32_Float,16,0,InputClassification.PerInstanceData,1),
new InputElementDescription("VAXISEXTENT",0,Format.R32G32B32A32_Float,32,0,InputClassification.PerInstanceData,1),
new InputElementDescription("USERDATA",0,Format.R32G32B32A32_Float,48,0,InputClassification.PerInstanceData,1)],vs.Span);
powerActivityBillboardInstance=device.CreateBuffer(64,BindFlags.VertexBuffer,ResourceUsage.Dynamic,CpuAccessFlags.Write);
powerActivityBillboardConstants=device.CreateBuffer(112,BindFlags.ConstantBuffer);
powerActivityBillboardBlend=device.CreateBlendState(new BlendDescription(Blend.One,Blend.InverseSourceAlpha));
}
private void DrawOriginalPowerActivityBillboard(GalaxyCamera camera,float hdrWrite)
{
SubmittedPowerActivityBillboards=0;
if(powerActivityBillboard is not{} value||powerActivityBillboardInvalid||!float.IsFinite(hdrWrite)||hdrWrite<=0)return;
var useTexture=powerActivityBillboardEmissive is null&&OriginalExposureReady;
if(powerActivityBillboardEmissive is null&&!useTexture)return;
var emissive=powerActivityBillboardEmissive??OriginalManualExposureResult?.Type2EmissiveRescaling??0;
if(emissive==0&&value.Colour.W==0)return;
var eye=camera.Eye;var right=camera.Right;var up=camera.Up;var forward=camera.Forward;
var frame=new PowerActivityBillboardFrame(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(.8999999761581421f,.75f,.9200000166893005f,.17499999701976776f),
new(1.5f,.004999999888241291f,width,height),new(emissive,hdrWrite,useTexture?1:0,0));
Upload<GalaxyOriginalPowerActivityBillboard>(powerActivityBillboardInstance,new[]{value});context.UpdateSubresource(in frame,powerActivityBillboardConstants);
context.VSSetConstantBuffer(12,powerActivityBillboardConstants);context.PSSetConstantBuffer(12,powerActivityBillboardConstants);
context.IASetInputLayout(powerActivityBillboardLayout);context.IASetPrimitiveTopology(PrimitiveTopology.TriangleStrip);
context.IASetVertexBuffer(0,powerActivityBillboardInstance,64);context.VSSetShader(powerActivityBillboardVs);context.PSSetShader(powerActivityBillboardPs);
context.PSSetShaderResource(20,useTexture?originalExposureView!:null!);context.OMSetBlendState(powerActivityBillboardBlend);
context.DrawInstanced(GalaxyOriginalPowerActivityBillboardGeometry.VertexCount,1,0,0);context.PSSetShaderResource(20,null!);
DrawCalls++;SubmittedPowerActivityBillboards=1;
}
private void DisposeOriginalPowerActivityBillboard()
{
powerActivityBillboardVs.Dispose();powerActivityBillboardPs.Dispose();powerActivityBillboardLayout.Dispose();
powerActivityBillboardInstance.Dispose();powerActivityBillboardConstants.Dispose();powerActivityBillboardBlend.Dispose();
}
[StructLayout(LayoutKind.Sequential)]
private readonly record struct PowerActivityBillboardFrame(Vector4 EyeFocal,Vector4 RightWidth,Vector4 UpHeight,Vector4 ForwardNear,Vector4 Material,Vector4 Highlight,Vector4 Output);
}