qstbak/Auspex/Auspex/AxMultiStopLinearGradient.cs
2026-08-17 20:25:32 +10:00

70 lines
1.7 KiB
C#

using System;
using System.Numerics;
using Auspex.Rendering.Direct3D;
namespace Auspex;
public readonly struct AxMultiStopLinearGradient : IPctGradient
{
private readonly Vector3 _start;
private readonly Vector3 _axis;
private readonly float _invLenSq;
private readonly float[] _positions;
private readonly Vector4[] _colors;
public AxMultiStopLinearGradient(Vector3 start, Vector3 end, params AxGradientStop[] stops)
{
_start = start;
_axis = end - start;
_invLenSq = 1f / Vector3.Dot(_axis, _axis);
(_positions, _colors) = ParseStops(stops);
}
public uint ColorAt(Vector3 point)
{
return SampleStops(Math.Clamp(Vector3.Dot(point - _start, _axis) * _invLenSq, 0f, 1f), _positions, _colors).ToUint();
}
internal static (float[] Positions, Vector4[] Colors) ParseStops(AxGradientStop[] stops)
{
AxGradientStop[] array = (AxGradientStop[])stops.Clone();
Array.Sort(array, (AxGradientStop a, AxGradientStop b) => a.Position.CompareTo(b.Position));
float[] array2 = new float[array.Length];
Vector4[] array3 = new Vector4[array.Length];
for (int num = 0; num < array.Length; num++)
{
array2[num] = array[num].Position;
array3[num] = array[num].Color.ToVector4();
}
return (Positions: array2, Colors: array3);
}
internal static Vector4 SampleStops(float t, float[] positions, Vector4[] colors)
{
if (colors.Length == 0)
{
return Vector4.Zero;
}
if (t <= positions[0])
{
return colors[0];
}
if (t >= positions[^1])
{
return colors[^1];
}
for (int i = 0; i < positions.Length - 1; i++)
{
if (t <= positions[i + 1])
{
float amount = (t - positions[i]) / (positions[i + 1] - positions[i]);
return Vector4.Lerp(colors[i], colors[i + 1], amount);
}
}
return colors[^1];
}
}