diff --git a/Prowl.Runtime/Graphics.cs b/Prowl.Runtime/Graphics.cs index be06e9578..932a636bf 100644 --- a/Prowl.Runtime/Graphics.cs +++ b/Prowl.Runtime/Graphics.cs @@ -196,7 +196,7 @@ public static void DrawMeshNowDirect(Mesh mesh) { Device.BindVertexArray(mesh.VertexArrayObject); Device.DrawElements(PrimitiveType.Triangles, (uint)mesh.IndexCount, mesh.IndexFormat == IndexFormat.UInt16 ? DrawElementsType.UnsignedShort : DrawElementsType.UnsignedInt, null); - Device.BindVertexArray(0); + Device.BindVertexArray(null); } } diff --git a/Prowl.Runtime/Rendering/GraphicsDevice.cs b/Prowl.Runtime/Rendering/GraphicsDevice.cs index 2e070407c..add0a3045 100644 --- a/Prowl.Runtime/Rendering/GraphicsDevice.cs +++ b/Prowl.Runtime/Rendering/GraphicsDevice.cs @@ -36,6 +36,12 @@ public enum WindingOrder { CW, CCW } public RasterizerState() { } } + public abstract class GraphicsVertexArray : IDisposable + { + public abstract bool IsDisposed { get; protected set; } + public abstract void Dispose(); + } + public abstract class GraphicsDevice { public abstract void Initialize(bool debug); @@ -62,12 +68,8 @@ public abstract class GraphicsDevice #region Vertex Arrays - public abstract uint GenVertexArray(); - public abstract void BindVertexArray(uint vertexArrayObject); - public abstract void DeleteVertexArray(uint vertexArrayObject); - public abstract void EnableVertexAttribArray(uint index); - public abstract unsafe void VertexAttribPointer(uint index, byte count, GLEnum type, bool normalized, uint size, void* offset); - public abstract unsafe void VertexAttribIPointer(uint index, byte count, GLEnum type, uint size, void* offset); + public abstract GraphicsVertexArray CreateVertexArray(VertexFormat format, GraphicsBuffer vertices, GraphicsBuffer? indices); + public abstract void BindVertexArray(GraphicsVertexArray? vertexArrayObject); #endregion diff --git a/Prowl.Runtime/Rendering/OpenGL/GLDevice.cs b/Prowl.Runtime/Rendering/OpenGL/GLDevice.cs index a547d463a..b6f479450 100644 --- a/Prowl.Runtime/Rendering/OpenGL/GLDevice.cs +++ b/Prowl.Runtime/Rendering/OpenGL/GLDevice.cs @@ -1,9 +1,57 @@ using Silk.NET.Core.Native; using Silk.NET.OpenGL; using System; +using static VertexFormat; +using System.Drawing; namespace Prowl.Runtime.Rendering.OpenGL { + public sealed unsafe class GLVertexArray : GraphicsVertexArray + { + public uint Handle { get; private set; } + + public GLVertexArray(VertexFormat format, GraphicsBuffer vertices, GraphicsBuffer? indices) + { + + Handle = GLDevice.GL.GenVertexArray(); + GLDevice.GL.BindVertexArray(Handle); + + BindFormat(format); + + GLDevice.GL.BindBuffer(BufferTargetARB.ArrayBuffer, (vertices as GLBuffer).Handle); + if (indices != null) + GLDevice.GL.BindBuffer(BufferTargetARB.ElementArrayBuffer, (indices as GLBuffer).Handle); + } + + void BindFormat(VertexFormat format) + { + for (var i = 0; i < format.Elements.Length; i++) + { + var element = format.Elements[i]; + var index = element.Semantic; + GLDevice.GL.EnableVertexAttribArray(index); + int offset = (int)element.Offset; + unsafe + { + if (element.Type == VertexType.Float) + GLDevice.GL.VertexAttribPointer(index, element.Count, (GLEnum)element.Type, element.Normalized, (uint)format.Size, (void*)offset); + else + GLDevice.GL.VertexAttribIPointer(index, element.Count, (GLEnum)element.Type, (uint)format.Size, (void*)offset); + } + } + } + + public override bool IsDisposed { get; protected set; } + + public override void Dispose() + { + if (IsDisposed) + return; + + GLDevice.GL.DeleteVertexArray(Handle); + IsDisposed = true; + } + } public sealed unsafe class GLDevice : GraphicsDevice { @@ -190,13 +238,19 @@ public override void BindBuffer(GraphicsBuffer buffer) #region Vertex Arrays - public override uint GenVertexArray() => GL.GenVertexArray(); - public override void BindVertexArray(uint vertexArrayObject) => GL.BindVertexArray(vertexArrayObject); - public override void DeleteVertexArray(uint vertexArrayObject) => GL.DeleteVertexArray(vertexArrayObject); - public override void EnableVertexAttribArray(uint index) => GL.EnableVertexAttribArray(index); - public override unsafe void VertexAttribIPointer(uint index, byte count, GLEnum type, uint size, void* offset) => GL.VertexAttribIPointer(index, count, type, size, offset); - - public override unsafe void VertexAttribPointer(uint index, byte count, GLEnum type, bool normalized, uint size, void* offset) => GL.VertexAttribPointer(index, count, type, normalized, size, offset); + public override GraphicsVertexArray CreateVertexArray(VertexFormat format, GraphicsBuffer vertices, GraphicsBuffer? indices) + { + return new GLVertexArray(format, vertices, indices); + } + public override void BindVertexArray(GraphicsVertexArray? vertexArrayObject) + { + GL.BindVertexArray((vertexArrayObject as GLVertexArray)?.Handle ?? 0); + //if (vertexArrayObject == null) + //{ + // GLDevice.GL.BindBuffer(BufferTargetARB.ElementArrayBuffer, 0); + // GLDevice.GL.BindBuffer(BufferTargetARB.ArrayBuffer, 0); + //} + } #endregion diff --git a/Prowl.Runtime/Resources/Mesh.cs b/Prowl.Runtime/Resources/Mesh.cs index 7478778ea..23bc5effd 100644 --- a/Prowl.Runtime/Resources/Mesh.cs +++ b/Prowl.Runtime/Resources/Mesh.cs @@ -122,7 +122,7 @@ public System.Numerics.Vector4[] BoneWeights { public int VertexCount => vertices?.Length ?? 0; public int IndexCount => indices?.Length ?? 0; - public uint VertexArrayObject => vertexArrayObject; + public GraphicsVertexArray? VertexArrayObject => vertexArrayObject; public GraphicsBuffer VertexBuffer => vertexBuffer; public GraphicsBuffer IndexBuffer => indexBuffer; @@ -154,7 +154,7 @@ public System.Numerics.Vector4[] BoneWeights { IndexFormat indexFormat = IndexFormat.UInt16; PrimitiveType meshTopology = PrimitiveType.TriangleStrip; - uint vertexArrayObject; + GraphicsVertexArray? vertexArrayObject; GraphicsBuffer vertexBuffer; GraphicsBuffer indexBuffer; @@ -180,7 +180,7 @@ public void Clear() public void Upload() { - if (changed == false && vertexArrayObject != 0) + if (changed == false && vertexArrayObject != null) return; changed = false; @@ -227,12 +227,7 @@ public void Upload() if (vertexBlob == null) return; - - vertexArrayObject = Graphics.Device.GenVertexArray(); - Graphics.Device.BindVertexArray(vertexArrayObject); - vertexBuffer = Graphics.Device.CreateBuffer(BufferType.VertexBuffer, vertexBlob, false); - layout.Bind(); if (indexFormat == IndexFormat.UInt16) { @@ -250,11 +245,11 @@ public void Upload() indexBuffer = Graphics.Device.CreateBuffer(BufferType.ElementsBuffer, indices, false); } + vertexArrayObject = Graphics.Device.CreateVertexArray(layout, vertexBuffer, indexBuffer); + Debug.Log($"VAO: [ID {vertexArrayObject}] Mesh uploaded successfully to VRAM (GPU)"); - Graphics.Device.BindVertexArray(0); - GLDevice.GL.BindBuffer(BufferTargetARB.ElementArrayBuffer, 0); - GLDevice.GL.BindBuffer(BufferTargetARB.ArrayBuffer, 0); + Graphics.Device.BindVertexArray(null); } public void RecalculateBounds() @@ -432,14 +427,12 @@ public static Mesh CreateSphere(float radius, int rings, int slices) private void DeleteGPUBuffers() { - if (vertexArrayObject != 0) - Graphics.Device.DeleteVertexArray(vertexArrayObject); - //vertexBuffer?.Dispose(); - //vertexBuffer = null; - //indexBuffer?.Dispose(); - //indexBuffer = null; - - vertexArrayObject = 0; + vertexArrayObject?.Dispose(); + vertexArrayObject = null; + vertexBuffer?.Dispose(); + vertexBuffer = null; + indexBuffer?.Dispose(); + indexBuffer = null; } private T ReadVertexData(T value) @@ -931,22 +924,4 @@ public Element(uint semantic, VertexType type, byte count, short divisor = 0, bo public enum VertexSemantic { Position, TexCoord0, TexCoord1, Normal, Color, Tangent, BoneIndex, BoneWeight } public enum VertexType { Byte = 5120, UnsignedByte = 5121, Short = 5122, Int = 5124, Float = 5126, } - - public void Bind() - { - for (var i = 0; i < Elements.Length; i++) - { - var element = Elements[i]; - var index = element.Semantic; - Graphics.Device.EnableVertexAttribArray(index); - int offset = (int)element.Offset; - unsafe - { - if (element.Type == VertexType.Float) - Graphics.Device.VertexAttribPointer(index, element.Count, (GLEnum)element.Type, element.Normalized, (uint)Size, (void*)offset); - else - Graphics.Device.VertexAttribIPointer(index, element.Count, (GLEnum)element.Type, (uint)Size, (void*)offset); - } - } - } } \ No newline at end of file diff --git a/Prowl.Runtime/Utils/PrimitiveBatch.cs b/Prowl.Runtime/Utils/PrimitiveBatch.cs index 4ed0ae2aa..eaab56db7 100644 --- a/Prowl.Runtime/Utils/PrimitiveBatch.cs +++ b/Prowl.Runtime/Utils/PrimitiveBatch.cs @@ -14,7 +14,7 @@ private struct Vertex public float r, g, b, a; } - private uint vao; + private GraphicsVertexArray? vao; private GraphicsBuffer vbo; private List vertices = new List(50); private Mesh mesh; @@ -27,14 +27,14 @@ public PrimitiveBatch(PrimitiveType primitiveType) { this.primitiveType = primitiveType; - vao = Graphics.Device.GenVertexArray(); - Graphics.Device.BindVertexArray(vao); vbo = Graphics.Device.CreateBuffer(BufferType.VertexBuffer, new byte[0], true); - new VertexFormat([ + var format = new VertexFormat([ new VertexFormat.Element((uint)0, VertexFormat.VertexType.Float, 3), new VertexFormat.Element((uint)1, VertexFormat.VertexType.Float, 4) - ]).Bind(); + ]); + + vao = Graphics.Device.CreateVertexArray(format, vbo, null); IsUploaded = false; } @@ -66,7 +66,7 @@ public void Upload() public void Draw() { - if (vertices.Count == 0 || vao <= 0) return; + if (vertices.Count == 0 || vao == null) return; Graphics.Device.BindVertexArray(vao); Graphics.Device.DrawArrays(primitiveType, 0, (uint)vertices.Count);