WorkInProgress/DistanceFieldGPU.cs
using Sandbox.Rendering;
using System.Numerics;

namespace Sandbox;

/// <summary>
/// Distance Field GPU from Hitboxes
/// No acceleration structure, no nothing but capsules, proof of concept
/// </summary>
[Title("Distance Field from Hitboxes")]
[Icon("light_mode")]
[Category("Rendering")]
[Hide]
public sealed partial class DistanceFieldGPU : PostProcess, Component.ExecuteInEditor
{
    struct Shape
    {
		public Vector3 A;
		public Vector3 B;
		public float Radius;
	}

	List<Shape> Shapes = new();
	GpuBuffer<Shape> Buffer;

	CommandList Commands;

	protected override void OnEnabled()
	{
		base.OnEnabled();
		Commands = new CommandList( "Distance Field Constants Upload" );
		Camera.AddCommandList( Commands, Stage.AfterDepthPrepass, 0 );
	}

	protected override void OnDisabled()
	{
		base.OnDisabled();
		Camera.RemoveCommandList( Commands );
	}

	protected override void OnPreRender()
	{
		base.OnPreRender();

		Shapes.Clear();

		foreach ( var anim in Scene.GetAll<SkinnedModelRenderer>() )
		{
			if ( anim is null )
				return;

			if ( anim.Model is null )
				return;

			foreach ( var hb in anim.Model.HitboxSet.All )
			{
				if ( hb.Bone is null )
					continue;

				if ( hb.Shape is Sphere sphere )
				{
				}
				else if ( hb.Shape is Capsule capsule && anim.TryGetBoneTransform( hb.Bone, out var tx ) )
				{
					Shape s = new Shape() { A = tx.PointToWorld( capsule.CenterA ), B = tx.PointToWorld( capsule.CenterB ), Radius = capsule.Radius };
					Shapes.Add( s );
				}
				else if ( hb.Shape is BBox box )
				{
				}
			}
		}

		if ( Buffer == null || Buffer.ElementCount != Shapes.Count() )
		{
			Buffer = new GpuBuffer<Shape>( Shapes.Count );
		}

		Buffer.SetData( Shapes );

		Commands.Reset();
		Commands.GlobalAttributes.Set( "HitboxBuffer", Buffer );
		Commands.GlobalAttributes.Set( "HitboxCount", Shapes.Count );
	}

	protected override void DrawGizmos()
	{
		base.DrawGizmos();

        Gizmo.Draw.Color = Color.White.WithAlpha( 0.5f );
		Gizmo.Transform = global::Transform.Zero;

		foreach( var s in Shapes )
		{
			Gizmo.Draw.SolidCapsule( s.A, s.B, s.Radius, 10, 10 );
		}

	}
}