89 lines
2.7 KiB
C#
89 lines
2.7 KiB
C#
using System.Reflection;
|
|
using System.Runtime.InteropServices;
|
|
using Engine.Renderer.Buffer.Vertex;
|
|
using OpenTK.Graphics.OpenGL;
|
|
using Serilog;
|
|
|
|
namespace Engine.Renderer.Buffer;
|
|
|
|
public class VertexArray : OpenGlObject
|
|
{
|
|
// private IndexBuffer? _boundIndexBuffer;
|
|
// private readonly Dictionary<int, VertexBuffer<IVertex>> _boundVertexBuffers = new();
|
|
|
|
public VertexArray()
|
|
{
|
|
GL.CreateVertexArrays(1, out int handle);
|
|
Handle = handle;
|
|
}
|
|
|
|
public void BindIndexBuffer(IndexBuffer buffer)
|
|
{
|
|
GL.VertexArrayElementBuffer(Handle, buffer.Handle);
|
|
|
|
Log.Debug("Vertex array {Handle} bound to index buffer {Buffer}", Handle, buffer.Handle);
|
|
}
|
|
|
|
public void BindVertexBuffer<T>(VertexBuffer<T> buffer, int bindingIndex = 0, int divisor = 0)
|
|
where T : struct, IVertex
|
|
{
|
|
if (bindingIndex < 0)
|
|
throw new ArgumentException("Binding index must be greater than 0");
|
|
|
|
if (divisor < 0)
|
|
throw new ArgumentException("Divisor must be greater than 0");
|
|
|
|
var stride = Marshal.SizeOf<T>();
|
|
var fields = IVertex.GetFields<T>();
|
|
|
|
GL.VertexArrayVertexBuffer(Handle, bindingIndex, buffer.Handle, 0, stride);
|
|
|
|
var location = 0;
|
|
foreach (var field in fields)
|
|
{
|
|
var attribute = field.GetCustomAttribute<VertexAttribute>()!;
|
|
|
|
var offset = Marshal.OffsetOf<T>(field.Name).ToInt32();
|
|
SetupAttribute(attribute, location, offset, bindingIndex);
|
|
|
|
location += attribute.RepeatCount;
|
|
}
|
|
|
|
GL.VertexArrayBindingDivisor(Handle, bindingIndex, divisor);
|
|
|
|
Log.Debug(
|
|
"Vertex array {Handle} bound to vertex buffer {Buffer} at {BindingIndex} binding with {Divisor} divisor",
|
|
Handle, buffer.Handle, bindingIndex, divisor);
|
|
}
|
|
|
|
private void SetupAttribute(VertexAttribute attribute, int baseLocation, int baseOffset, int bindingIndex)
|
|
{
|
|
var size = attribute.ComponentCount * IVertex.AttributeSize(attribute.Type);
|
|
|
|
for (var i = 0; i < attribute.RepeatCount; i++)
|
|
{
|
|
var location = baseLocation + i;
|
|
var offset = baseOffset + i * size;
|
|
|
|
GL.EnableVertexArrayAttrib(Handle, location);
|
|
GL.VertexArrayAttribFormat(Handle, location, attribute.ComponentCount, attribute.Type, attribute.Normalized,
|
|
offset);
|
|
GL.VertexArrayAttribBinding(Handle, location, bindingIndex);
|
|
}
|
|
}
|
|
|
|
internal override void Bind()
|
|
{
|
|
GL.BindVertexArray(Handle);
|
|
}
|
|
|
|
internal override void Unbind()
|
|
{
|
|
GL.BindVertexArray(0);
|
|
}
|
|
|
|
protected override void Destroy()
|
|
{
|
|
GL.DeleteVertexArray(Handle);
|
|
}
|
|
} |