[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = false)] public class VertexElementAttribute : Attribute { static Dictionary ms_elementCache = new Dictionary(); public static VertexElement[] GetVertexElements(Type vertexType) { if (!vertexType.IsValueType || vertexType.IsPrimitive || vertexType.IsEnum) throw new ArgumentException("The type specified must be a structure.", "vertexType"); VertexElement[] vertexElements; if (!ms_elementCache.TryGetValue(vertexType, out vertexElements)) { FieldInfo[] fields = vertexType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (fields != null) { List elementList = new List(); for (int f = 0; f < fields.Length; f++) { object[] veAttribs = fields[f].GetCustomAttributes(typeof(VertexElementAttribute), false); if (veAttribs == null || veAttribs.Length < 1) continue; VertexElementAttribute vertexAttrib = veAttribs[0] as VertexElementAttribute; if (vertexAttrib == null) continue; VertexElement newElement = new VertexElement(); newElement.Name = vertexAttrib.Name; newElement.Normalized = vertexAttrib.Normalized; newElement.Type = vertexAttrib.DataType; newElement.Size = vertexAttrib.Size; newElement.Offset = Marshal.OffsetOf(vertexType, fields[f].Name); elementList.Add(newElement); } if (elementList.Count > 0) { vertexElements = elementList.ToArray(); ms_elementCache.Add(vertexType, vertexElements); } } } VertexElement[] result = null; if (vertexElements != null) { result = new VertexElement[vertexElements.Length]; Array.Copy(vertexElements, result, vertexElements.Length); } return result; } public static bool Apply(Type vertexType, ShaderProgram program, int stride = 0) { VertexElement[] vertexElements = GetVertexElements(vertexType); if (vertexElements != null) { for (int i = 0; i < vertexElements.Length; i++) { vertexElements[i].Apply(program, stride); } return true; } return false; } public string Name { get; set; } public VertexAttribPointerType DataType { get; set; } public int Size { get; set; } public bool Normalized { get; set; } public VertexElementAttribute(string name, VertexAttribPointerType dataType, int size, bool normalized = false) : base() { Name = name; DataType = dataType; Size = size; Normalized = normalized; } }