Reflection and deserialization for vertex data
This commit is contained in:
@@ -47,20 +47,42 @@ namespace hexworld.Util
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool TryGetUniform(string name, out int id)
|
||||
{
|
||||
return uniforms.TryGetValue(name, out id);
|
||||
}
|
||||
|
||||
public int GetUniform(string name)
|
||||
{
|
||||
if (!uniforms.TryGetValue(name, out int id))
|
||||
if (!TryGetUniform(name, out int id))
|
||||
throw new ShaderException($"Shader Program {Id} does not contain uniform '{name}'");
|
||||
return id;
|
||||
}
|
||||
|
||||
public bool TryGetAttribute(string name, out int id)
|
||||
{
|
||||
return attributes.TryGetValue(name, out id);
|
||||
}
|
||||
|
||||
public int GetAttribute(string name)
|
||||
{
|
||||
if (!attributes.TryGetValue(name, out int id))
|
||||
throw new ShaderException($"Shader Program {Id} does not contain attribute '{name}'");
|
||||
if (!TryGetAttribute(name, out int id))
|
||||
throw new ShaderException($"Shader Program {Id} does not contain id '{name}'");
|
||||
return id;
|
||||
}
|
||||
|
||||
public void EnableAllAttribArrays()
|
||||
{
|
||||
foreach (var loc in attributes.Values)
|
||||
GL.EnableVertexAttribArray(loc);
|
||||
}
|
||||
|
||||
public void DisableAllAttribArrays()
|
||||
{
|
||||
foreach (var loc in attributes.Values)
|
||||
GL.DisableVertexAttribArray(loc);
|
||||
}
|
||||
|
||||
public void Use() => GL.UseProgram(Id);
|
||||
|
||||
public static void UseDefault() => GL.UseProgram(0);
|
||||
|
||||
@@ -8,7 +8,15 @@ using OpenTK.Graphics.OpenGL4;
|
||||
|
||||
namespace hexworld.Util
|
||||
{
|
||||
public class VBO : GLObject
|
||||
public static class VBO
|
||||
{
|
||||
public static void Unbind()
|
||||
{
|
||||
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public class VBO<T> : GLObject where T : struct
|
||||
{
|
||||
public VBO()
|
||||
: base((uint) GL.GenBuffer())
|
||||
@@ -20,17 +28,49 @@ namespace hexworld.Util
|
||||
GL.BindBuffer(BufferTarget.ArrayBuffer, Id);
|
||||
}
|
||||
|
||||
public void Data<T>(T[] data, BufferUsageHint usage = BufferUsageHint.StaticDraw) where T : struct
|
||||
public void Data(T[] data, BufferUsageHint usage = BufferUsageHint.StaticDraw)
|
||||
{
|
||||
Bind();
|
||||
var size = Marshal.SizeOf<T>();
|
||||
GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(size * data.Length), data, usage);
|
||||
Unbind();
|
||||
GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr) (size * data.Length), data, usage);
|
||||
VBO.Unbind();
|
||||
}
|
||||
|
||||
public static void Unbind()
|
||||
// todo: this needs a better solution.
|
||||
private static readonly int Stride;
|
||||
private static readonly VertexPointerAttribute[] Attributes;
|
||||
|
||||
static VBO()
|
||||
{
|
||||
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
|
||||
var attribList = new List<VertexPointerAttribute>();
|
||||
Stride = Marshal.SizeOf<T>();
|
||||
|
||||
foreach (var fieldInfo in typeof(T).GetFields())
|
||||
{
|
||||
var attrs = fieldInfo.GetCustomAttributes(typeof(VertexPointerAttribute), false);
|
||||
if (attrs.Length == 0) continue;
|
||||
var offset = (int) Marshal.OffsetOf<T>(fieldInfo.Name);
|
||||
foreach (var attr in attrs)
|
||||
{
|
||||
var vpa = (VertexPointerAttribute) attr;
|
||||
vpa.Offset = offset;
|
||||
attribList.Add(vpa);
|
||||
}
|
||||
}
|
||||
|
||||
Attributes = attribList.ToArray();
|
||||
}
|
||||
|
||||
public void AttribPointers(Program pgm)
|
||||
{
|
||||
Bind();
|
||||
foreach (var attr in Attributes)
|
||||
{
|
||||
if (!pgm.TryGetAttribute(attr.Name, out int loc)) continue;
|
||||
GL.VertexAttribPointer(loc, attr.Size, attr.Type, attr.Normalized, Stride, attr.Offset);
|
||||
GL.VertexAttribDivisor(loc, attr.Divisor);
|
||||
}
|
||||
VBO.Unbind();
|
||||
}
|
||||
}
|
||||
}
|
||||
22
hexworld/Util/VertexPointerAttribute.cs
Normal file
22
hexworld/Util/VertexPointerAttribute.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using OpenTK.Graphics.OpenGL4;
|
||||
|
||||
namespace hexworld.Util
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = true)]
|
||||
public sealed class VertexPointerAttribute : Attribute
|
||||
{
|
||||
public string Name { get; }
|
||||
public int Size { get; }
|
||||
public VertexAttribPointerType Type { get; set; } = VertexAttribPointerType.Float;
|
||||
public bool Normalized { get; set; } = false;
|
||||
public int Divisor { get; set; } = 0;
|
||||
public int Offset { get; set; } = 0;
|
||||
|
||||
public VertexPointerAttribute(string name, int size)
|
||||
{
|
||||
Name = name;
|
||||
Size = size;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user