Improved VertexBufferLayout api

This commit is contained in:
miku-666
2024-02-27 18:58:13 +01:00
parent f67606fc6f
commit 31f22e0b1c
6 changed files with 163 additions and 70 deletions

View File

@@ -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<float>(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<float>(3);
layout.Add<float>(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<float>(3);
layout.Add<float>(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<float>(3);
layout.Add<float>(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<float>(3);
layout.Add<float>(4);
layout.Add(ShaderDataType.Float3);
layout.Add(ShaderDataType.Float4);
vao.AddBuffer(debugVBO, layout);
debugDrawContext = new DrawContext(vao, debugVBO.GenIndexBuffer(), PrimitiveType.Points);
}

View File

@@ -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<float>(3);
layout.Add<float>(2);
layout.Add<float>(1);
layout.Add(ShaderDataType.Float3);
layout.Add(ShaderDataType.Float2);
return layout;
}
}

View File

@@ -11,10 +11,14 @@ namespace PckStudio.Rendering
internal class VertexArray : IDisposable
{
private int _id;
private int _vertexBufferIndex;
private List<VertexBuffer> _vertexBuffers;
public VertexArray()
{
_id = GL.GenVertexArray();
_vertexBufferIndex = 0;
_vertexBuffers = new List<VertexBuffer>();
}
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;
}
}
}

View File

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

View File

@@ -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<VertexBufferElement> elements;
private List<LayoutElement> elements;
private int stride;
public VertexBufferLayout()
{
elements = new List<VertexBufferElement>();
elements = new List<LayoutElement>();
stride = 0;
}
public ReadOnlyCollection<VertexBufferElement> GetElements()
public readonly ReadOnlyCollection<LayoutElement> GetElements()
{
return elements.AsReadOnly();
}
public void Add<T>(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;
}

View File

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