From 31f22e0b1cb718e0ad4fb491b10f7e313f819927 Mon Sep 17 00:00:00 2001 From: miku-666 <74728189+NessieHax@users.noreply.github.com> Date: Tue, 27 Feb 2024 18:58:13 +0100 Subject: [PATCH] Improved VertexBufferLayout api --- PCK-Studio/Rendering/SkinRenderer.cs | 24 ++-- PCK-Studio/Rendering/TextureVertex.cs | 19 +-- PCK-Studio/Rendering/VertexArray.cs | 61 ++++++++- PCK-Studio/Rendering/VertexBuffer.cs | 2 +- PCK-Studio/Rendering/VertexBufferLayout.cs | 122 +++++++++++++----- .../Resources/shader/skinVertexShader.glsl | 5 +- 6 files changed, 163 insertions(+), 70 deletions(-) diff --git a/PCK-Studio/Rendering/SkinRenderer.cs b/PCK-Studio/Rendering/SkinRenderer.cs index 8bba5e98..fe7d4eeb 100644 --- a/PCK-Studio/Rendering/SkinRenderer.cs +++ b/PCK-Studio/Rendering/SkinRenderer.cs @@ -391,7 +391,6 @@ namespace PckStudio.Rendering Texture ??= Resources.classic_template; - skinShader.Unbind(); GLErrorCheck(); } @@ -401,7 +400,7 @@ namespace PckStudio.Rendering var skyboxVBO = new VertexBuffer(); skyboxVBO.SetData(cubeVertices); var vboLayout = new VertexBufferLayout(); - vboLayout.Add(3); + vboLayout.Add(ShaderDataType.Float3); skyboxVAO.AddBuffer(skyboxVBO, vboLayout); var skybocIBO = IndexBuffer.Create( // front @@ -425,9 +424,6 @@ namespace PckStudio.Rendering _skyboxRenderBuffer = new DrawContext(skyboxVAO, skybocIBO, PrimitiveType.Triangles); - skyboxVAO.Unbind(); - skybocIBO.Unbind(); - var skyboxShader = ShaderProgram.Create(Resources.skyboxVertexShader, Resources.skyboxFragmentShader); skyboxShader.Bind(); skyboxShader.SetUniform1("skybox", 1); @@ -447,8 +443,6 @@ namespace PckStudio.Rendering _skyboxTexture.WrapS = TextureWrapMode.ClampToEdge; _skyboxTexture.WrapT = TextureWrapMode.ClampToEdge; _skyboxTexture.WrapR = TextureWrapMode.ClampToEdge; - _skyboxTexture.Unbind(); - skyboxShader.Unbind(); GLErrorCheck(); } @@ -497,8 +491,8 @@ namespace PckStudio.Rendering VertexBuffer buffer = new VertexBuffer(); buffer.SetData(vertices.ToArray()); VertexBufferLayout layout = new VertexBufferLayout(); - layout.Add(3); - layout.Add(4); + layout.Add(ShaderDataType.Float3); + layout.Add(ShaderDataType.Float4); lineVAO.AddBuffer(buffer, layout); lineVAO.Bind(); @@ -535,8 +529,8 @@ namespace PckStudio.Rendering VertexBuffer buffer = new VertexBuffer(); buffer.SetData(data); VertexBufferLayout layout = new VertexBufferLayout(); - layout.Add(3); - layout.Add(4); + layout.Add(ShaderDataType.Float3); + layout.Add(ShaderDataType.Float4); lineVAO.AddBuffer(buffer, layout); lineVAO.Bind(); @@ -559,8 +553,8 @@ namespace PckStudio.Rendering buffer.SetData(vertices); VertexBufferLayout layout = new VertexBufferLayout(); - layout.Add(3); - layout.Add(4); + layout.Add(ShaderDataType.Float3); + layout.Add(ShaderDataType.Float4); planeVAO.AddBuffer(buffer, layout); _groundDrawContext = new DrawContext(planeVAO, buffer.GenIndexBuffer(), PrimitiveType.Quads); @@ -579,8 +573,8 @@ namespace PckStudio.Rendering var debugVBO = new VertexBuffer(); debugVBO.SetData(vertices); VertexBufferLayout layout = new VertexBufferLayout(); - layout.Add(3); - layout.Add(4); + layout.Add(ShaderDataType.Float3); + layout.Add(ShaderDataType.Float4); vao.AddBuffer(debugVBO, layout); debugDrawContext = new DrawContext(vao, debugVBO.GenIndexBuffer(), PrimitiveType.Points); } diff --git a/PCK-Studio/Rendering/TextureVertex.cs b/PCK-Studio/Rendering/TextureVertex.cs index bb62ecc5..cc1c1579 100644 --- a/PCK-Studio/Rendering/TextureVertex.cs +++ b/PCK-Studio/Rendering/TextureVertex.cs @@ -3,10 +3,7 @@ using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; using OpenTK; -using OpenTK.Graphics; namespace PckStudio.Rendering { @@ -15,26 +12,18 @@ namespace PckStudio.Rendering { internal Vector3 Position { get; set; } internal Vector2 TexPosition { get; set; } - internal float Scale { get; set; } - - public TextureVertex(Vector3 position, Vector2 texPosition) - : this(position, texPosition, 1f) - { - } - public TextureVertex(Vector3 position, Vector2 texPosition, float scale) + public TextureVertex(Vector3 position, Vector2 texPosition) { Position = position; TexPosition = texPosition; - Scale = scale; - } + } public VertexBufferLayout GetLayout() { var layout = new VertexBufferLayout(); - layout.Add(3); - layout.Add(2); - layout.Add(1); + layout.Add(ShaderDataType.Float3); + layout.Add(ShaderDataType.Float2); return layout; } } diff --git a/PCK-Studio/Rendering/VertexArray.cs b/PCK-Studio/Rendering/VertexArray.cs index dce617fd..ac8fe411 100644 --- a/PCK-Studio/Rendering/VertexArray.cs +++ b/PCK-Studio/Rendering/VertexArray.cs @@ -11,10 +11,14 @@ namespace PckStudio.Rendering internal class VertexArray : IDisposable { private int _id; + private int _vertexBufferIndex; + private List _vertexBuffers; public VertexArray() { _id = GL.GenVertexArray(); + _vertexBufferIndex = 0; + _vertexBuffers = new List(); } public void AddBuffer(VertexBuffer buffer, VertexBufferLayout layout) @@ -23,14 +27,49 @@ namespace PckStudio.Rendering buffer.Bind(); var elements = layout.GetElements(); int offset = 0; - for (int i = 0; i < elements.Count; i++) + foreach(var element in elements) { - var element = elements[i]; - GL.EnableVertexAttribArray(i); - GL.VertexAttribPointer(i, element.Count, element.Type, element.Normalize, layout.GetStride(), offset); - offset += element.Count * VertexBufferElement.GetStrideSize(element.Type); + Debug.Assert(element.Size > 0); + switch (element.Type) + { + case ShaderDataType.Float: + case ShaderDataType.Float2: + case ShaderDataType.Float3: + case ShaderDataType.Float4: + GL.EnableVertexAttribArray(_vertexBufferIndex); + GL.VertexAttribPointer(_vertexBufferIndex, element.ComponentCount, VertexAttribPointerType.Float, element.Normalize, layout.GetStride(), offset); + _vertexBufferIndex += 1; + break; + case ShaderDataType.Int: + case ShaderDataType.Int2: + case ShaderDataType.Int3: + case ShaderDataType.Int4: + GL.EnableVertexAttribArray(_vertexBufferIndex); + GL.VertexAttribIPointer(_vertexBufferIndex, element.ComponentCount, VertexAttribIntegerType.Int, layout.GetStride(), new IntPtr(offset)); + _vertexBufferIndex += 1; + break; + case ShaderDataType.Mat2: + case ShaderDataType.Mat3: + case ShaderDataType.Mat4: + { + int count = element.ComponentCount; + for (int i = 0; i < count; i++) + { + GL.EnableVertexAttribArray(_vertexBufferIndex); + + GL.VertexAttribPointer(_vertexBufferIndex, count, VertexAttribPointerType.Float, element.Normalize, layout.GetStride(), offset + count * i); + + GL.VertexAttribDivisor(_vertexBufferIndex, 1); + _vertexBufferIndex += 1; + } + } + break; + default: + break; + } + offset += element.Size; } - Unbind(); + _vertexBuffers.Add(buffer); } public void Bind() @@ -48,5 +87,15 @@ namespace PckStudio.Rendering Unbind(); GL.DeleteVertexArray(_id); } + + internal void Clear() + { + foreach (var vao in _vertexBuffers) + { + vao.Dispose(); + } + _vertexBuffers.Clear(); + _vertexBufferIndex = 0; + } } } diff --git a/PCK-Studio/Rendering/VertexBuffer.cs b/PCK-Studio/Rendering/VertexBuffer.cs index 82a3b7e7..93b2ce55 100644 --- a/PCK-Studio/Rendering/VertexBuffer.cs +++ b/PCK-Studio/Rendering/VertexBuffer.cs @@ -37,7 +37,7 @@ namespace PckStudio.Rendering _count = data.Length; Bind(); int size = sizeofT * _count; - if (_size == 0) + if (_size < size) { GL.BufferData(BufferTarget.ArrayBuffer, size, data, BufferUsageHint.StaticDraw); _size = size; diff --git a/PCK-Studio/Rendering/VertexBufferLayout.cs b/PCK-Studio/Rendering/VertexBufferLayout.cs index c9f902ac..2cef633f 100644 --- a/PCK-Studio/Rendering/VertexBufferLayout.cs +++ b/PCK-Studio/Rendering/VertexBufferLayout.cs @@ -8,68 +8,130 @@ using OpenTK.Graphics.OpenGL; namespace PckStudio.Rendering { - struct VertexBufferElement + public enum ShaderDataType { - public readonly VertexAttribPointerType Type; - public readonly int Count; + Float, + Float2, + Float3, + Float4, + + Int, + Int2, + Int3, + Int4, + + Mat2, + Mat3, + Mat4, + } + + struct LayoutElement + { + public readonly ShaderDataType Type; public readonly bool Normalize; - public static int GetStrideSize(VertexAttribPointerType type) + public int Size => GetSize(Type); + + public int ComponentCount => GetComponentCount(Type); + + private static int GetSize(ShaderDataType type) { return type switch { - VertexAttribPointerType.Int => 4, - VertexAttribPointerType.UnsignedInt => 4, - VertexAttribPointerType.Float => 4, + ShaderDataType.Int => 1 * 4, + ShaderDataType.Int2 => 2 * 4, + ShaderDataType.Int3 => 3 * 4, + ShaderDataType.Int4 => 4 * 4, + + ShaderDataType.Float => 1 * 4, + ShaderDataType.Float2 => 2 * 4, + ShaderDataType.Float3 => 3 * 4, + ShaderDataType.Float4 => 4 * 4, + + ShaderDataType.Mat2 => 2 * 2 * 4, + ShaderDataType.Mat3 => 3 * 3 * 4, + ShaderDataType.Mat4 => 4 * 4 * 4, _ => 0 }; } - public VertexBufferElement(VertexAttribPointerType type, int count, bool normalize) + private static int GetComponentSize(ShaderDataType type) + { + return type switch + { + ShaderDataType.Int => 4, + ShaderDataType.Int2 => 4, + ShaderDataType.Int3 => 4, + ShaderDataType.Int4 => 4, + + ShaderDataType.Float => 4, + ShaderDataType.Float2 => 4, + ShaderDataType.Float3 => 4, + ShaderDataType.Float4 => 4, + + ShaderDataType.Mat2 => 2 * 4, + ShaderDataType.Mat3 => 3 * 4, + ShaderDataType.Mat4 => 4 * 4, + _ => 0 + }; + } + + private static int GetComponentCount(ShaderDataType type) + { + return type switch + { + ShaderDataType.Int => 1, + ShaderDataType.Int2 => 2, + ShaderDataType.Int3 => 3, + ShaderDataType.Int4 => 4, + + ShaderDataType.Float => 1, + ShaderDataType.Float2 => 2, + ShaderDataType.Float3 => 3, + ShaderDataType.Float4 => 4, + + ShaderDataType.Mat2 => 2 * 2, + ShaderDataType.Mat3 => 3 * 3, + ShaderDataType.Mat4 => 4 * 4, + _ => 0 + }; + } + + public LayoutElement(ShaderDataType type) : this(type, false) { } + + public LayoutElement(ShaderDataType type, bool normalize) { Type = type; - Count = count; Normalize = normalize; } + + public static implicit operator LayoutElement(ShaderDataType type) => new LayoutElement(type); } internal struct VertexBufferLayout { - private List elements; + private List elements; private int stride; - public VertexBufferLayout() { - elements = new List(); + elements = new List(); stride = 0; } - public ReadOnlyCollection GetElements() + public readonly ReadOnlyCollection GetElements() { return elements.AsReadOnly(); } - public void Add(int count) + public void Add(ShaderDataType type) { - if (typeof(T).Equals(typeof(float))) - { - elements.Add(new VertexBufferElement(VertexAttribPointerType.Float, count, false)); - stride += count * VertexBufferElement.GetStrideSize(VertexAttribPointerType.Float); - } - if (typeof(T).Equals(typeof(int))) - { - elements.Add(new VertexBufferElement(VertexAttribPointerType.Int, count, false)); - stride += count * VertexBufferElement.GetStrideSize(VertexAttribPointerType.Int); - } - if (typeof(T).Equals(typeof(uint))) - { - elements.Add(new VertexBufferElement(VertexAttribPointerType.UnsignedInt, count, false)); - stride += count * VertexBufferElement.GetStrideSize(VertexAttribPointerType.UnsignedInt); - } + var element = new LayoutElement(type); + elements.Add(element); + stride += element.Size; } - internal int GetStride() + internal readonly int GetStride() { return stride; } diff --git a/PCK-Studio/Resources/shader/skinVertexShader.glsl b/PCK-Studio/Resources/shader/skinVertexShader.glsl index 7d22fb22..42ba0031 100644 --- a/PCK-Studio/Resources/shader/skinVertexShader.glsl +++ b/PCK-Studio/Resources/shader/skinVertexShader.glsl @@ -1,8 +1,7 @@ #version 330 core -layout(location = 0) in vec4 vertexPosition; +layout(location = 0) in vec3 vertexPosition; layout(location = 1) in vec2 texCoord; -layout(location = 2) in float scale; uniform mat4 u_ViewProjection; uniform mat4 u_Transform; @@ -16,5 +15,5 @@ void main() { dataOut.TexCoord = texCoord; vec4 invertedVertex = vec4(vertexPosition.x, vertexPosition.yz * -1.0, 1.0); - gl_Position = u_ViewProjection * u_Transform * invertedVertex * scale; + gl_Position = u_ViewProjection * u_Transform * invertedVertex; }; \ No newline at end of file