Skip to content

Instantly share code, notes, and snippets.

@Thraka
Created November 13, 2019 19:00
Show Gist options
  • Save Thraka/9460b6988f8eb629dbfb01e3770602b1 to your computer and use it in GitHub Desktop.
Save Thraka/9460b6988f8eb629dbfb01e3770602b1 to your computer and use it in GitHub Desktop.
SpriteBatching for SFML and C# - Built for SadConsole

The Reset method confgures the drawing routine for the specific render target and tarnsform. The DrawQuad call will batch a sprite as long as the texture doesn't change. Once a DrawQuad call is made where there is a new texture, the End method is called which dumps the current buffer into the engine draw to get data on the screen and then the buffer pointer is reset to 0.

If the buffer is set for 1000 verticies, which gives you 250 sprite draws. However, there is an internal limit set at 800 (200 sprites) that once the batcher hits this, the buffer is resized by a small percentage and the internal limit raised. This ensures you never reach the limit of sprites and it grows as much as needed. The sprite draws just mentioned are only for batching. You have 200 batch draws of the same texture until it starts growing. Remember, as soon as you change sprite texture, the batcher restarts.

This code was written for SadConsole; I tried to clean this up as much as possible to make it generic. Hope it helps.

using Rectangle = SFML.Graphics.IntRect;
using Matrix = SFML.Graphics.Transform;
using System.Collections.Generic;
namespace SFML.Graphics
{
public class SpriteBatch
{
private Matrix _transform;
private BatchDrawCall _lastDrawCall = new BatchDrawCall();
private RenderTarget _target;
private RenderStates _state;
private int _maxIndex = 800;
public void Reset(RenderTarget target, RenderStates state, Matrix renderingTransform)
{
_transform = renderingTransform;
_lastDrawCall.VertIndex = 0;
_target = target;
_state = state;
_state.Transform *= renderingTransform;
}
private class BatchDrawCall
{
public Texture Texture;
public Vertex[] Verticies = new Vertex[1000];
public int VertIndex;
}
public unsafe void DrawQuad(Rectangle screenRect, Rectangle textCoords, Color color, Texture texture)
{
if (_lastDrawCall.Texture != texture && _lastDrawCall.Texture != null)
{
End();
_lastDrawCall.VertIndex = 0;
}
_lastDrawCall.Texture = texture;
if (_lastDrawCall.VertIndex >= _maxIndex)
{
global::System.Array.Resize(ref _lastDrawCall.Verticies, _lastDrawCall.Verticies.Length + _lastDrawCall.Verticies.Length / 2);
_maxIndex = _lastDrawCall.Verticies.Length - 200;
}
fixed (Vertex* verts = _lastDrawCall.Verticies)
{
verts[_lastDrawCall.VertIndex].Position.X = screenRect.Left;
verts[_lastDrawCall.VertIndex].Position.Y = screenRect.Top;
verts[_lastDrawCall.VertIndex].TexCoords.X = textCoords.Left;
verts[_lastDrawCall.VertIndex].TexCoords.Y = textCoords.Top;
verts[_lastDrawCall.VertIndex].Color = color;
_lastDrawCall.VertIndex++;
verts[_lastDrawCall.VertIndex].Position.X = screenRect.Width;
verts[_lastDrawCall.VertIndex].Position.Y = screenRect.Top;
verts[_lastDrawCall.VertIndex].TexCoords.X = textCoords.Width;
verts[_lastDrawCall.VertIndex].TexCoords.Y = textCoords.Top;
verts[_lastDrawCall.VertIndex].Color = color;
_lastDrawCall.VertIndex++;
verts[_lastDrawCall.VertIndex].Position.X = screenRect.Width;
verts[_lastDrawCall.VertIndex].Position.Y = screenRect.Height;
verts[_lastDrawCall.VertIndex].TexCoords.X = textCoords.Width;
verts[_lastDrawCall.VertIndex].TexCoords.Y = textCoords.Height;
verts[_lastDrawCall.VertIndex].Color = color;
_lastDrawCall.VertIndex++;
verts[_lastDrawCall.VertIndex].Position.X = screenRect.Left;
verts[_lastDrawCall.VertIndex].Position.Y = screenRect.Height;
verts[_lastDrawCall.VertIndex].TexCoords.X = textCoords.Left;
verts[_lastDrawCall.VertIndex].TexCoords.Y = textCoords.Height;
verts[_lastDrawCall.VertIndex].Color = color;
_lastDrawCall.VertIndex++;
}
}
public void End()
{
if (lastDrawCall.VertIndex != 0)
{
state.Texture = lastDrawCall.Texture;
target.Draw(lastDrawCall.Verticies, 0, (uint)(lastDrawCall.VertIndex), PrimitiveType.Quads, state);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment