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