Files
PCK-Studio/PckStudio.Rendering/VertexArray.cs

121 lines
4.0 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenTK.Graphics.OpenGL;
using PckStudio.Core.Extensions;
namespace PckStudio.Rendering
{
public class VertexArray : IDisposable
{
private int _id;
private List<VertexBuffer> _vertexBuffers;
public VertexArray()
{
_id = GL.GenVertexArray();
_vertexBuffers = new List<VertexBuffer>();
}
public int AddNewBuffer(VertexBufferLayout layout) => AddBuffer(new VertexBuffer(), layout);
public int AddBuffer(VertexBuffer buffer, VertexBufferLayout layout)
{
Bind();
buffer.Bind();
System.Collections.ObjectModel.ReadOnlyCollection<LayoutElement> elements = layout.GetElements();
int offset = 0;
int vertexBufferIndex = 0;
foreach (LayoutElement element in elements)
{
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;
}
int index = _vertexBuffers.Count;
_vertexBuffers.Add(buffer);
return index;
}
public void Bind()
{
GL.BindVertexArray(_id);
}
public void Unbind()
{
GL.BindVertexArray(0);
}
public void Dispose()
{
Unbind();
Clear();
GL.DeleteVertexArray(_id);
}
public void Clear()
{
foreach (VertexBuffer vao in _vertexBuffers)
{
vao.Dispose();
}
_vertexBuffers.Clear();
}
public void SelectBuffer(int index)
{
if (!_vertexBuffers.IndexInRange(index))
throw new IndexOutOfRangeException(index.ToString());
Bind();
GetBuffer(index).Bind();
}
public VertexBuffer GetBuffer(int index)
{
if (_vertexBuffers.IndexInRange(index))
return _vertexBuffers[index];
throw new IndexOutOfRangeException(index.ToString());
}
}
}