70 lines
1.7 KiB
C#
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];
|
|
}
|
|
}
|