using System.Runtime.InteropServices; using Engine.Renderer.Buffer.Vertex; using OpenTK.Graphics.OpenGL; using Serilog; namespace Engine.Renderer.Buffer; public class VertexBuffer : OpenGlObject where T : struct, IVertex { internal int Count { get; } private readonly int _stride = Marshal.SizeOf(); public VertexBuffer(int count, BufferStorageFlags flags) { if (!IVertex.IsValid(typeof(T))) throw new ArgumentException($"Type {typeof(T).Name} is not a valid vertex type"); if (count <= 0) throw new ArgumentException("Count must be greater than 0"); Count = count; GL.CreateBuffers(1, out int handle); Handle = handle; GL.NamedBufferStorage(Handle, Count * _stride, IntPtr.Zero, flags); Log.Debug("Vertex buffer {Handle} created with {Count} elements of type {Type}", Handle, Count, typeof(T).Name); } public void UploadData(T[] data) { UploadData(0, data); } public void UploadData(int offset, T[] data) { if (offset < 0) throw new ArgumentException("Offset must be greater than 0"); if (data.Length + offset > Count) throw new ArgumentException("Data array is too large"); GL.NamedBufferSubData(Handle, offset * _stride, data.Length * _stride, data); } internal override void Bind() { GL.BindBuffer(BufferTarget.ArrayBuffer, Handle); } internal override void Unbind() { GL.BindBuffer(BufferTarget.ArrayBuffer, 0); } protected override void Destroy() { GL.DeleteBuffer(Handle); } }