From 512b5f4b136923b23de5c8cbcdddc18a5b68aff7 Mon Sep 17 00:00:00 2001 From: Harrison Date: Tue, 7 Jul 2020 01:41:12 -0500 Subject: [PATCH] Refactored, and added separate constructor for custom shader. --- .../{MeshBatch.cs => MeshBatchRenderer.cs} | 115 +++++++++++++----- .../Graphics/Text/BitmapFont.cs | 2 +- .../Utilities/Playground/MainState.cs | 18 +-- 3 files changed, 92 insertions(+), 43 deletions(-) rename src/SlatedGameToolkit.Framework/Graphics/Render/{MeshBatch.cs => MeshBatchRenderer.cs} (53%) diff --git a/src/SlatedGameToolkit.Framework/Graphics/Render/MeshBatch.cs b/src/SlatedGameToolkit.Framework/Graphics/Render/MeshBatchRenderer.cs similarity index 53% rename from src/SlatedGameToolkit.Framework/Graphics/Render/MeshBatch.cs rename to src/SlatedGameToolkit.Framework/Graphics/Render/MeshBatchRenderer.cs index 3685134..b1e3ecc 100644 --- a/src/SlatedGameToolkit.Framework/Graphics/Render/MeshBatch.cs +++ b/src/SlatedGameToolkit.Framework/Graphics/Render/MeshBatchRenderer.cs @@ -10,14 +10,19 @@ using SlatedGameToolkit.Framework.Utilities; namespace SlatedGameToolkit.Framework.Graphics.Render { - public class MeshBatch : IDisposable { + + /// + /// Represents a grouping of similar meshes that can be rendered with similar properties. + /// Specifically, properties that need to be the same are: + /// Texture and it's respective properties, model matrix, and vertex buffer array and objects. + /// + public class MeshBatchRenderer : IDisposable { public bool Debug { get; set; } private const int VERTEX_LENGTH = 9; private bool disposed; private float batchDelta; public GLContext GLContext {get; private set; } - private int projALoc, viewALoc, modelALoc, texturedALoc, singleChanneledALoc, flippedALoc; - private bool flipped, singleChanneled; + private int projULoc, viewULoc, modelULoc, texturedULoc, singleChanneledULoc, flippedULoc; private Camera camera; private RenderProgram renderProgram; private ITexture texture; @@ -32,15 +37,20 @@ namespace SlatedGameToolkit.Framework.Graphics.Render private int[] verticeOffsets; private int dataIndex, indicesIndex, offsetIndex; - public MeshBatch(Camera camera, RenderProgram renderProgram = null, uint BatchVertexSize = 1024) { - if (renderProgram == null) { - VertexShader vert = new VertexShader(EmbeddedResUtils.ReadEmbeddedResourceText("default.vert")); - FragmentShader frag = new FragmentShader(EmbeddedResUtils.ReadEmbeddedResourceText("default.frag")); - renderProgram = new RenderProgram(null, vert, frag); - } - this.renderProgram = renderProgram; - this.GLContext = renderProgram.GLContext; + /// + /// Instantiates a mesh batch with a default vertex and fragment shader. + /// + /// The camera to use for providing the correct matrices. + /// The vertex batch size. Defaults to 1024. This is multiplied by 9 for each individual value of the vertex. + /// The glContext to associate the shaders with. Defaults to the currently active one. + public MeshBatchRenderer(Camera camera, uint BatchVertexSize = 1024, GLContext glContext = null) { + VertexShader vert = new VertexShader(EmbeddedResUtils.ReadEmbeddedResourceText("default.vert")); + FragmentShader frag = new FragmentShader(EmbeddedResUtils.ReadEmbeddedResourceText("default.frag")); + this.GLContext = glContext ?? WindowContextsManager.CurrentGL; + renderProgram = new RenderProgram(this.GLContext, vert, frag); + this.camera = camera ?? throw new ArgumentNullException("camera"); + if (BatchVertexSize < 1) throw new ArgumentException("Batch vertex size cannot be less than 1."); indices = new uint[BatchVertexSize]; lengths = new int[BatchVertexSize]; indiceOffsets = new int[BatchVertexSize]; @@ -51,16 +61,61 @@ namespace SlatedGameToolkit.Framework.Graphics.Render definitions[0] = new VertexAttributeDefinition((uint)GLContext.GetAttribLocation(renderProgram.Handle, "aPosition"), 3); definitions[1] = new VertexAttributeDefinition((uint)GLContext.GetAttribLocation(renderProgram.Handle, "aColor"), 4); definitions[2] = new VertexAttributeDefinition((uint)GLContext.GetAttribLocation(renderProgram.Handle, "aTexCoord"), 2); - renderProgram.Use(); - modelALoc = GLContext.GetUniformLocation(renderProgram.Handle, "models"); - viewALoc = GLContext.GetUniformLocation(renderProgram.Handle, "view"); - projALoc = GLContext.GetUniformLocation(renderProgram.Handle, "projection"); - texturedALoc = GLContext.GetUniformLocation(renderProgram.Handle, "textured"); - singleChanneledALoc = GLContext.GetUniformLocation(renderProgram.Handle, "singleChanneled"); - flippedALoc = GLContext.GetUniformLocation(renderProgram.Handle, "flipped"); vertexBuffers.defineVertexAttributes(definitions: definitions); + renderProgram.Use(); + modelULoc = GLContext.GetUniformLocation(renderProgram.Handle, "models"); + viewULoc = GLContext.GetUniformLocation(renderProgram.Handle, "view"); + projULoc = GLContext.GetUniformLocation(renderProgram.Handle, "projection"); + texturedULoc = GLContext.GetUniformLocation(renderProgram.Handle, "textured"); + singleChanneledULoc = GLContext.GetUniformLocation(renderProgram.Handle, "singleChanneled"); + flippedULoc = GLContext.GetUniformLocation(renderProgram.Handle, "flipped"); - GLContext.UniformMatrix4fv(projALoc, 1, false, camera.ProjectionMatrix.ToColumnMajorArray()); + GLContext.UniformMatrix4fv(projULoc, 1, false, camera.ProjectionMatrix.ToColumnMajorArray()); + } + + /// + /// Instantiates the mesh batch with a custom shader program. + /// + /// For this shader to work with this mesh batch, it must have at least defined the required attributes and uniforms. + /// + /// The position vertex attribute's name. A vec3. To be used to detect the index of the attribute in the shader program. + /// The color vertex attribute's name. A vec4. To be used to detect the index of the attribute in the shader program. + /// The texture coordinate vertex attribute's name. A vec2. To be used to detect the index of the attribute in the shader program. + /// The models 4x4 matrix's uniform name. To be used to detect the index of the uniform in the shader program. + /// The view 4x4 matrix's uniform name. To be used to detect the index of the uniform in the shader program. + /// The projection 4x4 matrix's uniform name. To be used to detect the index of the uniform in the shader program. + /// The name of a boolean uniform dictating whether or not the batch of meshes have an associated texture. + /// The name of a boolean uniform dictating whether or not the current texture is single channelled and only uses red. + /// The name of a boolean uniform dictating whether or not the current texture is to have it's coordinates flipped. + /// The camera to use to provide the matrices. + /// The render program to use for the actual rendering. + /// The vertex buffer size. Defaults to 1024, and is multiplied by 9 for the individual values of each vertex. + public MeshBatchRenderer(string aPosition, string aColor, string aTexCoord, string uModels, string uView, string uProjection, string uTextured, string uSingleChanneled, string uFlipped, Camera camera, RenderProgram renderProgram, uint BatchVertexSize = 1024) { + this.renderProgram = renderProgram ?? throw new ArgumentNullException("renderProgram"); + this.camera = camera ?? throw new ArgumentNullException("camera"); + if (BatchVertexSize < 1) throw new ArgumentException("Batch vertex size cannot be less than 1."); + this.GLContext = renderProgram.GLContext; + + indices = new uint[BatchVertexSize]; + lengths = new int[BatchVertexSize]; + indiceOffsets = new int[BatchVertexSize]; + data = new float[BatchVertexSize * VERTEX_LENGTH]; + verticeOffsets = new int[BatchVertexSize]; + vertexBuffers = new VertexArrayBuffers(GLContext); + VertexAttributeDefinition[] definitions = new VertexAttributeDefinition[3]; + definitions[0] = new VertexAttributeDefinition((uint)GLContext.GetAttribLocation(renderProgram.Handle, aPosition), 3); + definitions[1] = new VertexAttributeDefinition((uint)GLContext.GetAttribLocation(renderProgram.Handle, aColor), 4); + definitions[2] = new VertexAttributeDefinition((uint)GLContext.GetAttribLocation(renderProgram.Handle, aTexCoord), 2); + + renderProgram.Use(); + modelULoc = GLContext.GetUniformLocation(renderProgram.Handle, uModels); + viewULoc = GLContext.GetUniformLocation(renderProgram.Handle, uView); + projULoc = GLContext.GetUniformLocation(renderProgram.Handle, uProjection); + texturedULoc = GLContext.GetUniformLocation(renderProgram.Handle, uTextured); + singleChanneledULoc = GLContext.GetUniformLocation(renderProgram.Handle, uSingleChanneled); + flippedULoc = GLContext.GetUniformLocation(renderProgram.Handle, uFlipped); + + GLContext.UniformMatrix4fv(projULoc, 1, false, camera.ProjectionMatrix.ToColumnMajorArray()); } /// @@ -92,16 +147,10 @@ namespace SlatedGameToolkit.Framework.Graphics.Render if (mesh.Texture?.Handle != this.texture?.Handle) { Flush(); this.texture = mesh.Texture; - GLContext.Uniform1i(texturedALoc, texture == null ? 0 : 1); - } - if (texture != null) { - if (flipped != texture.Flipped) { - GLContext.Uniform1i(flippedALoc, texture.Flipped ? 1 : 0); - this.flipped = texture.Flipped; - } - if (singleChanneled != texture.SingleChanneled) { - GLContext.Uniform1i(singleChanneledALoc, texture.SingleChanneled ? 1 : 0); - this.singleChanneled = texture.SingleChanneled; + GLContext.Uniform1i(texturedULoc, texture == null ? 0 : 1); + if (texture != null) { + GLContext.Uniform1i(flippedULoc, texture.Flipped ? 1 : 0); + GLContext.Uniform1i(singleChanneledULoc, texture.SingleChanneled ? 1 : 0); } } ValueTuple[] vertices = mesh.Vertices; @@ -161,9 +210,9 @@ namespace SlatedGameToolkit.Framework.Graphics.Render vertexBuffers.BufferVertices(data, true); vertexBuffers.BufferIndices(indices, true); - GLContext.UniformMatrix4fv(modelALoc, 1, false, modelsMatrix.ToColumnMajorArray()); - if (camera.ViewChanged) GLContext.UniformMatrix4fv(viewALoc, 1, false, camera.ViewMatrix.ToColumnMajorArray()); - if (camera.ProjectionChanged) GLContext.UniformMatrix4fv(projALoc, 1, false, camera.ProjectionMatrix.ToColumnMajorArray()); + GLContext.UniformMatrix4fv(modelULoc, 1, false, modelsMatrix.ToColumnMajorArray()); + if (camera.ViewChanged) GLContext.UniformMatrix4fv(viewULoc, 1, false, camera.ViewMatrix.ToColumnMajorArray()); + if (camera.ProjectionChanged) GLContext.UniformMatrix4fv(projULoc, 1, false, camera.ProjectionMatrix.ToColumnMajorArray()); if (Debug) { GLContext.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); @@ -195,7 +244,7 @@ namespace SlatedGameToolkit.Framework.Graphics.Render } } - ~MeshBatch() + ~MeshBatchRenderer() { Dispose(false); } diff --git a/src/SlatedGameToolkit.Framework/Graphics/Text/BitmapFont.cs b/src/SlatedGameToolkit.Framework/Graphics/Text/BitmapFont.cs index 9e77ed2..57cba5e 100644 --- a/src/SlatedGameToolkit.Framework/Graphics/Text/BitmapFont.cs +++ b/src/SlatedGameToolkit.Framework/Graphics/Text/BitmapFont.cs @@ -108,7 +108,7 @@ namespace SlatedGameToolkit.Framework.Graphics.Text } } - public unsafe void WriteLine(MeshBatch batch, float x, float y, string text, Color color) { + public unsafe void WriteLine(MeshBatchRenderer batch, float x, float y, string text, Color color) { float currentPoint = x; float baseLine = y; char[] chars = text.ToCharArray(); diff --git a/src/SlatedGameToolkit.Tools/Utilities/Playground/MainState.cs b/src/SlatedGameToolkit.Tools/Utilities/Playground/MainState.cs index 85fbd62..9886258 100644 --- a/src/SlatedGameToolkit.Tools/Utilities/Playground/MainState.cs +++ b/src/SlatedGameToolkit.Tools/Utilities/Playground/MainState.cs @@ -17,7 +17,7 @@ namespace SlatedGameToolkit.Tools.Utilities.Playground { private WindowContext window; private Camera2D camera; - private MeshBatch batch; + private MeshBatchRenderer renderer; private BitmapFont font; private Texture logoTexture, fillerTexture; private RectangleMesh logo, textureTester, untextured; @@ -40,7 +40,7 @@ namespace SlatedGameToolkit.Tools.Utilities.Playground logoTexture.Dispose(); fillerTexture.Dispose(); font.Dispose(); - batch.Dispose(); + renderer.Dispose(); window.Dispose(); } @@ -55,7 +55,7 @@ namespace SlatedGameToolkit.Tools.Utilities.Playground Vector2 drawableDimensions = window.GetDrawableDimensions(); float ratio = drawableDimensions.Y / drawableDimensions.X; camera = new Camera2D(2f, ratio * 2f); - batch = new MeshBatch(camera, BatchVertexSize: 2048); + renderer = new MeshBatchRenderer(camera, BatchVertexSize: 2048); logoTexture = TextureLoader.Load2DTexture("Resources/Playground/yhdnbgnc.png"); logo = new RectangleMesh(logoTexture, Color.White); @@ -84,12 +84,12 @@ namespace SlatedGameToolkit.Tools.Utilities.Playground public void Render(double delta) { - batch.Begin(Matrix4x4.Identity, delta); - batch.Draw(logo); - batch.Draw(textureTester); - batch.Draw(untextured); - font.WriteLine(batch, 0.25f, -0.35f, "ABCDEFGHIJKLMNOPQRSTUVWXYZ\n1234567890", Color.White); - batch.End(); + renderer.Begin(Matrix4x4.Identity, delta); + renderer.Draw(logo); + renderer.Draw(textureTester); + renderer.Draw(untextured); + font.WriteLine(renderer, 0.25f, -0.35f, "ABCDEFGHIJKLMNOPQRSTUVWXYZ\n1234567890", Color.White); + renderer.End(); } public void Update(double timeStep)