From ee732240f7c3ffc87a408ccb4d3783a585a11866 Mon Sep 17 00:00:00 2001 From: Michel Fedde Date: Fri, 26 Mar 2021 10:41:29 +0100 Subject: [PATCH] Reworked the VBO --- SMCode/SM.Base/Log.cs | 2 +- SMCode/SM.Base/Objects/InstancedMesh.cs | 10 +- SMCode/SM.Base/Objects/Mesh.cs | 3 +- SMCode/SM.Base/Objects/Static/AxisHelper.cs | 17 +- SMCode/SM.Base/Objects/Static/Plate.cs | 20 +- SMCode/SM.OGL/Mesh/BoundingBox.cs | 2 +- SMCode/SM.OGL/Mesh/GenericMesh.cs | 15 +- SMCode/SM.OGL/Mesh/VBO.cs | 333 +++++++------------- SMCode/SM.OGL/Shaders/GenericShader.cs | 4 +- SMCode/SM2D/Object/Polygon.cs | 11 +- SM_TEST/Program.cs | 10 +- 11 files changed, 174 insertions(+), 253 deletions(-) diff --git a/SMCode/SM.Base/Log.cs b/SMCode/SM.Base/Log.cs index a043927..ac21108 100644 --- a/SMCode/SM.Base/Log.cs +++ b/SMCode/SM.Base/Log.cs @@ -163,7 +163,7 @@ namespace SM.Base private static void GLDebugAction(DebugSource source, DebugType type, DebugSeverity severity, string msg) { if (type.HasFlag(DebugType.DebugTypeError)) throw new Exception("[GLError] " + msg); - Write(type != DebugType.DontCare ? type.ToString().Substring(9) : "DontCare", ConsoleColor.Gray, msg); + Write("GL"+ (type != DebugType.DontCare ? type.ToString().Substring(9) : "DontCare"), ConsoleColor.Gray, msg); } [DebuggerStepThrough] diff --git a/SMCode/SM.Base/Objects/InstancedMesh.cs b/SMCode/SM.Base/Objects/InstancedMesh.cs index 102b359..ad4eaa2 100644 --- a/SMCode/SM.Base/Objects/InstancedMesh.cs +++ b/SMCode/SM.Base/Objects/InstancedMesh.cs @@ -1,5 +1,7 @@ #region usings +using OpenTK; +using OpenTK.Graphics; using OpenTK.Graphics.OpenGL4; using SM.OGL.Mesh; @@ -21,19 +23,19 @@ namespace SM.Base.Objects /// public InstancedMesh(PrimitiveType type, string[] enabledAttibute) : base(type) { - Attributes["vertex"] = Vertex = new VBO(); + Attributes["vertex"] = Vertex = new VBO(); foreach (string attribute in enabledAttibute) switch (attribute) { case "uv": - Attributes["uv"] = UVs = new VBO(pointerSize: 2); + Attributes["uv"] = UVs = new VBO(); break; case "normals": - Attributes["normal"] = Normals = new VBO(); + Attributes["normal"] = Normals = new VBO(); break; case "color": - Attributes["color"] = Color = new VBO(pointerSize: 4); + Attributes["color"] = Color = new VBO(); break; } } diff --git a/SMCode/SM.Base/Objects/Mesh.cs b/SMCode/SM.Base/Objects/Mesh.cs index 90468d2..18137c4 100644 --- a/SMCode/SM.Base/Objects/Mesh.cs +++ b/SMCode/SM.Base/Objects/Mesh.cs @@ -1,5 +1,6 @@ #region usings +using OpenTK.Graphics; using OpenTK.Graphics.OpenGL4; using SM.OGL.Mesh; @@ -22,7 +23,7 @@ namespace SM.Base.Objects /// /// Contains vertex colors /// - public virtual VBO Color { get; protected set; } + public virtual VBO Color { get; protected set; } /// public float LineWidth { get; set; } = 1; diff --git a/SMCode/SM.Base/Objects/Static/AxisHelper.cs b/SMCode/SM.Base/Objects/Static/AxisHelper.cs index 6c85802..2fbc234 100644 --- a/SMCode/SM.Base/Objects/Static/AxisHelper.cs +++ b/SMCode/SM.Base/Objects/Static/AxisHelper.cs @@ -1,5 +1,6 @@ #region usings +using OpenTK; using OpenTK.Graphics; using OpenTK.Graphics.OpenGL4; using SM.OGL.Mesh; @@ -27,18 +28,18 @@ namespace SM.Base.Objects.Static } /// - public override VBO Vertex { get; protected set; } = new VBO + public override VBO Vertex { get; protected set; } = new VBO { - {0, 0, 0}, - {.5f, 0, 0}, - {0, 0, 0}, - {0, .5f, 0}, - {0, 0, -.5f}, - {0, 0, .5f} + new Vector3(0, 0, 0), + new Vector3(.5f, 0, 0), + new Vector3(0, 0, 0), + new Vector3(0, .5f, 0), + new Vector3(0, 0, -.5f), + new Vector3(0, 0, .5f) }; /// - public override VBO Color { get; protected set; } = new VBO(pointerSize: 4) + public override VBO Color { get; protected set; } = new VBO { Color4.White, Color4.Red, diff --git a/SMCode/SM.Base/Objects/Static/Plate.cs b/SMCode/SM.Base/Objects/Static/Plate.cs index 222866d..ae43096 100644 --- a/SMCode/SM.Base/Objects/Static/Plate.cs +++ b/SMCode/SM.Base/Objects/Static/Plate.cs @@ -25,21 +25,21 @@ namespace SM.Base.Objects.Static } /// - public override VBO Vertex { get; protected set; } = new VBO + public override VBO Vertex { get; protected set; } = new VBO { - {-.5f, -.5f, 0}, - {-.5f, .5f, 0}, - {.5f, .5f, 0}, - {.5f, -.5f, 0} + new Vector3(-.5f, -.5f, 0), + new Vector3(-.5f, .5f, 0), + new Vector3(.5f, .5f, 0), + new Vector3(.5f, -.5f, 0), }; /// - public override VBO UVs { get; protected set; } = new VBO(pointerSize: 2) + public override VBO UVs { get; protected set; } = new VBO { - {0, 1}, - {0, 0}, - {1, 0}, - {1, 1} + new Vector2(0, 1), + new Vector2(0, 0), + new Vector2(1, 0), + new Vector2(1, 1), }; /// diff --git a/SMCode/SM.OGL/Mesh/BoundingBox.cs b/SMCode/SM.OGL/Mesh/BoundingBox.cs index 8db9137..1031e3b 100644 --- a/SMCode/SM.OGL/Mesh/BoundingBox.cs +++ b/SMCode/SM.OGL/Mesh/BoundingBox.cs @@ -124,7 +124,7 @@ namespace SM.OGL.Mesh public void Update(GenericMesh mesh) { int pos = 0; - foreach (float f in mesh.Vertex) + foreach (float f in mesh.Vertex.GetFloats()) { Min[pos] = Math.Min(Min[pos], f); Max[pos] = Math.Max(Max[pos], f); diff --git a/SMCode/SM.OGL/Mesh/GenericMesh.cs b/SMCode/SM.OGL/Mesh/GenericMesh.cs index 96e4b76..7a73bc3 100644 --- a/SMCode/SM.OGL/Mesh/GenericMesh.cs +++ b/SMCode/SM.OGL/Mesh/GenericMesh.cs @@ -1,6 +1,7 @@ #region usings using System; +using OpenTK; using OpenTK.Graphics.OpenGL4; #endregion @@ -29,17 +30,17 @@ namespace SM.OGL.Mesh /// /// Contains the vertices for the mesh. /// - public virtual VBO Vertex { get; protected set; } + public virtual VBO Vertex { get; protected set; } /// /// Contains the texture coords for the mesh. /// - public virtual VBO UVs { get; protected set; } + public virtual VBO UVs { get; protected set; } /// /// Contains the normals for the mesh. /// - public virtual VBO Normals { get; protected set; } + public virtual VBO Normals { get; protected set; } /// /// Represents the bounding box. @@ -97,8 +98,12 @@ namespace SM.OGL.Mesh if (!_boundingBoxUpdated) UpdateBoundingBox(); - foreach (var kvp in Attributes) - kvp.ConnectedVBO?.BindBuffer(kvp.Index); + foreach (var kvp in Attributes) + { + if (kvp.ConnectedVBO == null) continue; + kvp.ConnectedVBO.AttributeID = kvp.Index; + kvp.ConnectedVBO.Compile(); + } GL.BindVertexArray(0); } diff --git a/SMCode/SM.OGL/Mesh/VBO.cs b/SMCode/SM.OGL/Mesh/VBO.cs index 1fee8cc..6dd9e66 100644 --- a/SMCode/SM.OGL/Mesh/VBO.cs +++ b/SMCode/SM.OGL/Mesh/VBO.cs @@ -1,246 +1,155 @@ -#region usings - -using System; -using System.Collections.Generic; -using OpenTK; +using OpenTK; using OpenTK.Graphics; using OpenTK.Graphics.OpenGL4; - -#endregion +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; namespace SM.OGL.Mesh { - /// - /// Represents a Vertex Buffer Object used for meshes. - /// - public class VBO : List + public abstract class VBO : GLObject { - /// - /// The ID for the buffer. - /// - public int BufferID { get; private set; } + private float[] _floatArray; - /// - /// Specifies the expected usage pattern of the data store. - /// - public BufferUsageHint BufferUsageHint; + protected override bool AutoCompile { get => false; set { return; } } + public override ObjectLabelIdentifier TypeIdentifier => ObjectLabelIdentifier.Buffer; - /// - /// Normalise floats? - /// - public bool Normalised; + public bool Active { get; set; } = true; + public bool CanBeUpdated { get; set; } = true; - /// - /// Specifies a offset of the first component of the first generic vertex attribute in the array in the data store of - /// the buffer currently bound to the GL_ARRAY_BUFFER target. - /// - public int PointerOffset; + public bool Normalized { get; protected set; } + public int PointerOffset { get; protected set; } + public int PointerStride { get; protected set; } + public int PointerSize { get; protected set; } + public BufferUsageHint UsageHint { get; protected set; } + public VertexAttribPointerType PointerType { get; protected set; } - /// - /// Specifies the number of components per generic vertex attribute. Must be 1, 2, 3, 4. - /// - public int PointerSize; + public int AttributeID { get; internal set; } - /// - /// Specifies the byte offset between consecutive generic vertex attributes. - /// - public int PointerStride; + public abstract int Count { get; } - /// - /// The VBO gets ignored when true. - /// Default: true - /// - public bool Active = true; - - /// - /// Specifies the data type of each component in the array. - /// - public VertexAttribPointerType PointerType; - - /// - /// If true it can be updated, otherwise it will get ignored, when the mesh gets updated. - /// - public bool CanBeUpdated = false; - - /// - /// Generates a VBO for inserting mesh data. - /// - /// - /// Specifies the expected usage pattern of the data store. - /// Default: StaticDraw - /// - /// - /// Specifies the data type of each component in the array. - /// Default: Float - /// - /// - /// Specifies the number of components per generic vertex attribute. Must be 1, 2, 3, 4. - /// Default: 3 - /// - /// - /// Specifies the byte offset between consecutive generic vertex attributes. - /// Default: 0 - /// - /// - /// Specifies a offset of the first component of the first generic vertex attribute in the - /// array in the data store of the buffer currently bound to the GL_ARRAY_BUFFER target. - /// Default: 0 - /// - /// - /// Normalise floats? - /// Default: false - /// public VBO(BufferUsageHint bufferUsageHint = BufferUsageHint.StaticDraw, - VertexAttribPointerType pointerType = VertexAttribPointerType.Float, int pointerSize = 3, int pointerStride = 0, int pointerOffset = 0, bool normalised = false) { - BufferUsageHint = bufferUsageHint; - PointerType = pointerType; - PointerSize = pointerSize; + UsageHint = bufferUsageHint; PointerStride = pointerStride; PointerOffset = pointerOffset; - Normalised = normalised; + Normalized = normalised; } - public void Add(float x) + public override void Compile() { - CanBeUpdated = true; - } + base.Compile(); - /// - /// Adds two values to the VBO. - /// - public void Add(float x, float y) - { - AddRange(new[] {x, y}); - CanBeUpdated = true; - } - - /// - /// Adds three values to the VBO. - /// - public void Add(float x, float y, float z) - { - AddRange(new[] {x, y, z}); - CanBeUpdated = true; - } - - /// - /// Adds four values to the VBO. - /// - public void Add(float x, float y, float z, float w) - { - AddRange(new[] {x, y, z, w}); - CanBeUpdated = true; - } - - /// - /// Adds a Vector2. - /// - public void Add(Vector2 vector) - { - Add(vector.X, vector.Y); - } - - /// - /// Adds a Vector2 and a value. - /// - public void Add(Vector2 vector, float z) - { - Add(vector.X, vector.Y, z); - } - - /// - /// Adds a Vector2 and two values. - /// - public void Add(Vector2 vector, float z, float w) - { - Add(vector.X, vector.Y, z, w); - } - - /// - /// Adds a array of vector2s. - /// - /// - public void Add(params Vector2[] vectors) - { - foreach (Vector2 vector in vectors) - { - Add(vector); - } - } - - /// - /// Adds a Vector3. - /// - public void Add(Vector3 vector) - { - Add(vector.X, vector.Y, vector.Z); - } - - /// - /// Adds a Vector3 and a value. - /// - public void Add(Vector3 vector, float w) - { - Add(vector.X, vector.Y, vector.Z, w); - } - - /// - /// Adds a array of Vector3s. - /// - /// - public void Add(params Vector3[] vectors) - { - foreach (Vector3 vector in vectors) - { - Add(vector); - } - } - /// - /// Adds a vector4. - /// - /// - public void Add(Vector4 vector) - { - Add(vector.X, vector.Y, vector.Z, vector.W); - } - - /// - /// Adds a color. - /// - public void Add(Color4 color) - { - Add(color.R, color.G, color.B, color.A); - } - - /// - /// Binds the buffer to the active VAO. - /// - /// The id for the attribute. - internal void BindBuffer(int attribID) - { if (!Active) return; - var data = ToArray(); + float[] data = ToFloat(); - BufferID = GL.GenBuffer(); - GL.BindBuffer(BufferTarget.ArrayBuffer, BufferID); - GL.BufferData(BufferTarget.ArrayBuffer, data.Length * sizeof(float), data, BufferUsageHint); + _id = GL.GenBuffer(); + GL.BindBuffer(BufferTarget.ArrayBuffer, _id); + GL.BufferData(BufferTarget.ArrayBuffer, data.Length * sizeof(float), data, UsageHint); - GL.VertexAttribPointer(attribID, PointerSize, PointerType, Normalised, PointerStride, PointerOffset); - GL.EnableVertexAttribArray(attribID); - GL.BindBuffer(BufferTarget.ArrayBuffer, 0); + GL.VertexAttribPointer(AttributeID, PointerSize, PointerType, Normalized, PointerStride, PointerOffset); + GL.EnableVertexAttribArray(AttributeID); CanBeUpdated = false; } - internal void Update() + public void Update() { - var data = ToArray(); + float[] data = GetFloats(); - GL.BindBuffer(BufferTarget.ArrayBuffer, BufferID); + GL.BindBuffer(BufferTarget.ArrayBuffer, _id); GL.BufferSubData(BufferTarget.ArrayBuffer, IntPtr.Zero, data.Length * sizeof(float), data); + + CanBeUpdated = false; + } + + public override void Dispose() + { + GL.DeleteBuffer(_id); + base.Dispose(); + } + + public float[] GetFloats() + { + if (_floatArray == null || CanBeUpdated) + { + _floatArray = ToFloat(); + } + + return _floatArray; + } + + protected abstract float[] ToFloat(); + } + + public class VBO : VBO, IEnumerable + where TType : struct + { + static Dictionary> _pointerSizes = new Dictionary>() + { + { typeof(float), new Tuple(1, VertexAttribPointerType.Float) }, + { typeof(Vector2), new Tuple(2, VertexAttribPointerType.Float) }, + { typeof(Vector3), new Tuple(3, VertexAttribPointerType.Float) }, + { typeof(Vector4), new Tuple(4, VertexAttribPointerType.Float) }, + { typeof(Color4), new Tuple(4, VertexAttribPointerType.Float) }, + }; + private List _values = new List(); + + public override int Count => _values.Count; + + public VBO(BufferUsageHint bufferUsageHint = BufferUsageHint.StaticDraw, + int pointerStride = 0, int pointerOffset = 0, bool normalised = false) : base(bufferUsageHint, pointerStride, pointerOffset, normalised) + { + if (!_pointerSizes.ContainsKey(typeof(TType))) + throw new NotSupportedException($"The type '{typeof(TType).FullName}' is not applicable for VBOs."); + + PointerSize = _pointerSizes[typeof(TType)].Item1; + PointerType = _pointerSizes[typeof(TType)].Item2; + } + + public void Add(TType value) + { + _values.Add(value); + CanBeUpdated = true; + } + + public void RemoveAt(int pos) + { + _values.RemoveAt(pos); + CanBeUpdated = true; + } + + public IEnumerator GetEnumerator() + { + return _values.GetEnumerator(); + } + + protected override float[] ToFloat() + { + List floats = new List(); + + foreach (TType value in _values) + { + switch (value) + { + case float f: floats.Add(f); break; + case Vector2 v: floats.AddRange(new[] { v.X, v.Y }); break; + case Vector3 v: floats.AddRange(new[] { v.X, v.Y, v.Z }); break; + case Vector4 v: floats.AddRange(new[] { v.X, v.Y, v.Z, v.W }); break; + case Color4 v: floats.AddRange(new[] { v.R, v.G, v.B, v.A }); break; + } + } + return floats.ToArray(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return _values.GetEnumerator(); } } -} \ No newline at end of file +} diff --git a/SMCode/SM.OGL/Shaders/GenericShader.cs b/SMCode/SM.OGL/Shaders/GenericShader.cs index ddb32a1..27d74e7 100644 --- a/SMCode/SM.OGL/Shaders/GenericShader.cs +++ b/SMCode/SM.OGL/Shaders/GenericShader.cs @@ -144,7 +144,7 @@ namespace SM.OGL.Shaders if (mesh.Indices != null) GL.DrawElementsInstanced(mesh.PrimitiveType, 0, DrawElementsType.UnsignedInt, mesh.Indices, amount); else - GL.DrawArraysInstanced(mesh.PrimitiveType, 0, mesh.Vertex.Count / mesh.Vertex.PointerSize, amount); + GL.DrawArraysInstanced(mesh.PrimitiveType, 0, mesh.Vertex.Count, amount); } /// /// Draws the mesh while forcing a primitive type instead of using the mesh type. @@ -157,7 +157,7 @@ namespace SM.OGL.Shaders if (mesh.Indices != null) GL.DrawElementsInstanced(modelType, 0, DrawElementsType.UnsignedInt, mesh.Indices, amount); else - GL.DrawArraysInstanced(modelType, 0, mesh.Vertex.Count / mesh.Vertex.PointerSize, amount); + GL.DrawArraysInstanced(modelType, 0, mesh.Vertex.Count, amount); } /// diff --git a/SMCode/SM2D/Object/Polygon.cs b/SMCode/SM2D/Object/Polygon.cs index b1ef988..f9be0c2 100644 --- a/SMCode/SM2D/Object/Polygon.cs +++ b/SMCode/SM2D/Object/Polygon.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using OpenTK; +using OpenTK.Graphics; using OpenTK.Graphics.OpenGL4; using SM.Base.Objects; using SM.OGL.Mesh; @@ -17,13 +18,13 @@ namespace SM2D.Object public class Polygon : Mesh { /// - public override VBO Vertex { get; protected set; } = new VBO(); + public override VBO Vertex { get; protected set; } = new VBO(); /// - public override VBO UVs { get; protected set; } = new VBO(pointerSize: 2); + public override VBO UVs { get; protected set; } = new VBO(); /// - public override VBO Color { get; protected set; } = new VBO(pointerSize: 4); + public override VBO Color { get; protected set; } = new VBO(); /// public override PrimitiveType PrimitiveType { get; protected set; } = PrimitiveType.TriangleFan; @@ -38,7 +39,7 @@ namespace SM2D.Object foreach (var vertex in vertices) { - Vertex.Add(vertex, 0); + Vertex.Add(new Vector3(vertex)); } UpdateBoundingBox(); @@ -55,7 +56,7 @@ namespace SM2D.Object foreach (var polygonVertex in vertices) { Color.Add(polygonVertex.Color); - Vertex.Add(polygonVertex.Position, 0); + Vertex.Add(new Vector3(polygonVertex.Position.X, polygonVertex.Position.Y, 0)); } UpdateBoundingBox(); diff --git a/SM_TEST/Program.cs b/SM_TEST/Program.cs index 63afed2..a4dd181 100644 --- a/SM_TEST/Program.cs +++ b/SM_TEST/Program.cs @@ -53,11 +53,13 @@ namespace SM_TEST private static void WindowOnUpdateFrame(object sender, FrameEventArgs e) { - - line.Vertex.RemoveRange(3, 3); - line.Vertex.Add(Mouse2D.InWorld(window.ViewportCamera as Camera), 0); - line.Update(); + if (SM.Base.Controls.Mouse.LeftClick) + line.Vertex.Add(Vector3.Zero); + line.Vertex.RemoveAt(1); + line.Vertex.Add(new Vector3(Mouse2D.InWorld(window.ViewportCamera as Camera))); + line.Update(); + }