Dashboard/Dashboard.Drawing.OpenGL/GradientUniformBuffer.cs

90 lines
2.4 KiB
C#
Raw Normal View History

2025-01-14 18:34:47 +01:00
using System.Runtime.InteropServices;
using OpenTK.Mathematics;
namespace Dashboard.Drawing.OpenGL
{
public class GradientUniformBuffer : IInitializer, IGLDisposable, IResourceManager
2025-01-14 18:34:47 +01:00
{
private bool _isDisposed;
2025-01-14 18:34:47 +01:00
private int _top = 0;
private readonly MappableBuffer<GradientUniformStruct> _buffer = new MappableBuffer<GradientUniformStruct>();
private readonly Dictionary<Gradient, Entry> _entries = new Dictionary<Gradient, Entry>();
public bool IsInitialized { get; private set; } = false;
2025-01-14 18:34:47 +01:00
public void Initialize()
{
if (IsInitialized)
return;
IsInitialized = true;
2025-01-14 18:34:47 +01:00
_buffer.Initialize();
}
public Entry InternGradient(Gradient gradient)
{
if (_entries.TryGetValue(gradient, out Entry entry))
return entry;
int count = gradient.Count;
int offset = _top;
_top += count;
_buffer.EnsureCapacity(_top);
_buffer.Map();
Span<GradientUniformStruct> span = _buffer.AsSpan()[offset.._top];
for (int i = 0; i < count; i++)
{
GradientStop stop = gradient[i];
span[i] = new GradientUniformStruct()
{
Position = stop.Position,
Color = new Vector4(
stop.Color.R / 255f,
stop.Color.G / 255f,
stop.Color.B / 255f,
stop.Color.A / 255f),
};
}
entry = new Entry(offset, count);
_entries.Add(gradient, entry);
return entry;
}
public void Clear()
{
_entries.Clear();
_top = 0;
}
public record struct Entry(int Offset, int Count);
public void Dispose() => Dispose(true);
public void Dispose(bool safeExit)
{
if (_isDisposed)
return;
_isDisposed = true;
_buffer.Dispose(safeExit);
}
string IResourceManager.Name { get; } = nameof(GradientUniformBuffer);
2025-01-14 18:34:47 +01:00
}
[StructLayout(LayoutKind.Explicit, Size = 8 * sizeof(float))]
public struct GradientUniformStruct
{
[FieldOffset(0 * sizeof(float))]
public float Position;
[FieldOffset(4 * sizeof(float))]
public Vector4 Color;
}
}