General progress on getting OpenGL based rendering.
This commit is contained in:
99
src/SlatedGameToolkit.Framework/Graphics/Render/Batch.cs
Normal file
99
src/SlatedGameToolkit.Framework/Graphics/Render/Batch.cs
Normal file
@@ -0,0 +1,99 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Numerics;
|
||||
using SlatedGameToolkit.Framework.Graphics.Meshes;
|
||||
using SlatedGameToolkit.Framework.Graphics;
|
||||
using SlatedGameToolkit.Framework.Graphics.Textures;
|
||||
using SlatedGameToolkit.Framework.Graphics.Shaders;
|
||||
|
||||
namespace SlatedGameToolkit.Framework.Graphics.Render
|
||||
{
|
||||
public class Batch : IDisposable {
|
||||
private Texture texture;
|
||||
private bool disposed;
|
||||
private VertexArray vertexArray;
|
||||
private const int VERTEX_LENGTH = 6;
|
||||
private GLMultiDrawElements multiDrawElements;
|
||||
public bool Batching { get; private set; }
|
||||
private float[] data;
|
||||
private uint[] indices;
|
||||
private uint[] lengths;
|
||||
private uint[] offsets;
|
||||
private uint dataIndex, indicesIndex, lengthsIndex;
|
||||
|
||||
public Batch(uint BatchVertexSize = 4096) {
|
||||
multiDrawElements = GLFunctionUtils.RetrieveGLDelegate<GLMultiDrawElements>("glMultDrawElements");
|
||||
indices = new uint[BatchVertexSize];
|
||||
lengths = new uint[BatchVertexSize];
|
||||
offsets = new uint[BatchVertexSize];
|
||||
data = new float[BatchVertexSize * VERTEX_LENGTH];
|
||||
|
||||
vertexArray = new VertexArray();
|
||||
|
||||
VertexAttributeDefinition[] definitions = new VertexAttributeDefinition[3];
|
||||
definitions[0] = new VertexAttributeDefinition(0, 3, 3 * sizeof(float), 0);
|
||||
definitions[1] = new VertexAttributeDefinition(1, 4, 1 * sizeof(float), 3 * sizeof(float));
|
||||
definitions[2] = new VertexAttributeDefinition(2, 2, 2 * sizeof(float), 4 * sizeof(float));
|
||||
vertexArray.defineVertexAttributes(definitions: definitions);
|
||||
}
|
||||
|
||||
public virtual void Begin(Texture texture) {
|
||||
if (Batching) throw new InvalidOperationException("This batch is already started.");
|
||||
this.texture = texture ?? throw new ArgumentNullException("texture");
|
||||
this.Batching = true;
|
||||
}
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
if (disposed) return;
|
||||
disposed = true;
|
||||
vertexArray.Dispose();
|
||||
}
|
||||
|
||||
public virtual void Draw(IMeshable meshable, Color color) {
|
||||
ValueTuple<Vector3, Vector2>[] vertices = meshable.Vertices;
|
||||
uint[] indices = meshable.Elements;
|
||||
if (vertices.Length * VERTEX_LENGTH + dataIndex >= data.Length || indices.Length + indicesIndex >= indicesIndex) Flush();
|
||||
for (int i = 0; i < vertices.Length; i++) {
|
||||
data[dataIndex] = vertices[i].Item1.X;
|
||||
dataIndex++;
|
||||
data[dataIndex] = vertices[i].Item1.Y;
|
||||
dataIndex++;
|
||||
data[dataIndex] = vertices[i].Item1.Z;
|
||||
dataIndex++;
|
||||
|
||||
data[dataIndex] = color.ToArgb();
|
||||
dataIndex++;
|
||||
|
||||
data[dataIndex] = vertices[i].Item2.X;
|
||||
dataIndex++;
|
||||
data[dataIndex] = vertices[i].Item2.Y;
|
||||
dataIndex++;
|
||||
|
||||
uint elementsCount = (uint)indices.Length;
|
||||
Array.Copy(indices, indices, elementsCount);
|
||||
indicesIndex += elementsCount;
|
||||
|
||||
lengths[lengthsIndex] = elementsCount;
|
||||
lengthsIndex ++;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void End() {
|
||||
if (!Batching) throw new InvalidOperationException("This batch was never started.");
|
||||
this.Batching = false;
|
||||
Flush();
|
||||
}
|
||||
|
||||
protected virtual void Flush() {
|
||||
texture.Use();
|
||||
vertexArray.Use();
|
||||
vertexArray.BufferVertices(data);
|
||||
vertexArray.BufferIndices(indices);
|
||||
dataIndex = 0;
|
||||
indicesIndex = 0;
|
||||
lengthsIndex = 0;
|
||||
multiDrawElements(GLEnums.GL_TRIANGLE_STRIP, lengths, GLEnums.GL_UNSIGNED_INT, offsets);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user