130 lines
4.6 KiB
C#
130 lines
4.6 KiB
C#
using RecrownedGTK.Graphics.Render.Shaders;
|
|
using System;
|
|
using OpenTK;
|
|
using OpenTK.Graphics.OpenGL;
|
|
namespace RecrownedGTK.Graphics.Render {
|
|
public class Batch : IDisposable {
|
|
private bool disposed;
|
|
private bool begun;
|
|
private readonly float[] vertices;
|
|
private TextureData textureData;
|
|
private VertexAttributesArrayHandle vertexAttributes;
|
|
private Shader shader;
|
|
private VertexBufferArrayHandle bufferArrayHandle;
|
|
private uint[] indices;
|
|
private ElementBufferArrayHandle elementBufferArray;
|
|
private Matrix4 transformMatrix;
|
|
|
|
private uint vertPosition;
|
|
private int indicePosition;
|
|
public Batch(int verticesLimit = 300, int elementLimit = 450) {
|
|
elementBufferArray = new ElementBufferArrayHandle();
|
|
bufferArrayHandle = new VertexBufferArrayHandle();
|
|
vertices = new float[verticesLimit*9];
|
|
indices = new uint[elementLimit];
|
|
}
|
|
public void Begin(VertexAttributesArrayHandle vertexAttributesArray = null, Shader shader = null) {
|
|
if (begun) throw new InvalidOperationException("This TextureBatch has already been started.");
|
|
|
|
this.shader = shader ?? this.shader ?? Shader.CreateBasicShader();
|
|
this.vertexAttributes = vertexAttributes ?? this.vertexAttributes ?? VertexAttributesArrayHandle.CreateBasicVA(ref transformMatrix, this.shader);
|
|
|
|
begun = true;
|
|
}
|
|
|
|
public void Draw(IDrawable drawable) {
|
|
TextureData textureData = null;
|
|
VertexInformation[] vertices = null;
|
|
uint[] indices = null;
|
|
drawable.Draw(out vertices, out indices, out textureData);
|
|
|
|
// If the new set of vertices are greater than the max length, we flush.
|
|
if (vertices.Length * 9 + vertPosition > this.vertices.Length) {
|
|
Flush();
|
|
}
|
|
|
|
// Flush if the texture is changed.
|
|
if (!this.textureData.Equals(textureData)) {
|
|
Flush();
|
|
this.textureData = textureData;
|
|
}
|
|
|
|
if (indices.Length + indicePosition > this.indices.Length) {
|
|
Flush();
|
|
}
|
|
|
|
// Indices.
|
|
for (int indIndex = 0; indIndex < indices.Length; indIndex++) {
|
|
this.indices[indicePosition] = indices[indIndex] + vertPosition;
|
|
indicePosition++;
|
|
}
|
|
|
|
for (int vertIndex = 0; vertIndex < vertices.Length; vertIndex++) {
|
|
VertexInformation curr = vertices[vertIndex];
|
|
this.vertices[vertPosition] = curr.coords.X;
|
|
vertPosition++;
|
|
this.vertices[vertPosition] = curr.coords.Y;
|
|
vertPosition++;
|
|
this.vertices[vertPosition] = curr.coords.Z;
|
|
vertPosition++;
|
|
|
|
this.vertices[vertPosition] = curr.textureCoords.X;
|
|
vertPosition++;
|
|
this.vertices[vertPosition] = curr.textureCoords.Y;
|
|
vertPosition++;
|
|
|
|
this.vertices[vertPosition] = curr.color.R;
|
|
vertPosition++;
|
|
this.vertices[vertPosition] = curr.color.G;
|
|
vertPosition++;
|
|
this.vertices[vertPosition] = curr.color.B;
|
|
vertPosition++;
|
|
this.vertices[vertPosition] = curr.color.A;
|
|
vertPosition++;
|
|
}
|
|
}
|
|
|
|
private void Flush() {
|
|
if (vertPosition == 0) return;
|
|
indicePosition = 0;
|
|
vertPosition = 0;
|
|
|
|
vertexAttributes.Bind();
|
|
shader.Use();
|
|
bufferArrayHandle.Buffer(vertices);
|
|
elementBufferArray.Buffer(indices);
|
|
|
|
GL.DrawElements(PrimitiveType.Triangles, indicePosition, DrawElementsType.UnsignedInt, 0);
|
|
}
|
|
|
|
public void End() {
|
|
if (!begun) throw new InvalidOperationException("The TextureBatch has not begun.");
|
|
Flush();
|
|
begun = false;
|
|
}
|
|
|
|
protected virtual void Dispose(bool disposing) {
|
|
if (disposed) return;
|
|
if (disposing) {
|
|
elementBufferArray.Dispose();
|
|
vertexAttributes.Dispose();
|
|
bufferArrayHandle.Dispose();
|
|
shader.Dispose();
|
|
}
|
|
|
|
disposed = true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Disposes all the handles and shaders.
|
|
/// </summary>
|
|
public void Dispose() {
|
|
Dispose(true);
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
~Batch() {
|
|
Dispose(false);
|
|
}
|
|
}
|
|
} |