Reflection and deserialization for vertex data

This commit is contained in:
2017-02-25 06:03:56 -05:00
parent d185544e47
commit 88e773ef25
9 changed files with 239 additions and 151 deletions

View File

@@ -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);

View File

@@ -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();
}
}
}

View 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;
}
}
}