this repo has no description

Compare changes

Choose any two refs to compare.

-11
Peridot.sln
··· 20 20 .editorconfig = .editorconfig 21 21 EndProjectSection 22 22 EndProject 23 - Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{ACE2E1B3-D8BA-4BF8-B188-C5CB1C948075}" 24 - EndProject 25 - Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Peridot.Sample2", "src\Peridot.Sample2\Peridot.Sample2.csproj", "{B65C90A8-64E6-47B7-A392-53DF086F622A}" 26 - EndProject 27 23 Global 28 24 GlobalSection(SolutionConfigurationPlatforms) = preSolution 29 25 Debug|Any CPU = Debug|Any CPU ··· 42 38 {2B5DA501-2051-4045-A3C7-B5E9C74DE7ED}.Debug|Any CPU.Build.0 = Debug|Any CPU 43 39 {2B5DA501-2051-4045-A3C7-B5E9C74DE7ED}.Release|Any CPU.ActiveCfg = Release|Any CPU 44 40 {2B5DA501-2051-4045-A3C7-B5E9C74DE7ED}.Release|Any CPU.Build.0 = Release|Any CPU 45 - {B65C90A8-64E6-47B7-A392-53DF086F622A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 46 - {B65C90A8-64E6-47B7-A392-53DF086F622A}.Debug|Any CPU.Build.0 = Debug|Any CPU 47 - {B65C90A8-64E6-47B7-A392-53DF086F622A}.Release|Any CPU.ActiveCfg = Release|Any CPU 48 - {B65C90A8-64E6-47B7-A392-53DF086F622A}.Release|Any CPU.Build.0 = Release|Any CPU 49 41 EndGlobalSection 50 42 GlobalSection(SolutionProperties) = preSolution 51 43 HideSolutionNode = FALSE 52 44 EndGlobalSection 53 45 GlobalSection(ExtensibilityGlobals) = postSolution 54 46 SolutionGuid = {283E4FA4-87D7-4804-B948-D717D1157195} 55 - EndGlobalSection 56 - GlobalSection(NestedProjects) = preSolution 57 - {B65C90A8-64E6-47B7-A392-53DF086F622A} = {ACE2E1B3-D8BA-4BF8-B188-C5CB1C948075} 58 47 EndGlobalSection 59 48 EndGlobal
+3
README.md
··· 1 1 # peridot 2 2 A generic SpriteBatch implementation with Veldrid support. 3 + 4 + ## Peridot.Sample2 5 + [![Watch the video](https://i.imgur.com/tiO2vWA.png)](https://youtu.be/7LPDZkyRmhs)
+65
src/Peridot/BatchGroup.cs
··· 1 + ๏ปฟ// Copyright (c) 2021 ezequias2d <ezequiasmoises@gmail.com> and the Peridot contributors 2 + // This code is licensed under MIT license (see LICENSE for details) 3 + 4 + namespace Peridot; 5 + 6 + public class BatchGroup 7 + { 8 + private BatchItem[] _items; 9 + 10 + public BatchGroup() 11 + { 12 + _items = new BatchItem[64]; 13 + } 14 + public int Count { get; private set; } 15 + 16 + public ref BatchItem Add() 17 + { 18 + if (Count >= _items.Length) 19 + { 20 + var lastSize = _items.Length; 21 + var newSize = (lastSize + lastSize / 2 + 63) & (~63); 22 + Array.Resize(ref _items, newSize); 23 + } 24 + 25 + return ref _items[Count++]; 26 + } 27 + 28 + public void Clear() 29 + { 30 + Count = 0; 31 + } 32 + 33 + public ReadOnlySpan<BatchItem> GetSpan() => new ReadOnlySpan<BatchItem>(_items, 0, Count); 34 + 35 + public Enumerator GetEnumerator() => new(_items, Count); 36 + 37 + public struct Enumerator 38 + { 39 + private readonly BatchItem[] _items; 40 + private readonly int _count; 41 + private int _index; 42 + 43 + internal Enumerator(BatchItem[] items, int count) 44 + { 45 + _items = items; 46 + _count = count; 47 + _index = -1; 48 + } 49 + 50 + public BatchItem Current => _items[_index]; 51 + 52 + public bool MoveNext() 53 + { 54 + if (_index >= _count) 55 + return false; 56 + _index++; 57 + return true; 58 + } 59 + 60 + public void Reset() 61 + { 62 + _index = -1; 63 + } 64 + } 65 + }
+20 -133
src/Peridot/Batcher.cs
··· 1 - ๏ปฟusing System.Diagnostics; 2 - using System.Diagnostics.CodeAnalysis; 3 - // Copyright (c) 2021 ezequias2d <ezequiasmoises@gmail.com> and the Peridot contributors 1 + ๏ปฟ// Copyright (c) 2021 ezequias2d <ezequiasmoises@gmail.com> and the Peridot contributors 4 2 // This code is licensed under MIT license (see LICENSE for details) 5 3 6 4 namespace Peridot; 7 5 8 6 public class Batcher<TTexture> where TTexture : notnull 9 7 { 10 - private TTexture[] _textures; 11 - private BatchItem[] _items; 12 - private int _count; 13 - private Slice[] _slices; 14 - private int _slicesCount; 8 + private Stack<BatchGroup> _batchGroups; 9 + private Dictionary<TTexture, BatchGroup> _batchItems; 15 10 16 11 public Batcher() 17 12 { 18 - _slices = new Slice[8]; 19 - _textures = new TTexture[8]; 20 - _items = new BatchItem[8]; 21 - _count = 0; 22 - _slicesCount = 0; 13 + _batchItems = new(); 14 + _batchGroups = new(); 23 15 } 24 16 25 17 public ref BatchItem Add(TTexture texture) 26 18 { 27 - if (_count >= _items.Length) 19 + if (!_batchItems.TryGetValue(texture, out var group)) 28 20 { 29 - var lastSize = _items.Length; 30 - var newSize = (lastSize + lastSize / 2 + 7) & (~7); 31 - Array.Resize(ref _items, newSize); 32 - Array.Resize(ref _textures, newSize); 21 + group = GetBatchGroup(); 22 + group.Clear(); 23 + _batchItems[texture] = group; 33 24 } 34 25 35 - var i = _count++; 36 - _textures[i] = texture; 37 - return ref _items[i]; 26 + return ref group.Add(); 38 27 } 39 28 40 29 public void Clear() 41 30 { 42 - Array.Clear(_items); 43 - Array.Clear(_textures); 44 - Array.Clear(_slices); 45 - 46 - _count = 0; 47 - _slicesCount = 0; 31 + foreach (var group in this) 32 + ReturnBatchGroup(group.Value); 33 + _batchItems.Clear(); 48 34 } 49 35 50 - public void Build(SortMode mode) 51 - { 52 - if (_count == 0) 53 - return; 54 - 55 - switch (mode) 56 - { 57 - case SortMode.FrontToBack: 58 - Array.Sort(_items, _textures, 0, _count, FrontToBackComparer.Instance); 59 - break; 60 - case SortMode.BackToFront: 61 - Array.Sort(_items, _textures, 0, _count, BackToFrontComparer.Instance); 62 - break; 63 - } 64 - 65 - TTexture currentTexture = _textures[0]; 36 + public Dictionary<TTexture, BatchGroup>.Enumerator GetEnumerator() => 37 + _batchItems.GetEnumerator(); 66 38 67 - int index = 0; 68 - int start = 0; 69 - _slicesCount = 0; 70 - do 71 - { 72 - TTexture texture = _textures[index]; 73 - if (!currentTexture.Equals(texture)) 74 - { 75 - if (_slicesCount >= _slices.Length) 76 - { 77 - var lastSize = _slices.Length; 78 - var newSize = (lastSize + lastSize / 2 + 7) & (~7); 79 - Array.Resize(ref _slices, newSize); 80 - } 81 - _slices[_slicesCount++] = new(currentTexture, start, index - start); 82 - Debug.Assert(index - start >= 0); 83 - start = index; 84 - currentTexture = texture; 85 - } 86 - index++; 87 - } 88 - while (index < _count); 89 - 90 - if (index - start != 0) 91 - { 92 - if (_slicesCount >= _slices.Length) 93 - { 94 - var lastSize = _slices.Length; 95 - var newSize = (lastSize + lastSize / 2 + 7) & (~7); 96 - Array.Resize(ref _slices, newSize); 97 - } 98 - _slices[_slicesCount++] = new(currentTexture, start, index - start); 99 - } 100 - int a = 0; 101 - } 102 - 103 - public ReadOnlySpan<BatchItem> Items => new ReadOnlySpan<BatchItem>(_items, 0, _count); 104 - public ReadOnlySpan<Slice> Slices => new ReadOnlySpan<Slice>(_slices, 0, _slicesCount); 105 - public TTexture GetSliceTexture(Slice slice) 39 + private BatchGroup GetBatchGroup() 106 40 { 107 - return _textures[slice.Start]; 108 - } 109 - 110 - private class FrontToBackComparer : IComparer<BatchItem> 111 - { 112 - public readonly static IComparer<BatchItem> Instance = new FrontToBackComparer(); 113 - private FrontToBackComparer() { } 114 - 115 - public int Compare(BatchItem x, BatchItem y) 116 - { 117 - return x.Location.Z.CompareTo(y.Location.Z); 118 - } 119 - } 120 - 121 - private class BackToFrontComparer : IComparer<BatchItem> 122 - { 123 - public readonly static IComparer<BatchItem> Instance = new BackToFrontComparer(); 124 - private BackToFrontComparer() { } 125 - public int Compare(BatchItem x, BatchItem y) 126 - { 127 - return y.Location.Z.CompareTo(x.Location.Z); 128 - } 41 + if (!_batchGroups.TryPop(out var group)) 42 + group = new(); 43 + return group; 129 44 } 130 45 131 - public struct Slice : IEquatable<Slice> 132 - { 133 - public Slice(TTexture texture, int start, int length) 134 - { 135 - Texture = texture; 136 - Start = start; 137 - Length = length; 138 - } 139 - 140 - public readonly TTexture Texture; 141 - public readonly int Start; 142 - public readonly int Length; 143 - 144 - public override bool Equals([NotNullWhen(true)] object? obj) 145 - { 146 - return base.Equals(obj); 147 - } 148 - 149 - public override int GetHashCode() 150 - { 151 - return HashCode.Combine(Start, Length); 152 - } 153 - 154 - public bool Equals(Batcher<TTexture>.Slice other) 155 - { 156 - return Start == other.Start && 157 - Length == other.Length; 158 - } 159 - } 46 + private void ReturnBatchGroup(BatchGroup group) => _batchGroups.Push(group); 160 47 }
+1 -5
src/Peridot/ColorB.Static.cs
··· 232 232 #endregion 233 233 #region Colors 234 234 /// <summary> 235 - /// Red (255, 0, 0, 255) 235 + /// Red (1, 0, 0, 1) 236 236 /// </summary> 237 237 public static readonly ColorB Red = new(255, 0, 0, 255); 238 - 239 - /// <summary> 240 - /// Transparent (0, 0, 0, 0) 241 - /// </summary> 242 238 public static readonly ColorB Transparent = new(0, 0, 0, 0); 243 239 244 240 /// <summary>
+2 -3
src/Peridot/ColorB.cs
··· 59 59 /// </summary> 60 60 public byte A; 61 61 62 - /// <inheritdoc/> 63 62 public bool Equals(ColorB other) 64 63 { 65 64 return (R, G, B, A) == (other.R, other.G, other.B, other.A); 66 65 } 67 66 68 67 /// <inheritdoc/> 69 - public override bool Equals(object? obj) 68 + public override bool Equals(object obj) 70 69 { 71 - return obj != null && obj is ColorB other && Equals(other); 70 + return obj is ColorB other && Equals(other); 72 71 } 73 72 74 73 /// <inheritdoc/>
+1 -20
src/Peridot/ColorF.Static.cs
··· 23 23 public static implicit operator ColorF(Vector4 color) => new(color); 24 24 25 25 /// <summary> 26 - /// Cast a <see cref="ColorF"/> to <see cref="Color"/>. 26 + /// Cast a <see cref="Vector4"/> to <see cref="ColorF"/>. 27 27 /// </summary> 28 28 /// <param name="color"></param> 29 29 public static implicit operator Color(ColorF color) 30 30 { 31 31 color = Vector4.Clamp(color, Vector4.Zero, Vector4.One) * 255f; 32 32 return Color.FromArgb((byte)color.A, (byte)color.R, (byte)color.G, (byte)color.B); 33 - } 34 - 35 - /// <summary> 36 - /// Cast a <see cref="Vector4"/> to <see cref="ColorF"/>. 37 - /// </summary> 38 - /// <param name="color"></param> 39 - public static implicit operator ColorF(Color color) 40 - { 41 - return (ColorF)Vector4.Clamp(new Vector4(color.R, color.G, color.B, color.A) * (1f / 255f), Vector4.Zero, Vector4.One); 42 33 } 43 34 #endregion 44 35 #region Math 45 - 46 - public static ColorF Blend(ColorF dst, ColorF src) 47 - { 48 - var dstA = dst.A; 49 - var srcA = src.A; 50 - var res = dst * (1 - srcA) + src * srcA; 51 - res.A = dstA * (1 - srcA) + srcA; 52 - return res; 53 - } 54 - 55 36 /// <summary> 56 37 /// Negates the specified color. 57 38 /// </summary>
+2 -25
src/Peridot/ColorF.cs
··· 42 42 } 43 43 44 44 /// <summary> 45 - /// Constructs a new gray color. 46 - /// </summary> 47 - /// <param name="grayColor"></param> 48 - public ColorF(float grayColor) 49 - { 50 - m_rgba = new Vector4(grayColor, grayColor, grayColor, 1f); 51 - } 52 - 53 - /// <summary> 54 - /// Constructs a new gray color. 55 - /// </summary> 56 - /// <param name="grayColor"></param> 57 - /// <param name="alpha"></param> 58 - public ColorF(float grayColor, float alpha) 59 - { 60 - m_rgba = new Vector4(grayColor, grayColor, grayColor, alpha); 61 - } 62 - 63 - /// <summary> 64 45 /// The red color component. 65 46 /// </summary> 66 47 public float R { get => m_rgba.X; set => m_rgba.X = value; } ··· 80 61 /// </summary> 81 62 public float A { get => m_rgba.W; set => m_rgba.W = value; } 82 63 83 - /// <summary> 84 - /// Gets or sets components RGBA as a <see cref="Vector4"/>. 85 - /// </summary> 86 64 public Vector4 AsVector { get => m_rgba; set => m_rgba = value; } 87 65 88 - /// <inheritdoc/> 89 66 public bool Equals(ColorF other) 90 67 { 91 68 return m_rgba.Equals(other.m_rgba); 92 69 } 93 70 94 71 /// <inheritdoc/> 95 - public override bool Equals(object? obj) 72 + public override bool Equals(object obj) 96 73 { 97 - return obj != null && obj is ColorF other && Equals(other); 74 + return obj is ColorF other && Equals(other); 98 75 } 99 76 100 77 /// <inheritdoc/>
+29 -43
src/Peridot/IPeridot.cs
··· 1 - using System.Drawing; 2 1 namespace Peridot; 3 2 4 3 /// <summary> ··· 6 5 /// </summary> 7 6 public interface IPeridot 8 7 { 9 - /// <summary> 10 - /// Creates a new image. 11 - /// </summary> 12 - /// <param name="description">The description of image.</param> 13 - /// <returns>A new image.</returns> 14 - public Image CreateImage(ImageDescription description); 15 - 16 - /// <summary> 17 - /// Updates a portion of Image with new data. 18 - /// </summary> 19 - /// <param name="image">The image to update.</param> 20 - /// <param name="source">An span with data to upload.</param> 21 - /// <param name="x">The minimum X value of the updated region.</param> 22 - /// <param name="y">The minimum Y value of the updated region.</param> 23 - /// <param name="width">The width of the updated region.</param> 24 - /// <param name="height">The height of the updated region.</param> 25 - /// <typeparam name="T">Type of data updated.</typeparam> 26 - public void UpdateImage<T>(Image image, ReadOnlySpan<T> source, uint x, uint y, uint width, uint height) where T : unmanaged; 8 + /// <summary> 9 + /// Creates a new image. 10 + /// </summary> 11 + /// <param name="description">The description of image.</param> 12 + /// <returns>A new image.</returns> 13 + public Image CreateImage(ImageDescription description); 27 14 28 - /// <summary> 29 - /// Copy a part of an image to another. 30 - /// </summary> 31 - /// <param name="source"></param> 32 - /// <param name="destination"></param> 33 - /// <param name="sx"></param> 34 - /// <param name="sy"></param> 35 - /// <param name="dx"></param> 36 - /// <param name="dy"></param> 37 - /// <param name="width"></param> 38 - /// <param name="height"></param> 39 - public void CopyImage(Image source, Image destination, uint sx, uint sy, uint dx, uint dy, uint width, uint height); 15 + /// <summary> 16 + /// Updates a portion of Image with new data. 17 + /// </summary> 18 + /// <param name="image">The image to update.</param> 19 + /// <param name="source">An span with data to upload.</param> 20 + /// <param name="x">The minimum X value of the updated region.</param> 21 + /// <param name="y">The minimum Y value of the updated region.</param> 22 + /// <param name="width">The width of the updated region.</param> 23 + /// <param name="height">The height of the updated region.</param> 24 + /// <typeparam name="T">Type of data updated.</typeparam> 25 + public void UpdateImage<T>(Image image, ReadOnlySpan<T> source, uint x, uint y, uint width, uint height) where T : unmanaged; 40 26 } 41 27 42 28 /// <summary> ··· 44 30 /// </summary> 45 31 public interface IPeridot<TSpriteBatchDescripton> : IPeridot 46 32 { 47 - /// <summary> 48 - /// Creates a new sprite batch. 49 - /// </summary> 50 - /// <param name="description">The description of sprite batch.</param> 51 - /// <returns>A new sprite batch.</returns> 52 - public ISpriteBatch CreateSpriteBatch(TSpriteBatchDescripton description); 33 + /// <summary> 34 + /// Creates a new sprite batch. 35 + /// </summary> 36 + /// <param name="description">The description of sprite batch.</param> 37 + /// <returns>A new sprite batch.</returns> 38 + public ISpriteBatch CreateSpriteBatch(TSpriteBatchDescripton description); 53 39 } 54 40 55 41 /// <summary> ··· 57 43 /// </summary> 58 44 public interface IPeridot<TImage, TSpriteBatchDescripton> : IPeridot<TSpriteBatchDescripton> 59 45 { 60 - /// <summary> 61 - /// Creates a new sprite batch. 62 - /// </summary> 63 - /// <param name="description">The description of sprite batch.</param> 64 - /// <returns>A new sprite batch.</returns> 65 - public new ISpriteBatch<TImage> CreateSpriteBatch(TSpriteBatchDescripton description); 46 + /// <summary> 47 + /// Creates a new sprite batch. 48 + /// </summary> 49 + /// <param name="description">The description of sprite batch.</param> 50 + /// <returns>A new sprite batch.</returns> 51 + public new ISpriteBatch<TImage> CreateSpriteBatch(TSpriteBatchDescripton description); 66 52 }
+1 -13
src/Peridot/Image.cs
··· 16 16 public bool IsDisposed { get; } 17 17 18 18 /// <summary> 19 - /// Image size. 19 + /// The total size of the texture. 20 20 /// </summary> 21 21 public Size Size { get; } 22 - 23 - /// <summary> 24 - /// Pixel format. 25 - /// </summary> 26 - /// <value></value> 27 22 public PixelFormat Format { get; } 28 23 29 - /// <summary> 30 - /// Image width. 31 - /// </summary> 32 24 public int Width => Size.Width; 33 - 34 - /// <summary> 35 - /// Image height. 36 - /// </summary> 37 25 public int Height => Size.Height; 38 26 }
-3
src/Peridot/PixelFormat.cs
··· 5 5 /// </summary> 6 6 public enum PixelFormat 7 7 { 8 - /// <summary> 9 - /// Undefined format. 10 - /// </summary> 11 8 Undefined, 12 9 /// <summary> 13 10 /// One-channel, byte storage.
-20
src/Peridot/SortMode.cs
··· 1 - namespace Peridot; 2 - 3 - /// <summary> 4 - /// Defines sort mode of a <see cref="ISpriteBatch"/>. 5 - /// </summary> 6 - public enum SortMode 7 - { 8 - /// <summary> 9 - /// Sprites are draw in call sequence. 10 - /// </summary> 11 - None, 12 - /// <summary> 13 - /// Sprites are sorted by depth in back-to-front order before drawing. 14 - /// </summary> 15 - BackToFront, 16 - /// <summary> 17 - /// Sprites are sorted by depth in front-to-back order before drawing. 18 - /// </summary> 19 - FrontToBack 20 - }
+645 -644
src/Peridot/SpriteBatch.cs
··· 10 10 /// A class for drawing sprites in one or more optimized batches. 11 11 /// </summary> 12 12 /// <typeparam name="TImage">The image type to renderer.</typeparam> 13 - public abstract class SpriteBatch<TImage> : ISpriteBatch<TImage> where TImage : notnull 13 + public abstract class SpriteBatch<TImage> : ISpriteBatch<TImage> 14 14 { 15 - /// <summary> 16 - /// The batcher with all entities to renderer. 17 - /// </summary> 18 - protected readonly Batcher<TImage> m_batcher; 15 + /// <summary> 16 + /// The batcher with all entities to renderer. 17 + /// </summary> 18 + protected readonly Batcher<TImage> m_batcher; 19 19 20 - protected readonly Image m_whiteImage; 20 + protected readonly Image m_whiteImage; 21 21 22 - private bool m_beginCalled; 22 + private bool m_beginCalled; 23 23 24 - /// <summary> 25 - /// Creates a new <see cref="SpriteBatch{TImage}"/>. 26 - /// </summary> 27 - public SpriteBatch(Image whiteImage) 28 - { 29 - m_batcher = new(); 30 - m_whiteImage = whiteImage; 31 - m_beginCalled = false; 32 - IsDisposed = false; 33 - ResetScissor(); 34 - } 24 + /// <summary> 25 + /// Creates a new <see cref="SpriteBatch{TImage}"/>. 26 + /// </summary> 27 + public SpriteBatch(Image whiteImage) 28 + { 29 + m_batcher = new(); 30 + m_whiteImage = whiteImage; 31 + m_beginCalled = false; 32 + IsDisposed = false; 33 + ResetScissor(); 34 + } 35 35 36 - /// <summary> 37 - /// Deconstructor of <see cref="SpriteBatch{TImage}"/>. 38 - /// </summary> 39 - ~SpriteBatch() 40 - { 41 - CoreDispose(false); 42 - } 36 + /// <summary> 37 + /// Deconstructor of <see cref="SpriteBatch{TImage}"/>. 38 + /// </summary> 39 + ~SpriteBatch() 40 + { 41 + CoreDispose(false); 42 + } 43 43 44 - /// <summary> 45 - /// The view matrix to use to renderer. 46 - /// </summary> 47 - public Matrix4x4 ViewMatrix { get; set; } 44 + /// <summary> 45 + /// The view matrix to use to renderer. 46 + /// </summary> 47 + public Matrix4x4 ViewMatrix { get; set; } 48 48 49 - /// <inheritdoc/> 50 - public bool IsDisposed { get; protected set; } 49 + /// <inheritdoc/> 50 + public bool IsDisposed { get; protected set; } 51 51 52 - /// <inheritdoc/> 53 - public RectangleF Scissor { get; set; } 52 + /// <inheritdoc/> 53 + public RectangleF Scissor { get; set; } 54 54 55 - /// <summary> 56 - /// Begins the sprite branch. 57 - /// </summary> 58 - /// <exception cref="InvalidOperationException">Thrown if <see cref="Begin"/> is called next time without previous <see cref="End"/>.</exception> 59 - public void Begin() 60 - { 61 - if (m_beginCalled) 62 - throw new InvalidOperationException("Begin cannot be called again until End has been successfully called."); 55 + /// <summary> 56 + /// Begins the sprite branch. 57 + /// </summary> 58 + /// <exception cref="InvalidOperationException">Thrown if <see cref="Begin"/> is called next time without previous <see cref="End"/>.</exception> 59 + public void Begin() 60 + { 61 + if (m_beginCalled) 62 + throw new InvalidOperationException("Begin cannot be called again until End has been successfully called."); 63 63 64 - ViewMatrix = Matrix4x4.Identity; 65 - m_beginCalled = true; 66 - m_batcher.Clear(); 67 - } 64 + ViewMatrix = Matrix4x4.Identity; 65 + m_beginCalled = true; 66 + m_batcher.Clear(); 67 + } 68 68 69 - /// <summary> 70 - /// Flushes all batched text and sprites to the screen. 71 - /// </summary> 72 - /// <exception cref="InvalidOperationException">This command should be called after <see cref="Begin"/> and drawing commands.</exception> 73 - public void End() 74 - { 75 - if (!m_beginCalled) 76 - throw new InvalidOperationException("Begin must be called before calling End."); 69 + /// <summary> 70 + /// Flushes all batched text and sprites to the screen. 71 + /// </summary> 72 + /// <exception cref="InvalidOperationException">This command should be called after <see cref="Begin"/> and drawing commands.</exception> 73 + public void End() 74 + { 75 + if (!m_beginCalled) 76 + throw new InvalidOperationException("Begin must be called before calling End."); 77 77 78 - m_beginCalled = false; 79 - } 78 + m_beginCalled = false; 79 + } 80 80 81 - /// <inheritdoc/> 82 - public void Draw(Image image, RectangleF destinationRectangle, RectangleF sourceRectangle, Color color, float rotation, Vector2 origin, SpriteOptions options, float layerDepth) => 83 - Draw(GetHandle(image), destinationRectangle, sourceRectangle, color, rotation, origin, options, layerDepth); 81 + /// <inheritdoc/> 82 + public void Draw(Image image, RectangleF destinationRectangle, RectangleF sourceRectangle, Color color, float rotation, Vector2 origin, SpriteOptions options, float layerDepth) => 83 + Draw(GetHandle(image), destinationRectangle, sourceRectangle, color, rotation, origin, options, layerDepth); 84 84 85 - /// <inheritdoc/> 86 - public void Draw(Image image, Vector2 position, RectangleF sourceRectangle, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteOptions options, float layerDepth) => 87 - Draw(GetHandle(image), position, sourceRectangle, color, rotation, origin, scale, options, layerDepth); 85 + /// <inheritdoc/> 86 + public void Draw(Image image, Vector2 position, RectangleF sourceRectangle, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteOptions options, float layerDepth) => 87 + Draw(GetHandle(image), position, sourceRectangle, color, rotation, origin, scale, options, layerDepth); 88 88 89 - /// <inheritdoc/> 90 - public void Draw(TImage image, RectangleF destinationRectangle, RectangleF sourceRectangle, Color color, float rotation, Vector2 origin, SpriteOptions options, float layerDepth) 91 - { 92 - CheckValid(image); 93 - ref var item = ref m_batcher.Add(image); 94 - var size = GetSize(image); 95 - var vsize = new Vector2(size.Width, size.Height); 89 + /// <inheritdoc/> 90 + public void Draw(TImage image, RectangleF destinationRectangle, RectangleF sourceRectangle, Color color, float rotation, Vector2 origin, SpriteOptions options, float layerDepth) 91 + { 92 + CheckValid(image); 93 + ref var item = ref m_batcher.Add(image); 94 + var size = GetSize(image); 95 + var vsize = new Vector2(size.Width, size.Height); 96 96 97 - item = new(vsize, destinationRectangle, sourceRectangle, color, rotation, origin, layerDepth, Transform(Scissor, ViewMatrix), options); 98 - } 97 + item = new(vsize, destinationRectangle, sourceRectangle, color, rotation, origin, layerDepth, Transform(Scissor, ViewMatrix), options); 98 + } 99 99 100 - /// <inheritdoc/> 101 - public void Draw(TImage image, Vector2 position, RectangleF sourceRectangle, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteOptions options, float layerDepth) 102 - { 103 - CheckValid(image); 104 - ref var item = ref m_batcher.Add(image); 105 - var size = GetSize(image); 106 - var vsize = new Vector2(size.Width, size.Height); 100 + /// <inheritdoc/> 101 + public void Draw(TImage image, Vector2 position, RectangleF sourceRectangle, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteOptions options, float layerDepth) 102 + { 103 + CheckValid(image); 104 + ref var item = ref m_batcher.Add(image); 105 + var size = GetSize(image); 106 + var vsize = new Vector2(size.Width, size.Height); 107 107 108 - item = new(vsize, position, sourceRectangle, color, rotation, origin, scale, layerDepth, Transform(Scissor, ViewMatrix), options); 109 - } 108 + item = new(vsize, position, sourceRectangle, color, rotation, origin, scale, layerDepth, Transform(Scissor, ViewMatrix), options); 109 + } 110 110 111 - /// <inheritdoc/> 112 - public void Dispose() 113 - { 114 - CoreDispose(true); 115 - GC.SuppressFinalize(this); 116 - } 111 + /// <inheritdoc/> 112 + public void Dispose() 113 + { 114 + CoreDispose(true); 115 + GC.SuppressFinalize(this); 116 + } 117 117 118 - private void CoreDispose(bool disposing) 119 - { 120 - if (IsDisposed) 121 - return; 122 - IsDisposed = true; 118 + private void CoreDispose(bool disposing) 119 + { 120 + if (IsDisposed) 121 + return; 122 + IsDisposed = true; 123 123 124 - Dispose(disposing); 125 - } 124 + Dispose(disposing); 125 + } 126 126 127 - /// <summary> 128 - /// Disposes resources. 129 - /// </summary> 130 - /// <param name="disposing">If called by <see cref="Dispose()"/></param> 131 - protected abstract void Dispose(bool disposing); 127 + /// <summary> 128 + /// Disposes resources. 129 + /// </summary> 130 + /// <param name="disposing">If called by <see cref="Dispose()"/></param> 131 + protected abstract void Dispose(bool disposing); 132 132 133 - private void CheckValid(TImage image) 134 - { 135 - if (image == null) 136 - throw new ArgumentNullException(nameof(image)); 137 - if (!m_beginCalled) 138 - throw new InvalidOperationException("Draw was called, but Begin has not yet been called. Begin must be called successfully before you can call Draw."); 139 - } 133 + private void CheckValid(TImage image) 134 + { 135 + if (image == null) 136 + throw new ArgumentNullException(nameof(image)); 137 + if (!m_beginCalled) 138 + throw new InvalidOperationException("Draw was called, but Begin has not yet been called. Begin must be called successfully before you can call Draw."); 139 + } 140 140 141 - /// <inheritdoc/> 142 - public void ResetScissor() 143 - { 144 - const float v = 1 << 23; 145 - const float s = -(1 << 22); 146 - Scissor = new RectangleF(s, s, v, v); 147 - } 141 + /// <inheritdoc/> 142 + public void ResetScissor() 143 + { 144 + const float v = 1 << 23; 145 + const float s = -(1 << 22); 146 + Scissor = new RectangleF(s, s, v, v); 147 + } 148 148 149 - /// <inheritdoc/> 150 - public void IntersectScissor(RectangleF clip) 151 - { 152 - var scissor = Scissor; 153 - scissor.Intersect(clip); 154 - Scissor = scissor; 155 - } 149 + /// <inheritdoc/> 150 + public void IntersectScissor(RectangleF clip) 151 + { 152 + var scissor = Scissor; 153 + scissor.Intersect(clip); 154 + Scissor = scissor; 155 + } 156 156 157 - private static RectangleF Transform(RectangleF rect, Matrix4x4 matrix) 158 - { 159 - var pos = Vector4.Transform(new Vector4(rect.X, rect.Y, 0, 1), matrix); 160 - var size = Vector4.Transform(new Vector4(rect.X + rect.Width, rect.Y + rect.Height, 0, 1), matrix); 161 - return new(pos.X, pos.Y, size.X - pos.X, size.Y - pos.Y); 162 - } 157 + private static RectangleF Transform(RectangleF rect, Matrix4x4 matrix) 158 + { 159 + var pos = Vector4.Transform(new Vector4(rect.X, rect.Y, 0, 1), matrix); 160 + var size = Vector4.Transform(new Vector4(rect.X + rect.Width, rect.Y + rect.Height, 0, 1), matrix); 161 + return new(pos.X, pos.Y, size.X - pos.X, size.Y - pos.Y); 162 + } 163 163 164 - #region ISpriteBatch 165 - /// <inheritdoc/> 166 - public void Draw(Image image, 167 - RectangleF destinationRectangle, 168 - RectangleF sourceRectangle, 169 - Color color, 170 - float rotation, 171 - Vector2 origin, 172 - float layerDepth) 173 - { 174 - Draw(image, destinationRectangle, sourceRectangle, color, rotation, origin, SpriteOptions.None, layerDepth); 175 - } 164 + #region ISpriteBatch 165 + /// <inheritdoc/> 166 + public void Draw(Image image, 167 + RectangleF destinationRectangle, 168 + RectangleF sourceRectangle, 169 + Color color, 170 + float rotation, 171 + Vector2 origin, 172 + float layerDepth) 173 + { 174 + Draw(image, destinationRectangle, sourceRectangle, color, rotation, origin, SpriteOptions.None, layerDepth); 175 + } 176 176 177 - /// <inheritdoc/> 178 - public void Draw(Image image, 179 - Vector2 position, 180 - RectangleF sourceRectangle, 181 - Color color, 182 - float rotation, 183 - Vector2 origin, 184 - Vector2 scale, 185 - float layerDepth) 186 - { 187 - Draw(image, position, sourceRectangle, color, rotation, origin, scale, SpriteOptions.None, layerDepth); 188 - } 177 + /// <inheritdoc/> 178 + public void Draw(Image image, 179 + Vector2 position, 180 + RectangleF sourceRectangle, 181 + Color color, 182 + float rotation, 183 + Vector2 origin, 184 + Vector2 scale, 185 + float layerDepth) 186 + { 187 + Draw(image, position, sourceRectangle, color, rotation, origin, scale, SpriteOptions.None, layerDepth); 188 + } 189 189 190 - /// <inheritdoc/> 191 - public void Draw(Image image, 192 - RectangleF destinationRectangle, 193 - RectangleF? sourceRectangle, 194 - Color color, 195 - float rotation, 196 - Vector2 origin, 197 - SpriteOptions options, 198 - float layerDepth) 199 - { 200 - var srcRect = sourceRectangle ?? new(0, 0, image.Width, image.Height); 201 - Draw(image, destinationRectangle, srcRect, color, rotation, origin, options, layerDepth); 202 - } 190 + /// <inheritdoc/> 191 + public void Draw(Image image, 192 + RectangleF destinationRectangle, 193 + RectangleF? sourceRectangle, 194 + Color color, 195 + float rotation, 196 + Vector2 origin, 197 + SpriteOptions options, 198 + float layerDepth) 199 + { 200 + var srcRect = sourceRectangle ?? new(0, 0, image.Width, image.Height); 201 + Draw(image, destinationRectangle, srcRect, color, rotation, origin, options, layerDepth); 202 + } 203 203 204 - /// <inheritdoc/> 205 - public void Draw(Image image, 206 - RectangleF destinationRectangle, 207 - RectangleF? sourceRectangle, 208 - Color color, 209 - float rotation, 210 - Vector2 origin, 211 - float layerDepth) 212 - { 213 - Draw(image, destinationRectangle, sourceRectangle, color, rotation, origin, SpriteOptions.None, layerDepth); 214 - } 204 + /// <inheritdoc/> 205 + public void Draw(Image image, 206 + RectangleF destinationRectangle, 207 + RectangleF? sourceRectangle, 208 + Color color, 209 + float rotation, 210 + Vector2 origin, 211 + float layerDepth) 212 + { 213 + Draw(image, destinationRectangle, sourceRectangle, color, rotation, origin, SpriteOptions.None, layerDepth); 214 + } 215 215 216 - /// <inheritdoc/> 217 - public void Draw(Image image, 218 - Vector2 position, 219 - RectangleF? sourceRectangle, 220 - Color color, 221 - float rotation, 222 - Vector2 origin, 223 - Vector2 scale, 224 - SpriteOptions options, 225 - float layerDepth) 226 - { 227 - Draw(image: image, 228 - position: position, 229 - sourceRectangle: sourceRectangle ?? new() 230 - { 231 - X = 0, 232 - Y = 0, 233 - Width = image.Width, 234 - Height = image.Height, 235 - }, 236 - color: color, 237 - rotation: rotation, 238 - origin: origin, 239 - scale: scale, 240 - options: options, 241 - layerDepth: layerDepth); 242 - } 216 + /// <inheritdoc/> 217 + public void Draw(Image image, 218 + Vector2 position, 219 + RectangleF? sourceRectangle, 220 + Color color, 221 + float rotation, 222 + Vector2 origin, 223 + Vector2 scale, 224 + SpriteOptions options, 225 + float layerDepth) 226 + { 227 + Draw(image: image, 228 + position: position, 229 + sourceRectangle: sourceRectangle ?? new() 230 + { 231 + X = 0, 232 + Y = 0, 233 + Width = image.Width, 234 + Height = image.Height, 235 + }, 236 + color: color, 237 + rotation: rotation, 238 + origin: origin, 239 + scale: scale, 240 + options: options, 241 + layerDepth: layerDepth); 242 + } 243 243 244 - /// <inheritdoc/> 245 - public void Draw(Image image, 246 - Vector2 position, 247 - RectangleF? sourceRectangle, 248 - Color color, 249 - float rotation, 250 - Vector2 origin, 251 - Vector2 scale, 252 - float layerDepth) 253 - { 254 - Draw(image: image, 255 - position: position, 256 - sourceRectangle: sourceRectangle, 257 - color: color, 258 - rotation: rotation, 259 - origin: origin, 260 - scale: scale, 261 - options: SpriteOptions.None, 262 - layerDepth: layerDepth); 263 - } 244 + /// <inheritdoc/> 245 + public void Draw(Image image, 246 + Vector2 position, 247 + RectangleF? sourceRectangle, 248 + Color color, 249 + float rotation, 250 + Vector2 origin, 251 + Vector2 scale, 252 + float layerDepth) 253 + { 254 + Draw(image: image, 255 + position: position, 256 + sourceRectangle: sourceRectangle, 257 + color: color, 258 + rotation: rotation, 259 + origin: origin, 260 + scale: scale, 261 + options: SpriteOptions.None, 262 + layerDepth: layerDepth); 263 + } 264 264 265 - /// <inheritdoc/> 266 - public void Draw(Image image, 267 - Vector2 position, 268 - RectangleF? sourceRectangle, 269 - Color color, 270 - float rotation, 271 - Vector2 origin, 272 - float scale, 273 - SpriteOptions options, 274 - float layerDepth) 275 - { 276 - Draw(image: image, 277 - position: position, 278 - sourceRectangle: sourceRectangle, 279 - color: color, 280 - rotation: rotation, 281 - origin: origin, 282 - scale: new Vector2(scale), 283 - options: options, 284 - layerDepth: layerDepth); 285 - } 265 + /// <inheritdoc/> 266 + public void Draw(Image image, 267 + Vector2 position, 268 + RectangleF? sourceRectangle, 269 + Color color, 270 + float rotation, 271 + Vector2 origin, 272 + float scale, 273 + SpriteOptions options, 274 + float layerDepth) 275 + { 276 + Draw(image: image, 277 + position: position, 278 + sourceRectangle: sourceRectangle, 279 + color: color, 280 + rotation: rotation, 281 + origin: origin, 282 + scale: new Vector2(scale), 283 + options: options, 284 + layerDepth: layerDepth); 285 + } 286 286 287 - /// <inheritdoc/> 288 - public void Draw(Image image, 289 - Vector2 position, 290 - RectangleF? sourceRectangle, 291 - Color color, 292 - float rotation, 293 - Vector2 origin, 294 - float scale, 295 - float layerDepth) 296 - { 297 - Draw(image: image, 298 - position: position, 299 - sourceRectangle: sourceRectangle, 300 - color: color, 301 - rotation: rotation, 302 - origin: origin, 303 - scale: scale, 304 - options: SpriteOptions.None, 305 - layerDepth: layerDepth); 306 - } 287 + /// <inheritdoc/> 288 + public void Draw(Image image, 289 + Vector2 position, 290 + RectangleF? sourceRectangle, 291 + Color color, 292 + float rotation, 293 + Vector2 origin, 294 + float scale, 295 + float layerDepth) 296 + { 297 + Draw(image: image, 298 + position: position, 299 + sourceRectangle: sourceRectangle, 300 + color: color, 301 + rotation: rotation, 302 + origin: origin, 303 + scale: scale, 304 + options: SpriteOptions.None, 305 + layerDepth: layerDepth); 306 + } 307 307 308 - /// <inheritdoc/> 309 - public void Draw(Image image, 310 - Vector2 position, 311 - RectangleF? sourceRectangle, 312 - Color color, 313 - SpriteOptions options, 314 - float layerDepth) 315 - { 316 - Draw(image: image, 317 - position: position, 318 - sourceRectangle: sourceRectangle, 319 - color: color, 320 - rotation: 0f, 321 - origin: default, 322 - scale: 1f, 323 - options: options, 324 - layerDepth: layerDepth); 325 - } 308 + /// <inheritdoc/> 309 + public void Draw(Image image, 310 + Vector2 position, 311 + RectangleF? sourceRectangle, 312 + Color color, 313 + SpriteOptions options, 314 + float layerDepth) 315 + { 316 + Draw(image: image, 317 + position: position, 318 + sourceRectangle: sourceRectangle, 319 + color: color, 320 + rotation: 0f, 321 + origin: default, 322 + scale: 0f, 323 + options: options, 324 + layerDepth: layerDepth); 325 + } 326 326 327 - /// <inheritdoc/> 328 - public void Draw(Image image, 329 - Vector2 position, 330 - RectangleF? sourceRectangle, 331 - Color color, 332 - float layerDepth) 333 - { 334 - Draw(image: image, 335 - position: position, 336 - sourceRectangle: sourceRectangle, 337 - color: color, 338 - options: SpriteOptions.None, 339 - layerDepth: layerDepth); 340 - } 327 + /// <inheritdoc/> 328 + public void Draw(Image image, 329 + Vector2 position, 330 + RectangleF? sourceRectangle, 331 + Color color, 332 + float layerDepth) 333 + { 334 + Draw(image: image, 335 + position: position, 336 + sourceRectangle: sourceRectangle, 337 + color: color, 338 + options: SpriteOptions.None, 339 + layerDepth: layerDepth); 340 + } 341 341 342 - /// <inheritdoc/> 343 - public void Draw(Image image, 344 - RectangleF destinationRectangle, 345 - RectangleF? sourceRectangle, 346 - Color color, 347 - SpriteOptions options, 348 - float layerDepth) 349 - { 350 - Draw(image: image, 351 - destinationRectangle: destinationRectangle, 352 - sourceRectangle: sourceRectangle, 353 - color: color, 354 - rotation: 0, 355 - origin: default, 356 - options: options, 357 - layerDepth: layerDepth); 358 - } 342 + /// <inheritdoc/> 343 + public void Draw(Image image, 344 + RectangleF destinationRectangle, 345 + RectangleF? sourceRectangle, 346 + Color color, 347 + SpriteOptions options, 348 + float layerDepth) 349 + { 350 + Draw(image: image, 351 + destinationRectangle: destinationRectangle, 352 + sourceRectangle: sourceRectangle, 353 + color: color, 354 + rotation: 0, 355 + origin: default, 356 + options: options, 357 + layerDepth: layerDepth); 358 + } 359 359 360 - /// <inheritdoc/> 361 - public void Draw(Image image, 362 - RectangleF destinationRectangle, 363 - RectangleF? sourceRectangle, 364 - Color color, 365 - float layerDepth) 366 - { 367 - Draw(image: image, 368 - destinationRectangle: destinationRectangle, 369 - sourceRectangle: sourceRectangle, 370 - color: color, 371 - options: SpriteOptions.None, 372 - layerDepth: layerDepth); 373 - } 360 + /// <inheritdoc/> 361 + public void Draw(Image image, 362 + RectangleF destinationRectangle, 363 + RectangleF? sourceRectangle, 364 + Color color, 365 + float layerDepth) 366 + { 367 + Draw(image: image, 368 + destinationRectangle: 369 + destinationRectangle, 370 + sourceRectangle: sourceRectangle, 371 + color: color, 372 + options: SpriteOptions.None, 373 + layerDepth: layerDepth); 374 + } 374 375 375 - /// <inheritdoc/> 376 - public void Draw(Image image, 377 - Vector2 position, 378 - Color color, 379 - SpriteOptions options, 380 - float layerDepth) 381 - { 382 - Draw(image: image, 383 - position: position, 384 - sourceRectangle: new Rectangle(default, image.Size), 385 - color: color, 386 - rotation: 0, 387 - origin: default, 388 - scale: Vector2.One, 389 - options: options, 390 - layerDepth: layerDepth); 391 - } 376 + /// <inheritdoc/> 377 + public void Draw(Image image, 378 + Vector2 position, 379 + Color color, 380 + SpriteOptions options, 381 + float layerDepth) 382 + { 383 + Draw(image: image, 384 + position: position, 385 + sourceRectangle: new Rectangle(default, image.Size), 386 + color: color, 387 + rotation: 0, 388 + origin: default, 389 + scale: default, 390 + options: options, 391 + layerDepth: layerDepth); 392 + } 392 393 393 - /// <inheritdoc/> 394 - public void Draw(Image image, 395 - Vector2 position, 396 - Color color, 397 - float layerDepth) 398 - { 399 - Draw(image: image, 400 - position: position, 401 - color: color, 402 - options: SpriteOptions.None, 403 - layerDepth: layerDepth); 404 - } 394 + /// <inheritdoc/> 395 + public void Draw(Image image, 396 + Vector2 position, 397 + Color color, 398 + float layerDepth) 399 + { 400 + Draw(image: image, 401 + position: position, 402 + color: color, 403 + options: SpriteOptions.None, 404 + layerDepth: layerDepth); 405 + } 405 406 406 - /// <inheritdoc/> 407 - public void Draw(Image image, 408 - RectangleF destinationRectangle, 409 - Color color, 410 - SpriteOptions options, 411 - float layerDepth) 412 - { 413 - Draw(image: image, 414 - destinationRectangle: destinationRectangle, 415 - sourceRectangle: new Rectangle(default, image.Size), 416 - color: color, 417 - rotation: 0, 418 - origin: default, 419 - options: options, 420 - layerDepth: layerDepth); 421 - } 407 + /// <inheritdoc/> 408 + public void Draw(Image image, 409 + RectangleF destinationRectangle, 410 + Color color, 411 + SpriteOptions options, 412 + float layerDepth) 413 + { 414 + Draw(image: image, 415 + destinationRectangle: destinationRectangle, 416 + sourceRectangle: new Rectangle(default, image.Size), 417 + color: color, 418 + rotation: 0, 419 + origin: default, 420 + options: options, 421 + layerDepth: layerDepth); 422 + } 422 423 423 - /// <inheritdoc/> 424 - public void Draw(Image image, 425 - RectangleF destinationRectangle, 426 - Color color, 427 - float layerDepth) 428 - { 429 - Draw(image: image, 430 - destinationRectangle: destinationRectangle, 431 - color: color, 432 - options: SpriteOptions.None, 433 - layerDepth: layerDepth); 434 - } 435 - #endregion 424 + /// <inheritdoc/> 425 + public void Draw(Image image, 426 + RectangleF destinationRectangle, 427 + Color color, 428 + float layerDepth) 429 + { 430 + Draw(image: image, 431 + destinationRectangle: destinationRectangle, 432 + color: color, 433 + options: SpriteOptions.None, 434 + layerDepth: layerDepth); 435 + } 436 + #endregion 436 437 437 - #region ISpriteBatch<TImage> 438 + #region ISpriteBatch<TImage> 438 439 439 - /// <inheritdoc/> 440 - public void Draw(TImage image, 441 - RectangleF destinationRectangle, 442 - RectangleF sourceRectangle, 443 - Color color, 444 - float rotation, 445 - Vector2 origin, 446 - float layerDepth) 447 - { 448 - Draw(image: image, 449 - destinationRectangle: destinationRectangle, 450 - sourceRectangle: sourceRectangle, 451 - color: color, 452 - rotation: rotation, 453 - origin: origin, 454 - options: SpriteOptions.None, 455 - layerDepth: layerDepth); 456 - } 440 + /// <inheritdoc/> 441 + public void Draw(TImage image, 442 + RectangleF destinationRectangle, 443 + RectangleF sourceRectangle, 444 + Color color, 445 + float rotation, 446 + Vector2 origin, 447 + float layerDepth) 448 + { 449 + Draw(image: image, 450 + destinationRectangle: destinationRectangle, 451 + sourceRectangle: sourceRectangle, 452 + color: color, 453 + rotation: rotation, 454 + origin: origin, 455 + options: SpriteOptions.None, 456 + layerDepth: layerDepth); 457 + } 457 458 458 - /// <inheritdoc/> 459 - public void Draw(TImage image, 460 - Vector2 position, 461 - RectangleF sourceRectangle, 462 - Color color, 463 - float rotation, 464 - Vector2 origin, 465 - Vector2 scale, 466 - float layerDepth) 467 - { 468 - Draw(image: image, 469 - position: position, 470 - sourceRectangle: sourceRectangle, 471 - color: color, 472 - rotation: rotation, 473 - origin: origin, 474 - scale: scale, 475 - options: SpriteOptions.None, 476 - layerDepth: layerDepth); 477 - } 459 + /// <inheritdoc/> 460 + public void Draw(TImage image, 461 + Vector2 position, 462 + RectangleF sourceRectangle, 463 + Color color, 464 + float rotation, 465 + Vector2 origin, 466 + Vector2 scale, 467 + float layerDepth) 468 + { 469 + Draw(image: image, 470 + position: position, 471 + sourceRectangle: sourceRectangle, 472 + color: color, 473 + rotation: rotation, 474 + origin: origin, 475 + scale: scale, 476 + options: SpriteOptions.None, 477 + layerDepth: layerDepth); 478 + } 478 479 479 - /// <inheritdoc/> 480 - public void Draw(TImage image, 481 - RectangleF destinationRectangle, 482 - RectangleF? sourceRectangle, 483 - Color color, 484 - float rotation, 485 - Vector2 origin, 486 - SpriteOptions options, 487 - float layerDepth) 488 - { 489 - var size = GetSize(image); 490 - Draw(image: image, 491 - destinationRectangle: destinationRectangle, 492 - sourceRectangle: sourceRectangle ?? new() 493 - { 494 - X = 0, 495 - Y = 0, 496 - Width = size.Width, 497 - Height = size.Height, 498 - }, 499 - color: color, 500 - rotation: rotation, 501 - origin: origin, 502 - options: options, 503 - layerDepth: layerDepth); 504 - } 480 + /// <inheritdoc/> 481 + public void Draw(TImage image, 482 + RectangleF destinationRectangle, 483 + RectangleF? sourceRectangle, 484 + Color color, 485 + float rotation, 486 + Vector2 origin, 487 + SpriteOptions options, 488 + float layerDepth) 489 + { 490 + var size = GetSize(image); 491 + Draw(image: image, 492 + destinationRectangle: destinationRectangle, 493 + sourceRectangle: sourceRectangle ?? new() 494 + { 495 + X = 0, 496 + Y = 0, 497 + Width = size.Width, 498 + Height = size.Height, 499 + }, 500 + color: color, 501 + rotation: rotation, 502 + origin: origin, 503 + options: options, 504 + layerDepth: layerDepth); 505 + } 505 506 506 - /// <inheritdoc/> 507 - public void Draw(TImage image, 508 - RectangleF destinationRectangle, 509 - RectangleF? sourceRectangle, 510 - Color color, 511 - float rotation, 512 - Vector2 origin, 513 - float layerDepth) 514 - { 515 - Draw(image, destinationRectangle, sourceRectangle, color, rotation, origin, SpriteOptions.None, layerDepth); 516 - } 507 + /// <inheritdoc/> 508 + public void Draw(TImage image, 509 + RectangleF destinationRectangle, 510 + RectangleF? sourceRectangle, 511 + Color color, 512 + float rotation, 513 + Vector2 origin, 514 + float layerDepth) 515 + { 516 + Draw(image, destinationRectangle, sourceRectangle, color, rotation, origin, SpriteOptions.None, layerDepth); 517 + } 517 518 518 - /// <inheritdoc/> 519 - public void Draw(TImage image, 520 - Vector2 position, 521 - RectangleF? sourceRectangle, 522 - Color color, 523 - float rotation, 524 - Vector2 origin, 525 - Vector2 scale, 526 - SpriteOptions options, 527 - float layerDepth) 528 - { 529 - var size = GetSize(image); 530 - Draw(image: image, 531 - position: position, 532 - sourceRectangle: sourceRectangle ?? new() 533 - { 534 - X = 0, 535 - Y = 0, 536 - Width = size.Width, 537 - Height = size.Height, 538 - }, 539 - color: color, 540 - rotation: rotation, 541 - origin: origin, 542 - scale: scale, 543 - options: options, 544 - layerDepth: layerDepth); 545 - } 519 + /// <inheritdoc/> 520 + public void Draw(TImage image, 521 + Vector2 position, 522 + RectangleF? sourceRectangle, 523 + Color color, 524 + float rotation, 525 + Vector2 origin, 526 + Vector2 scale, 527 + SpriteOptions options, 528 + float layerDepth) 529 + { 530 + var size = GetSize(image); 531 + Draw(image: image, 532 + position: position, 533 + sourceRectangle: sourceRectangle ?? new() 534 + { 535 + X = 0, 536 + Y = 0, 537 + Width = size.Width, 538 + Height = size.Height, 539 + }, 540 + color: color, 541 + rotation: rotation, 542 + origin: origin, 543 + scale: scale, 544 + options: options, 545 + layerDepth: layerDepth); 546 + } 546 547 547 - /// <inheritdoc/> 548 - public void Draw(TImage image, 549 - Vector2 position, 550 - RectangleF? sourceRectangle, 551 - Color color, 552 - float rotation, 553 - Vector2 origin, 554 - Vector2 scale, 555 - float layerDepth) 556 - { 557 - Draw(image: image, 558 - position: position, 559 - sourceRectangle: sourceRectangle, 560 - color: color, 561 - rotation: rotation, 562 - origin: origin, 563 - scale: scale, 564 - options: SpriteOptions.None, 565 - layerDepth: layerDepth); 566 - } 548 + /// <inheritdoc/> 549 + public void Draw(TImage image, 550 + Vector2 position, 551 + RectangleF? sourceRectangle, 552 + Color color, 553 + float rotation, 554 + Vector2 origin, 555 + Vector2 scale, 556 + float layerDepth) 557 + { 558 + Draw(image: image, 559 + position: position, 560 + sourceRectangle: sourceRectangle, 561 + color: color, 562 + rotation: rotation, 563 + origin: origin, 564 + scale: scale, 565 + options: SpriteOptions.None, 566 + layerDepth: layerDepth); 567 + } 567 568 568 - /// <inheritdoc/> 569 - public void Draw(TImage image, 570 - Vector2 position, 571 - RectangleF? sourceRectangle, 572 - Color color, 573 - float rotation, 574 - Vector2 origin, 575 - float scale, 576 - SpriteOptions options, 577 - float layerDepth) 578 - { 579 - Draw(image, position, sourceRectangle, color, rotation, origin, new Vector2(scale), options, layerDepth); 580 - } 569 + /// <inheritdoc/> 570 + public void Draw(TImage image, 571 + Vector2 position, 572 + RectangleF? sourceRectangle, 573 + Color color, 574 + float rotation, 575 + Vector2 origin, 576 + float scale, 577 + SpriteOptions options, 578 + float layerDepth) 579 + { 580 + Draw(image, position, sourceRectangle, color, rotation, origin, new Vector2(scale), options, layerDepth); 581 + } 581 582 582 - /// <inheritdoc/> 583 - public void Draw(TImage image, 584 - Vector2 position, 585 - RectangleF? sourceRectangle, 586 - Color color, 587 - float rotation, 588 - Vector2 origin, 589 - float scale, 590 - float layerDepth) 591 - { 592 - Draw(image, position, sourceRectangle, color, rotation, origin, scale, SpriteOptions.None, layerDepth); 593 - } 583 + /// <inheritdoc/> 584 + public void Draw(TImage image, 585 + Vector2 position, 586 + RectangleF? sourceRectangle, 587 + Color color, 588 + float rotation, 589 + Vector2 origin, 590 + float scale, 591 + float layerDepth) 592 + { 593 + Draw(image, position, sourceRectangle, color, rotation, origin, scale, SpriteOptions.None, layerDepth); 594 + } 594 595 595 - /// <inheritdoc/> 596 - public void Draw(TImage image, 597 - Vector2 position, 598 - RectangleF? sourceRectangle, 599 - Color color, 600 - SpriteOptions options, 601 - float layerDepth) 602 - { 603 - Draw(image, position, sourceRectangle, color, 0f, default, 0f, options, layerDepth); 604 - } 596 + /// <inheritdoc/> 597 + public void Draw(TImage image, 598 + Vector2 position, 599 + RectangleF? sourceRectangle, 600 + Color color, 601 + SpriteOptions options, 602 + float layerDepth) 603 + { 604 + Draw(image, position, sourceRectangle, color, 0f, default, 0f, options, layerDepth); 605 + } 605 606 606 - /// <inheritdoc/> 607 - public void Draw(TImage image, 608 - Vector2 position, 609 - RectangleF? sourceRectangle, 610 - Color color, 611 - float layerDepth) 612 - { 613 - Draw(image, position, sourceRectangle, color, SpriteOptions.None, layerDepth); 614 - } 607 + /// <inheritdoc/> 608 + public void Draw(TImage image, 609 + Vector2 position, 610 + RectangleF? sourceRectangle, 611 + Color color, 612 + float layerDepth) 613 + { 614 + Draw(image, position, sourceRectangle, color, SpriteOptions.None, layerDepth); 615 + } 615 616 616 - /// <inheritdoc/> 617 - public void Draw(TImage image, 618 - RectangleF destinationRectangle, 619 - RectangleF? sourceRectangle, 620 - Color color, 621 - SpriteOptions options, 622 - float layerDepth) 623 - { 624 - Draw(image, destinationRectangle, sourceRectangle, color, 0, default, options, layerDepth); 625 - } 617 + /// <inheritdoc/> 618 + public void Draw(TImage image, 619 + RectangleF destinationRectangle, 620 + RectangleF? sourceRectangle, 621 + Color color, 622 + SpriteOptions options, 623 + float layerDepth) 624 + { 625 + Draw(image, destinationRectangle, sourceRectangle, color, 0, default, options, layerDepth); 626 + } 626 627 627 - /// <inheritdoc/> 628 - public void Draw(TImage image, 629 - RectangleF destinationRectangle, 630 - RectangleF? sourceRectangle, 631 - Color color, 632 - float layerDepth) 633 - { 634 - Draw(image, destinationRectangle, sourceRectangle, color, SpriteOptions.None, layerDepth); 635 - } 628 + /// <inheritdoc/> 629 + public void Draw(TImage image, 630 + RectangleF destinationRectangle, 631 + RectangleF? sourceRectangle, 632 + Color color, 633 + float layerDepth) 634 + { 635 + Draw(image, destinationRectangle, sourceRectangle, color, SpriteOptions.None, layerDepth); 636 + } 636 637 637 - /// <inheritdoc/> 638 - public void Draw(TImage image, 639 - Vector2 position, 640 - Color color, 641 - SpriteOptions options, 642 - float layerDepth) 643 - { 644 - Draw(image, position, new Rectangle(default, GetSize(image)), color, 0, default, default, options, layerDepth); 645 - } 638 + /// <inheritdoc/> 639 + public void Draw(TImage image, 640 + Vector2 position, 641 + Color color, 642 + SpriteOptions options, 643 + float layerDepth) 644 + { 645 + Draw(image, position, new Rectangle(default, GetSize(image)), color, 0, default, default, options, layerDepth); 646 + } 646 647 647 - /// <inheritdoc/> 648 - public void Draw(TImage image, 649 - Vector2 position, 650 - Color color, 651 - float layerDepth) 652 - { 653 - Draw(image, position, new Rectangle(default, GetSize(image)), color, 0, default, default, SpriteOptions.None, layerDepth); 654 - } 648 + /// <inheritdoc/> 649 + public void Draw(TImage image, 650 + Vector2 position, 651 + Color color, 652 + float layerDepth) 653 + { 654 + Draw(image, position, new Rectangle(default, GetSize(image)), color, 0, default, default, SpriteOptions.None, layerDepth); 655 + } 655 656 656 - /// <inheritdoc/> 657 - public void Draw(TImage image, 658 - RectangleF destinationRectangle, 659 - Color color, 660 - SpriteOptions options, 661 - float layerDepth) 662 - { 663 - Draw(image, destinationRectangle, new Rectangle(default, GetSize(image)), color, 0, default, options, layerDepth); 664 - } 657 + /// <inheritdoc/> 658 + public void Draw(TImage image, 659 + RectangleF destinationRectangle, 660 + Color color, 661 + SpriteOptions options, 662 + float layerDepth) 663 + { 664 + Draw(image, destinationRectangle, new Rectangle(default, GetSize(image)), color, 0, default, options, layerDepth); 665 + } 665 666 666 - /// <inheritdoc/> 667 - public void Draw(TImage image, 668 - RectangleF destinationRectangle, 669 - Color color, 670 - float layerDepth) 671 - { 672 - Draw(image, destinationRectangle, color, SpriteOptions.None, layerDepth); 673 - } 667 + /// <inheritdoc/> 668 + public void Draw(TImage image, 669 + RectangleF destinationRectangle, 670 + Color color, 671 + float layerDepth) 672 + { 673 + Draw(image, destinationRectangle, color, SpriteOptions.None, layerDepth); 674 + } 674 675 675 - /// <inheritdoc/> 676 - public void DrawRect(RectangleF rectangle, Color color, float rotation, Vector2 origin, float layerDepth) 677 - { 678 - Draw(m_whiteImage, rectangle, new RectangleF(0, 0, 1, 1), color, rotation, origin, layerDepth); 679 - } 676 + /// <inheritdoc/> 677 + public void DrawRect(RectangleF rectangle, Color color, float rotation, Vector2 origin, float layerDepth) 678 + { 679 + Draw(m_whiteImage, rectangle, new RectangleF(0, 0, 1, 1), color, rotation, origin, layerDepth); 680 + } 680 681 681 - /// <inheritdoc/> 682 - public void DrawRect(RectangleF rectangle, Color color, float layerDepth) 683 - { 684 - Draw(m_whiteImage, rectangle, new RectangleF(0, 0, 1, 1), color, layerDepth); 685 - } 682 + /// <inheritdoc/> 683 + public void DrawRect(RectangleF rectangle, Color color, float layerDepth) 684 + { 685 + Draw(m_whiteImage, rectangle, new RectangleF(0, 0, 1, 1), color, layerDepth); 686 + } 686 687 687 - /// <inheritdoc/> 688 - public void DrawDot(Vector2 position, float size, Color color, float layerDepth) 689 - { 690 - Draw(m_whiteImage, new RectangleF(position.X, position.Y, size, size), new RectangleF(0, 0, 1, 1), color, layerDepth); 691 - } 688 + /// <inheritdoc/> 689 + public void DrawDot(Vector2 position, float size, Color color, float layerDepth) 690 + { 691 + Draw(m_whiteImage, new RectangleF(0, 0, size, size), new RectangleF(0, 0, 1, 1), color, layerDepth); 692 + } 692 693 693 - /// <inheritdoc/> 694 - public void DrawSegment(Vector2 a, Vector2 b, Color color, float thickness, float layerDepth) 695 - { 696 - var diff = b - a; 697 - var length = MathF.Sqrt(Vector2.Dot(diff, diff)); 698 - var angle = MathF.Atan2(diff.Y, diff.X); 699 - DrawSegment(a, length, color, angle, thickness, layerDepth); 700 - } 694 + /// <inheritdoc/> 695 + public void DrawSegment(Vector2 a, Vector2 b, Color color, float thickness, float layerDepth) 696 + { 697 + var diff = b - a; 698 + var length = MathF.Sqrt(Vector2.Dot(diff, diff)); 699 + var angle = MathF.Atan2(diff.Y, diff.X); 700 + DrawSegment(a, length, color, angle, thickness, layerDepth); 701 + } 701 702 702 - /// <inheritdoc/> 703 - public void DrawSegment(Vector2 start, float length, Color color, float angle, float thickness, float layerDepth) 704 - { 705 - var rect = new RectangleF(start.X, start.Y, length, thickness); 706 - DrawRect(rect, color, angle, new Vector2(0, 0.5f), layerDepth); 707 - } 703 + /// <inheritdoc/> 704 + public void DrawSegment(Vector2 start, float length, Color color, float angle, float thickness, float layerDepth) 705 + { 706 + var rect = new RectangleF(start.X, start.Y, length, thickness); 707 + DrawRect(rect, color, angle, new Vector2(0, 0.5f), layerDepth); 708 + } 708 709 709 - #endregion 710 + #endregion 710 711 711 - /// <summary> 712 - /// Gets size of a image. 713 - /// </summary> 714 - /// <param name="image">Image.</param> 715 - /// <returns>Image Size.</returns> 716 - protected abstract Size GetSize(TImage image); 712 + /// <summary> 713 + /// Gets size of a image. 714 + /// </summary> 715 + /// <param name="image">Image.</param> 716 + /// <returns>Image Size.</returns> 717 + protected abstract Size GetSize(TImage image); 717 718 718 - /// <summary> 719 - /// Gets TImage. 720 - /// </summary> 721 - /// <param name="image"></param> 722 - /// <returns></returns> 723 - protected abstract TImage GetHandle(Image image); 719 + /// <summary> 720 + /// Gets TImage. 721 + /// </summary> 722 + /// <param name="image"></param> 723 + /// <returns></returns> 724 + protected abstract TImage GetHandle(Image image); 724 725 }
+69 -70
src/Peridot/Text/Font.cs
··· 3 3 4 4 namespace Peridot.Text 5 5 { 6 - /// <summary> 7 - /// Represents a font that can be rendered with <see cref="TextRenderer"/>. 8 - /// </summary> 9 - public class Font 10 - { 11 - /// <summary> 12 - /// Creates a new instance of <see cref="Font"/>. 13 - /// </summary> 14 - public Font() 15 - { 16 - var settings = new FontSystemSettings 17 - { 18 - FontResolutionFactor = 2, 19 - KernelWidth = 2, 20 - KernelHeight = 2, 21 - }; 22 - FontSystem = new FontSystem(settings); 23 - } 6 + /// <summary> 7 + /// Represents a font that can be rendered with <see cref="TextRenderer"/>. 8 + /// </summary> 9 + public class Font 10 + { 11 + /// <summary> 12 + /// Creates a new instance of <see cref="Font"/>. 13 + /// </summary> 14 + public Font() 15 + { 16 + var settings = new FontSystemSettings 17 + { 18 + Effect = FontSystemEffect.None, 19 + EffectAmount = 2, 20 + }; 21 + FontSystem = new FontSystem(settings); 22 + } 23 + 24 + /// <summary> 25 + /// Destroys font. 26 + /// </summary> 27 + ~Font() 28 + { 29 + Dispose(false); 30 + } 24 31 25 - /// <summary> 26 - /// Destroys font. 27 - /// </summary> 28 - ~Font() 29 - { 30 - Dispose(false); 31 - } 32 + internal FontSystem FontSystem { get; } 32 33 33 - internal FontSystem FontSystem { get; } 34 + /// <summary> 35 + /// A bool indicating whether this instance has been disposed. 36 + /// </summary> 37 + public bool IsDisposed { get; private set; } 34 38 35 - /// <summary> 36 - /// A bool indicating whether this instance has been disposed. 37 - /// </summary> 38 - public bool IsDisposed { get; private set; } 39 + /// <summary> 40 + /// Add a character font to the font. 41 + /// </summary> 42 + /// <param name="stream">The stream that contains the font.</param> 43 + public void AddFont(Stream stream) 44 + { 45 + FontSystem.AddFont(stream); 46 + } 39 47 40 - /// <summary> 41 - /// Add a character font to the font. 42 - /// </summary> 43 - /// <param name="stream">The stream that contains the font.</param> 44 - public void AddFont(Stream stream) 45 - { 46 - FontSystem.AddFont(stream); 47 - } 48 + /// <summary> 49 + /// Add a character font to the font. 50 + /// </summary> 51 + /// <param name="data">The data that contains the font.</param> 52 + public void AddFont(byte[] data) 53 + { 54 + FontSystem.AddFont(data); 55 + } 48 56 49 - /// <summary> 50 - /// Add a character font to the font. 51 - /// </summary> 52 - /// <param name="data">The data that contains the font.</param> 53 - public void AddFont(byte[] data) 54 - { 55 - FontSystem.AddFont(data); 56 - } 57 + /// <summary> 58 + /// Gets the size of a string when rendered in this font. 59 + /// </summary> 60 + /// <param name="text">The text to measure.</param> 61 + /// <param name="fontSize">The font size to measure.</param> 62 + /// <returns>The size of <paramref name="text"/> rendered with <paramref name="fontSize"/> font size.</returns> 63 + public Vector2 MeasureString(string text, int fontSize) 64 + { 65 + var font = FontSystem.GetFont(fontSize); 66 + return font.MeasureString(text); 67 + } 57 68 58 - /// <summary> 59 - /// Gets the size of a string when rendered in this font. 60 - /// </summary> 61 - /// <param name="text">The text to measure.</param> 62 - /// <param name="fontSize">The font size to measure.</param> 63 - /// <returns>The size of <paramref name="text"/> rendered with <paramref name="fontSize"/> font size.</returns> 64 - public Vector2 MeasureString(string text, int fontSize) 65 - { 66 - var font = FontSystem.GetFont(fontSize); 67 - return font.MeasureString(text); 68 - } 69 - 70 - /// <inheritdoc/> 71 - public void Dispose() 72 - { 73 - Dispose(true); 74 - GC.SuppressFinalize(this); 75 - } 69 + /// <inheritdoc/> 70 + public void Dispose() 71 + { 72 + Dispose(true); 73 + GC.SuppressFinalize(this); 74 + } 76 75 77 - private void Dispose(bool disposing) 78 - { 79 - if (disposing) 80 - FontSystem.Dispose(); 81 - } 82 - } 76 + private void Dispose(bool disposing) 77 + { 78 + if (disposing) 79 + FontSystem.Dispose(); 80 + } 81 + } 83 82 }
+121 -121
src/Peridot/Text/FontRenderer.cs
··· 9 9 10 10 namespace Peridot 11 11 { 12 - internal class FontStashRenderer : IFontStashRenderer, IDisposable 13 - { 14 - private bool m_disposed; 15 - private readonly ISpriteBatch m_spriteBatch; 16 - private readonly Texture2DManager m_textureManager; 17 - public FontStashRenderer(IPeridot peridot, ISpriteBatch spriteBatch) 18 - { 19 - m_spriteBatch = spriteBatch; 20 - m_textureManager = new Texture2DManager(peridot); 21 - ResetScissor(); 22 - } 12 + internal class FontStashRenderer : IFontStashRenderer, IDisposable 13 + { 14 + private bool m_disposed; 15 + private readonly ISpriteBatch m_spriteBatch; 16 + private readonly Texture2DManager m_textureManager; 17 + public FontStashRenderer(IPeridot peridot, ISpriteBatch spriteBatch) 18 + { 19 + m_spriteBatch = spriteBatch; 20 + m_textureManager = new Texture2DManager(peridot); 21 + ResetScissor(); 22 + } 23 23 24 - ~FontStashRenderer() 25 - { 26 - Dispose(false); 27 - } 24 + ~FontStashRenderer() 25 + { 26 + Dispose(false); 27 + } 28 28 29 - public Rectangle Scissor { get; set; } 29 + public Rectangle Scissor { get; set; } 30 30 31 - public ITexture2DManager TextureManager => m_textureManager; 31 + public ITexture2DManager TextureManager => m_textureManager; 32 + 33 + private void Dispose(bool disposing) 34 + { 35 + if (m_disposed) 36 + return; 37 + m_disposed = true; 38 + if (disposing) 39 + m_textureManager.Dispose(); 40 + } 41 + 42 + public void Dispose() 43 + { 44 + Dispose(true); 45 + } 32 46 33 - private void Dispose(bool disposing) 34 - { 35 - if (m_disposed) 36 - return; 37 - m_disposed = true; 38 - if (disposing) 39 - m_textureManager.Dispose(); 40 - } 47 + public void ResetScissor() 48 + { 49 + const int v = 1 << 23; 50 + const int s = -(1 << 22); 51 + Scissor = new Rectangle(s, s, v, v); 52 + } 41 53 42 - public void Dispose() 43 - { 44 - Dispose(true); 45 - } 46 - 47 - public void ResetScissor() 48 - { 49 - const int v = 1 << 23; 50 - const int s = -(1 << 22); 51 - Scissor = new Rectangle(s, s, v, v); 52 - } 53 - 54 - public void Draw(object texture, Vector2 pos, Rectangle? src, FSColor color, float rotation, Vector2 scale, float depth) 55 - { 56 - Debug.Assert(texture is Image, "The texture object must be a Image."); 57 - if (texture is not Image t) 58 - throw new ArgumentException(nameof(texture)); 59 - 60 - var s = src ?? new(0, 0, (int)t.Width, (int)t.Height); 61 - 62 - var oldScissor = m_spriteBatch.Scissor; 63 - m_spriteBatch.Scissor = RectangleF.Intersect(m_spriteBatch.Scissor, Scissor); 64 - m_spriteBatch.Draw(t, pos, s, ToColor(color), rotation, Vector2.Zero, new Vector2(scale.X, scale.Y), depth); 65 - m_spriteBatch.Scissor = oldScissor; 66 - } 67 - 68 - private static Color ToColor(in FSColor color) 69 - { 70 - return Color.FromArgb(color.A, color.R, color.G, color.B); 71 - } 72 - 73 - private class Texture2DManager : ITexture2DManager, IDisposable 74 - { 75 - private readonly List<WeakReference<Image>> m_images; 76 - private readonly IPeridot m_peridot; 77 - private bool m_disposed; 78 - public Texture2DManager(IPeridot peridot) 79 - { 80 - m_images = new(); 81 - m_peridot = peridot; 82 - m_disposed = false; 83 - } 84 - 85 - ~Texture2DManager() 86 - { 87 - Dispose(false); 88 - } 89 - 90 - public object CreateTexture(int width, int height) 91 - { 92 - var image = m_peridot.CreateImage(new ImageDescription() 93 - { 94 - Format = PixelFormat.BGRA8, 95 - Width = (uint)width, 96 - Height = (uint)height, 97 - }); 98 - m_images.Add(new WeakReference<Image>(image)); 99 - return image; 100 - } 54 + public void Draw(object texture, Vector2 pos, Rectangle? src, FSColor color, float rotation, Vector2 scale, float depth) 55 + { 56 + Debug.Assert(texture is Image, "The texture object must be a Image."); 57 + if (texture is not Image t) 58 + throw new ArgumentException(nameof(texture)); 101 59 102 - public Point GetTextureSize(object texture) 103 - { 104 - Debug.Assert(texture is Image); 105 - Image image = (texture as Image)!; 106 - return new Point(image.Width, image.Height); 107 - } 60 + var s = src ?? new(0, 0, (int)t.Width, (int)t.Height); 108 61 109 - public void SetTextureData(object texture, Rectangle bounds, byte[] data) 110 - { 111 - Debug.Assert(texture is Image); 62 + var oldScissor = m_spriteBatch.Scissor; 63 + m_spriteBatch.Scissor = RectangleF.Intersect(m_spriteBatch.Scissor, Scissor); 64 + m_spriteBatch.Draw(t, pos, s, ToColor(color), rotation, Vector2.Zero, new Vector2(scale.X, scale.Y), depth); 65 + m_spriteBatch.Scissor = oldScissor; 66 + } 67 + 68 + private static Color ToColor(in FSColor color) 69 + { 70 + return Color.FromArgb(color.A, color.R, color.G, color.B); 71 + } 112 72 113 - if (texture is not Image) 114 - throw new NotImplementedException(); 73 + private class Texture2DManager : ITexture2DManager, IDisposable 74 + { 75 + private readonly List<WeakReference<Image>> m_images; 76 + private readonly IPeridot m_peridot; 77 + private bool m_disposed; 78 + public Texture2DManager(IPeridot peridot) 79 + { 80 + m_images = new(); 81 + m_peridot = peridot; 82 + m_disposed = false; 83 + } 84 + 85 + ~Texture2DManager() 86 + { 87 + Dispose(false); 88 + } 89 + 90 + public object CreateTexture(int width, int height) 91 + { 92 + var image = m_peridot.CreateImage(new ImageDescription() 93 + { 94 + Format = PixelFormat.BGRA8, 95 + Width = (uint)width, 96 + Height = (uint)height, 97 + }); 98 + m_images.Add(new WeakReference<Image>(image)); 99 + return image; 100 + } 115 101 116 - m_peridot.UpdateImage<byte>( 117 - (texture as Image)!, 118 - data, 119 - (uint)bounds.X, 120 - (uint)bounds.Y, 121 - (uint)bounds.Width, 122 - (uint)bounds.Height); 123 - } 102 + public Point GetTextureSize(object texture) 103 + { 104 + Debug.Assert(texture is Image); 105 + Image image = (texture as Image)!; 106 + return new Point(image.Width, image.Height); 107 + } 124 108 125 - public void Dispose() 126 - { 127 - Dispose(true); 128 - } 109 + public void SetTextureData(object texture, Rectangle bounds, byte[] data) 110 + { 111 + Debug.Assert(texture is Image); 112 + 113 + if (texture is not Image) 114 + throw new NotImplementedException(); 115 + 116 + m_peridot.UpdateImage<byte>( 117 + (texture as Image)!, 118 + data, 119 + (uint)bounds.X, 120 + (uint)bounds.Y, 121 + (uint)bounds.Width, 122 + (uint)bounds.Height); 123 + } 124 + 125 + public void Dispose() 126 + { 127 + Dispose(true); 128 + } 129 129 130 - private void Dispose(bool disposing) 131 - { 132 - if (m_disposed) 133 - return; 134 - m_disposed = true; 130 + private void Dispose(bool disposing) 131 + { 132 + if (m_disposed) 133 + return; 134 + m_disposed = true; 135 135 136 - if (disposing) 137 - { 138 - foreach (var wt in m_images) 139 - if (wt.TryGetTarget(out var texture)) 140 - texture.Dispose(); 141 - } 142 - } 143 - } 144 - } 136 + if (disposing) 137 + { 138 + foreach (var wt in m_images) 139 + if (wt.TryGetTarget(out var texture)) 140 + texture.Dispose(); 141 + } 142 + } 143 + } 144 + } 145 145 }
+172 -172
src/Peridot/Text/TextRenderer.cs
··· 6 6 7 7 namespace Peridot.Text 8 8 { 9 - /// <summary> 10 - /// Represents an interface to a text renderer. 11 - /// </summary> 12 - public class TextRenderer : IDisposable 13 - { 14 - private readonly ISpriteBatch m_spriteBatch; 15 - private readonly FontStashRenderer _textRenderer; 9 + /// <summary> 10 + /// Represents an interface to a text renderer. 11 + /// </summary> 12 + public class TextRenderer : IDisposable 13 + { 14 + private readonly ISpriteBatch m_spriteBatch; 15 + private readonly FontStashRenderer _textRenderer; 16 16 17 - /// <summary> 18 - /// Creates a new instance of <see cref="TextRenderer"/>. 19 - /// </summary> 20 - /// <param name="peridot">Peridot implementation.</param> 21 - /// <param name="spriteBatch">SpriteBatch to use to render.</param> 22 - public TextRenderer(IPeridot peridot, ISpriteBatch spriteBatch) 23 - { 24 - m_spriteBatch = spriteBatch; 25 - _textRenderer = new(peridot, spriteBatch); 26 - } 27 - 28 - /// <inheritdoc/> 29 - ~TextRenderer() 30 - { 31 - Dispose(false); 32 - } 33 - 34 - /// <summary> 35 - /// A bool indicating whether this instance has been disposed. 36 - /// </summary> 37 - public bool IsDisposed { get; private set; } 38 - 39 - /// <summary> 40 - /// Submit a text string for drawing. 41 - /// </summary> 42 - /// <param name="font">The font to draw.</param> 43 - /// <param name="fontSize">The font size.</param> 44 - /// <param name="text">The text which will be drawn.</param> 45 - /// <param name="position">The drawing location on screen.</param> 46 - /// <param name="color">The text color.</param> 47 - /// <param name="rotation">The rotation of the drawing.</param> 48 - /// <param name="origin">The center of the rotation. (0, 0) for default.</param> 49 - /// <param name="scale">The scaling of this drawing.</param> 50 - /// <param name="layerDepth">The layer depth of this drawing.</param> 51 - public void DrawString( 52 - Font font, 53 - int fontSize, 54 - string text, 55 - Vector2 position, 56 - Color color, 57 - float rotation, 58 - Vector2 origin, 59 - Vector2 scale, 60 - float layerDepth) 61 - { 62 - var rf = font.FontSystem.GetFont(fontSize); 63 - var fcolor = new FontStashSharp.FSColor(color.R, color.G, color.B, color.A); 17 + /// <summary> 18 + /// Creates a new instance of <see cref="TextRenderer"/>. 19 + /// </summary> 20 + /// <param name="peridot">Peridot implementation.</param> 21 + /// <param name="spriteBatch">SpriteBatch to use to render.</param> 22 + public TextRenderer(IPeridot peridot, ISpriteBatch spriteBatch) 23 + { 24 + m_spriteBatch = spriteBatch; 25 + _textRenderer = new(peridot, spriteBatch); 26 + } 64 27 65 - rf.DrawText(_textRenderer, text, position, fcolor, scale, rotation, origin, layerDepth); 66 - } 28 + /// <inheritdoc/> 29 + ~TextRenderer() 30 + { 31 + Dispose(false); 32 + } 33 + 34 + /// <summary> 35 + /// A bool indicating whether this instance has been disposed. 36 + /// </summary> 37 + public bool IsDisposed { get; private set; } 67 38 68 - /// <summary> 69 - /// Submit a text string for drawing. 70 - /// </summary> 71 - /// <param name="font">The font to draw.</param> 72 - /// <param name="fontSize">The font size.</param> 73 - /// <param name="text">The text which will be drawn.</param> 74 - /// <param name="position">The drawing location on screen.</param> 75 - /// <param name="color">The text color.</param> 76 - /// <param name="rotation">The rotation of the drawing.</param> 77 - /// <param name="origin">The center of the rotation. (0, 0) for default.</param> 78 - /// <param name="scale">The scaling of this drawing.</param> 79 - /// <param name="layerDepth">The layer depth of this drawing.</param> 80 - /// <param name="scissor">The scissor rectangle.</param> 81 - public void DrawString( 82 - Font font, 83 - int fontSize, 84 - string text, 85 - Vector2 position, 86 - Color color, 87 - float rotation, 88 - Vector2 origin, 89 - Vector2 scale, 90 - float layerDepth, 91 - Rectangle scissor) 92 - { 93 - var rf = font.FontSystem.GetFont(fontSize); 94 - var fcolor = new FontStashSharp.FSColor(color.R, color.G, color.B, color.A); 39 + /// <summary> 40 + /// Submit a text string for drawing. 41 + /// </summary> 42 + /// <param name="font">The font to draw.</param> 43 + /// <param name="fontSize">The font size.</param> 44 + /// <param name="text">The text which will be drawn.</param> 45 + /// <param name="position">The drawing location on screen.</param> 46 + /// <param name="color">The text color.</param> 47 + /// <param name="rotation">The rotation of the drawing.</param> 48 + /// <param name="origin">The center of the rotation. (0, 0) for default.</param> 49 + /// <param name="scale">The scaling of this drawing.</param> 50 + /// <param name="layerDepth">The layer depth of this drawing.</param> 51 + public void DrawString( 52 + Font font, 53 + int fontSize, 54 + string text, 55 + Vector2 position, 56 + Color color, 57 + float rotation, 58 + Vector2 origin, 59 + Vector2 scale, 60 + float layerDepth) 61 + { 62 + var rf = font.FontSystem.GetFont(fontSize); 63 + var fcolor = new FontStashSharp.FSColor(color.R, color.G, color.B, color.A); 64 + 65 + rf.DrawText(_textRenderer, text, position, fcolor, scale, rotation, origin, layerDepth); 66 + } 95 67 96 - _textRenderer.Scissor = scissor; 97 - rf.DrawText(_textRenderer, text, position, fcolor, scale, rotation, origin, layerDepth); 98 - _textRenderer.ResetScissor(); 99 - } 68 + /// <summary> 69 + /// Submit a text string for drawing. 70 + /// </summary> 71 + /// <param name="font">The font to draw.</param> 72 + /// <param name="fontSize">The font size.</param> 73 + /// <param name="text">The text which will be drawn.</param> 74 + /// <param name="position">The drawing location on screen.</param> 75 + /// <param name="color">The text color.</param> 76 + /// <param name="rotation">The rotation of the drawing.</param> 77 + /// <param name="origin">The center of the rotation. (0, 0) for default.</param> 78 + /// <param name="scale">The scaling of this drawing.</param> 79 + /// <param name="layerDepth">The layer depth of this drawing.</param> 80 + /// <param name="scissor">The scissor rectangle.</param> 81 + public void DrawString( 82 + Font font, 83 + int fontSize, 84 + string text, 85 + Vector2 position, 86 + Color color, 87 + float rotation, 88 + Vector2 origin, 89 + Vector2 scale, 90 + float layerDepth, 91 + Rectangle scissor) 92 + { 93 + var rf = font.FontSystem.GetFont(fontSize); 94 + var fcolor = new FontStashSharp.FSColor(color.R, color.G, color.B, color.A); 95 + 96 + _textRenderer.Scissor = scissor; 97 + rf.DrawText(_textRenderer, text, position, fcolor, scale, rotation, origin, layerDepth); 98 + _textRenderer.ResetScissor(); 99 + } 100 100 101 - /// <summary> 102 - /// Submit a text string for drawing. 103 - /// </summary> 104 - /// <param name="font">The font to draw.</param> 105 - /// <param name="fontSize">The font size.</param> 106 - /// <param name="text">The text which will be drawn.</param> 107 - /// <param name="position">The drawing location on screen</param> 108 - /// <param name="color">The text color.</param> 109 - public void DrawString( 110 - Font font, 111 - int fontSize, 112 - string text, 113 - Vector2 position, 114 - Color color) 115 - { 116 - DrawString(font, fontSize, text, position, color, 0, Vector2.Zero, Vector2.One, 0); 117 - } 101 + /// <summary> 102 + /// Submit a text string for drawing. 103 + /// </summary> 104 + /// <param name="font">The font to draw.</param> 105 + /// <param name="fontSize">The font size.</param> 106 + /// <param name="text">The text which will be drawn.</param> 107 + /// <param name="position">The drawing location on screen</param> 108 + /// <param name="color">The text color.</param> 109 + public void DrawString( 110 + Font font, 111 + int fontSize, 112 + string text, 113 + Vector2 position, 114 + Color color) 115 + { 116 + DrawString(font, fontSize, text, position, color, 0, Vector2.Zero, Vector2.One, 0); 117 + } 118 118 119 - /// <summary> 120 - /// Submit a text string for drawing. 121 - /// </summary> 122 - /// <param name="font">The font to draw.</param> 123 - /// <param name="fontSize">The font size.</param> 124 - /// <param name="text">The text which will be drawn.</param> 125 - /// <param name="position">The drawing location on screen</param> 126 - /// <param name="color">The text color.</param> 127 - /// <param name="scissor">The scissor rectangle.</param> 128 - public void DrawString( 129 - Font font, 130 - int fontSize, 131 - string text, 132 - Vector2 position, 133 - Color color, 134 - Rectangle scissor) 135 - { 136 - DrawString(font, fontSize, text, position, color, 0, Vector2.Zero, Vector2.One, 0, scissor); 137 - } 119 + /// <summary> 120 + /// Submit a text string for drawing. 121 + /// </summary> 122 + /// <param name="font">The font to draw.</param> 123 + /// <param name="fontSize">The font size.</param> 124 + /// <param name="text">The text which will be drawn.</param> 125 + /// <param name="position">The drawing location on screen</param> 126 + /// <param name="color">The text color.</param> 127 + /// <param name="scissor">The scissor rectangle.</param> 128 + public void DrawString( 129 + Font font, 130 + int fontSize, 131 + string text, 132 + Vector2 position, 133 + Color color, 134 + Rectangle scissor) 135 + { 136 + DrawString(font, fontSize, text, position, color, 0, Vector2.Zero, Vector2.One, 0, scissor); 137 + } 138 138 139 - /// <summary> 140 - /// Submit a text string for drawing. 141 - /// </summary> 142 - /// <param name="font">The font to draw.</param> 143 - /// <param name="fontSize">The font size.</param> 144 - /// <param name="text">The text which will be drawn.</param> 145 - /// <param name="position">The drawing location on screen</param> 146 - /// <param name="color">The text color.</param> 147 - /// <param name="rotation">The rotation of the drawing.</param> 148 - /// <param name="origin">The center of the rotation. (0, 0) for default.</param> 149 - /// <param name="scale">The scaling of this drawing.</param> 150 - /// <param name="layerDepth">The layer depth of this drawing.</param> 151 - public void DrawString( 152 - Font font, 153 - int fontSize, 154 - string text, 155 - Vector2 position, 156 - Color color, 157 - float rotation, 158 - Vector2 origin, 159 - float scale, 160 - float layerDepth) 161 - { 162 - DrawString(font, fontSize, text, position, color, rotation, origin, new Vector2(scale), layerDepth); 163 - } 139 + /// <summary> 140 + /// Submit a text string for drawing. 141 + /// </summary> 142 + /// <param name="font">The font to draw.</param> 143 + /// <param name="fontSize">The font size.</param> 144 + /// <param name="text">The text which will be drawn.</param> 145 + /// <param name="position">The drawing location on screen</param> 146 + /// <param name="color">The text color.</param> 147 + /// <param name="rotation">The rotation of the drawing.</param> 148 + /// <param name="origin">The center of the rotation. (0, 0) for default.</param> 149 + /// <param name="scale">The scaling of this drawing.</param> 150 + /// <param name="layerDepth">The layer depth of this drawing.</param> 151 + public void DrawString( 152 + Font font, 153 + int fontSize, 154 + string text, 155 + Vector2 position, 156 + Color color, 157 + float rotation, 158 + Vector2 origin, 159 + float scale, 160 + float layerDepth) 161 + { 162 + DrawString(font, fontSize, text, position, color, rotation, origin, new Vector2(scale), layerDepth); 163 + } 164 164 165 - /// <summary> 166 - /// Submit a text string for drawing. 167 - /// </summary> 168 - /// <param name="font">The font to draw.</param> 169 - /// <param name="fontSize">The font size.</param> 170 - /// <param name="text">The text which will be drawn.</param> 171 - /// <param name="position">The drawing location on screen</param> 172 - /// <param name="color">The text color.</param> 173 - /// <param name="rotation">The rotation of the drawing.</param> 174 - /// <param name="origin">The center of the rotation. (0, 0) for default.</param> 175 - /// <param name="scale">The scaling of this drawing.</param> 176 - /// <param name="layerDepth">The layer depth of this drawing.</param> 177 - /// <param name="scissor">The scissor rectangle.</param> 178 - public void DrawString( 179 - Font font, 180 - int fontSize, 181 - string text, 182 - Vector2 position, 183 - Color color, 184 - float rotation, 185 - Vector2 origin, 186 - float scale, 187 - float layerDepth, 188 - Rectangle scissor) 165 + /// <summary> 166 + /// Submit a text string for drawing. 167 + /// </summary> 168 + /// <param name="font">The font to draw.</param> 169 + /// <param name="fontSize">The font size.</param> 170 + /// <param name="text">The text which will be drawn.</param> 171 + /// <param name="position">The drawing location on screen</param> 172 + /// <param name="color">The text color.</param> 173 + /// <param name="rotation">The rotation of the drawing.</param> 174 + /// <param name="origin">The center of the rotation. (0, 0) for default.</param> 175 + /// <param name="scale">The scaling of this drawing.</param> 176 + /// <param name="layerDepth">The layer depth of this drawing.</param> 177 + /// <param name="scissor">The scissor rectangle.</param> 178 + public void DrawString( 179 + Font font, 180 + int fontSize, 181 + string text, 182 + Vector2 position, 183 + Color color, 184 + float rotation, 185 + Vector2 origin, 186 + float scale, 187 + float layerDepth, 188 + Rectangle scissor) 189 189 { 190 190 DrawString(font, fontSize, text, position, color, rotation, origin, new Vector2(scale), layerDepth, scissor); 191 191 }
-19
src/Peridot.Sample2/Peridot.Sample2.csproj
··· 1 - <Project Sdk="Microsoft.NET.Sdk"> 2 - 3 - <PropertyGroup> 4 - <OutputType>Exe</OutputType> 5 - <TargetFramework>net6.0</TargetFramework> 6 - <ImplicitUsings>enable</ImplicitUsings> 7 - <Nullable>enable</Nullable> 8 - </PropertyGroup> 9 - 10 - <ItemGroup> 11 - <PackageReference Include="Veldrid.StartupUtilities" Version="4.8.0" /> 12 - </ItemGroup> 13 - 14 - <ItemGroup> 15 - <ProjectReference Include="..\Peridot.Veldrid\Peridot.Veldrid.csproj" /> 16 - <ProjectReference Include="..\Peridot\Peridot.csproj" /> 17 - </ItemGroup> 18 - 19 - </Project>
-236
src/Peridot.Sample2/Program.cs
··· 1 - ๏ปฟusing System.Drawing; 2 - using Peridot.Text; 3 - using System.Numerics; 4 - using Veldrid.StartupUtilities; 5 - using Veldrid; 6 - using Peridot; 7 - using System.Globalization; 8 - 9 - internal class Program 10 - { 11 - public class Unit 12 - { 13 - public Vector2 Position; 14 - public Vector2 Speed; 15 - } 16 - 17 - private static Dictionary<Color, List<Unit>> Groups = new(); 18 - private static Dictionary<(Color, Color), float> Rules = new(); 19 - private static Random rnd = new(); 20 - private static Size Bounds; 21 - private static readonly float Gold = (MathF.Sqrt(5) + 1f) / 2f; 22 - 23 - private static void Rule(float deltaTime, List<Unit> units1, List<Unit> units2, float g) 24 - { 25 - units1.AsParallel().ForAll(a => 26 - { 27 - var force = new Vector2(); 28 - 29 - for (var j = 0; j < units2.Count; j++) 30 - { 31 - var b = units2[j]; 32 - 33 - var diff = a.Position - b.Position; 34 - var distance = Vector2.Distance(a.Position, b.Position); 35 - if (distance > 0 && distance < 80) 36 - { 37 - var F = g * (1f / distance); 38 - force += diff * F; 39 - } 40 - } 41 - 42 - a.Speed += force * 0.5f; 43 - a.Position += a.Speed; 44 - 45 - var m = 0.5f; 46 - 47 - if (((a.Position.X <= 0 && a.Speed.X < 0) || (a.Position.X >= Bounds.Width && a.Speed.X > 0))) 48 - a.Speed.X *= -m; 49 - else 50 - a.Speed.X *= m; 51 - 52 - if (((a.Position.Y <= 0 && a.Speed.Y < 0) || (a.Position.Y >= Bounds.Height && a.Speed.Y > 0))) 53 - a.Speed.Y *= -m; 54 - else 55 - a.Speed.Y *= m; 56 - }); 57 - } 58 - 59 - private static void AddUnits(int count, Color color) 60 - { 61 - if (!Groups.TryGetValue(color, out var units)) 62 - { 63 - Groups[color] = units = new(); 64 - } 65 - 66 - for(var i = 0; i < count; i++) 67 - { 68 - var x = rnd.Next(0, Bounds.Width); 69 - var y = rnd.Next(0, Bounds.Height); 70 - 71 - units.Add(new() 72 - { 73 - Position = new(x, y) 74 - }); 75 - } 76 - } 77 - 78 - private static void Load() 79 - { 80 - Groups.Clear(); 81 - AddUnits(500, Color.Yellow); 82 - AddUnits(500, Color.Red); 83 - AddUnits(500, Color.Green); 84 - AddUnits(500, Color.White); 85 - AddUnits(500, Color.Purple); 86 - } 87 - 88 - private static void Gen() 89 - { 90 - var colors = new Color[] { Color.Yellow, Color.Red, Color.Green, Color.White, Color.Purple }; 91 - Rules.Clear(); 92 - Console.WriteLine(); 93 - Console.WriteLine(); 94 - Console.WriteLine(); 95 - Console.WriteLine("New Rules!"); 96 - Console.WriteLine(); 97 - foreach (var color1 in colors) 98 - foreach(var color2 in colors) 99 - { 100 - var rule = rnd.NextSingle() - 0.5f; 101 - Rules.Add((color1, color2), rule); 102 - Console.WriteLine($"Rules.Add((Color.{color1.Name}, Color.{color2.Name}), {rule.ToString(CultureInfo.InvariantCulture)}f);"); 103 - } 104 - } 105 - 106 - private static void VirusRule() 107 - { 108 - Rules.Clear(); 109 - Rules.Add((Color.Yellow, Color.Yellow), 0.16813803f); 110 - Rules.Add((Color.Yellow, Color.Red), -0.13937545f); 111 - Rules.Add((Color.Yellow, Color.Green), 0.15008587f); 112 - Rules.Add((Color.Yellow, Color.White), -0.3598255f); 113 - Rules.Add((Color.Red, Color.Yellow), 0.12564862f); 114 - Rules.Add((Color.Red, Color.Red), 0.096319795f); 115 - Rules.Add((Color.Red, Color.Green), -0.12434393f); 116 - Rules.Add((Color.Red, Color.White), -0.23231715f); 117 - Rules.Add((Color.Green, Color.Yellow), 0.46440452f); 118 - Rules.Add((Color.Green, Color.Red), 0.38713688f); 119 - Rules.Add((Color.Green, Color.Green), -0.36697257f); 120 - Rules.Add((Color.Green, Color.White), -0.033506453f); 121 - Rules.Add((Color.White, Color.Yellow), -0.35188568f); 122 - Rules.Add((Color.White, Color.Red), 0.1912772f); 123 - Rules.Add((Color.White, Color.Green), 0.3761289f); 124 - Rules.Add((Color.White, Color.White), 0.059764445f); 125 - } 126 - 127 - private static void Draw(float deltaTime, ISpriteBatch spriteBatch) 128 - { 129 - foreach(var rule in Rules) 130 - { 131 - if (!Groups.TryGetValue(rule.Key.Item1, out var units1) || 132 - !Groups.TryGetValue(rule.Key.Item2, out var units2)) 133 - continue; 134 - 135 - Rule(deltaTime, units1, units2, rule.Value); 136 - } 137 - 138 - foreach(var pair in Groups) 139 - { 140 - foreach(var unit in pair.Value) 141 - { 142 - var rect = new RectangleF(unit.Position.X, unit.Position.Y, 4, 4); 143 - 144 - var colorF = new ColorF(pair.Key) / 2; 145 - var length = unit.Speed.Length(); 146 - colorF += colorF * length/ (length + 50); 147 - colorF.A = 0.5f; 148 - 149 - spriteBatch.DrawRect(rect, colorF, 1); 150 - } 151 - } 152 - } 153 - 154 - private static void Main(string[] args) 155 - { 156 - var title = "Peridot.Sample2"; 157 - var wci = new WindowCreateInfo(100, 100, 640, 480, WindowState.Normal, title); 158 - 159 - var window = VeldridStartup.CreateWindow(wci); 160 - var gd = VeldridStartup.CreateVulkanGraphicsDevice( 161 - new(true, 162 - Veldrid.PixelFormat.D32_Float_S8_UInt, 163 - false, 164 - ResourceBindingModel.Default, 165 - true, 166 - true), 167 - window); 168 - 169 - Bounds = new Size(window.Width, window.Height); 170 - window.Resized += () => 171 - { 172 - Bounds = new Size(window.Width, window.Height); 173 - gd.MainSwapchain.Resize((uint)window.Width, (uint)window.Height); 174 - }; 175 - 176 - window.KeyDown += (e) => 177 - { 178 - if (e.Key == Key.G) 179 - Gen(); 180 - else if (e.Key == Key.V) 181 - VirusRule(); 182 - else if (e.Key == Key.R) 183 - Load(); 184 - }; 185 - 186 - 187 - var peridot = new VPeridot(gd); 188 - 189 - var shaders = peridot.LoadDefaultShaders(); 190 - var sbd = new SpriteBatchDescriptor(gd.MainSwapchain.Framebuffer.OutputDescription, shaders); 191 - var sb = peridot.CreateSpriteBatch(sbd); 192 - 193 - var tr = new TextRenderer(peridot, sb); 194 - var cl = gd.ResourceFactory.CreateCommandList(); 195 - var fence = gd.ResourceFactory.CreateFence(false); 196 - 197 - var time = DateTime.Now; 198 - 199 - Load(); 200 - var count = 0.0; 201 - while (window.Exists) 202 - { 203 - var now = DateTime.Now; 204 - var delta = now - time; 205 - var deltaTime = delta.TotalSeconds; 206 - time = now; 207 - count += deltaTime; 208 - 209 - if (count > 1) 210 - { 211 - count -= 1; 212 - window.Title = title + " " + (1f / deltaTime); 213 - } 214 - 215 - window.PumpEvents(); 216 - 217 - sb.Begin(); 218 - sb.ViewMatrix = Matrix4x4.CreateOrthographicOffCenter(0, Bounds.Width, 0, Bounds.Height, 0.01f, -100f); 219 - 220 - Draw((float)deltaTime, sb); 221 - sb.End(); 222 - 223 - cl.Begin(); 224 - cl.SetFramebuffer(gd.SwapchainFramebuffer); 225 - cl.ClearColorTarget(0, RgbaFloat.Black); 226 - cl.ClearDepthStencil(0f); 227 - cl.DrawBatch(sb); 228 - cl.End(); 229 - 230 - fence.Reset(); 231 - gd.SubmitCommands(cl, fence); 232 - gd.WaitForFence(fence); 233 - gd.SwapBuffers(); 234 - } 235 - } 236 - }
+8 -10
src/Peridot.Veldrid/Resources/shader.vert
··· 1 1 ๏ปฟ#version 450 2 2 3 - layout(constant_id = 0) const bool InvertY = false; 3 + layout (constant_id = 0) const bool InvertY = false; 4 4 5 5 layout(location = 0) in vec2 Position; 6 6 layout(location = 0) out vec4 fsin_Color; ··· 18 18 vec4 scissor; 19 19 }; 20 20 21 - layout(std430, set = 0, binding = 0) readonly buffer Items 22 - { 23 - Item items[]; 24 - }; 25 - 26 - layout(std140, set = 2, binding = 0) uniform View 21 + layout(std430, binding = 0) readonly buffer Items 27 22 { 28 23 mat4 view; 24 + Item items[]; 29 25 }; 30 26 31 27 mat2 makeRotation(float angle) ··· 35 31 return mat2(c, -s, s, c); 36 32 } 37 33 38 - void main() { 34 + void main() 35 + { 39 36 Item item = items[gl_InstanceIndex]; 40 37 41 38 float angle = item.location.w; ··· 45 42 pos += item.location.xy; 46 43 47 44 tex_coord = Position * item.uv.zw + item.uv.xy; 48 - 45 + 49 46 // scissor bounds 50 47 vec2 start = item.scissor.xy; 51 48 vec2 end = start + item.scissor.zw; ··· 54 51 gl_Position = view * vec4(pos, item.location.z, 1); 55 52 pos = gl_Position.xy; 56 53 57 - if (!InvertY) 54 + if(!InvertY) 58 55 gl_Position.y = -gl_Position.y; 56 + 59 57 60 58 fsin_Color = item.color; 61 59 }
+65 -70
src/Peridot.Veldrid/SpriteBatchDescriptor.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using System.Linq; 4 + using System.Threading.Tasks; 1 5 using Veldrid; 2 6 3 7 namespace Peridot 4 8 { 5 - /// <summary> 6 - /// Describes a sprite batch. 7 - /// </summary> 8 - public struct SpriteBatchDescriptor 9 - { 10 - /// <summary> 11 - /// Creates a sprite batch descriptior. 12 - /// </summary> 13 - /// <param name="outputDescription">The output description of target framebuffer.</param> 9 + /// <summary> 10 + /// Describes a sprite batch. 11 + /// </summary> 12 + public struct SpriteBatchDescriptor 13 + { 14 + /// <summary> 15 + /// Creates a sprite batch descriptior. 16 + /// </summary> 17 + /// <param name="outputDescription">The output description of target framebuffer.</param> 14 18 /// <param name="shaders">The shaders to use to render. Uses <seealso cref="VPeridot.LoadDefaultShaders(GraphicsDevice)"/> for default.</param> 15 19 /// <param name="sampler">The samppler used to sample.</param> 16 20 /// <param name="cullMode">Controls which face will be culled. By default the sprite are rendered with forward normal, negatives scales can flips that normal.</param> 17 21 /// <param name="blendState">The blend state description for creating the pipeline.</param> 18 22 /// <param name="depthStencil">The depth stencil state description for creating the pipeline.</param> 19 - /// <param name="sortMode">The drawing order for sprite and text.</param> 20 - public SpriteBatchDescriptor( 21 - OutputDescription outputDescription, 22 - Shader[] shaders, 23 - Sampler? sampler = null, 24 - FaceCullMode cullMode = FaceCullMode.None, 25 - BlendStateDescription? blendState = null, 26 - DepthStencilStateDescription? depthStencil = null, 27 - SortMode sortMode = SortMode.BackToFront) 28 - { 29 - OutputDescription = outputDescription; 30 - Shaders = shaders; 31 - Sampler = sampler; 32 - CullMode = cullMode; 33 - BlendState = blendState; 34 - DepthStencil = depthStencil; 35 - SortMode = sortMode; 36 - 37 - } 38 - 39 - /// <summary> 40 - /// The output description of target framebuffer. 41 - /// </summary> 42 - public OutputDescription OutputDescription { init; get; } 43 - 44 - /// <summary> 45 - /// The shaders to use to render. 46 - /// Uses <seealso cref="VPeridot.LoadDefaultShaders(GraphicsDevice)"/> for default. 47 - /// </summary> 48 - public Shader[] Shaders { init; get; } 49 - 50 - /// <summary> 51 - /// The samppler used to sample. 52 - /// If null, will use LinearSampler. 53 - /// </summary> 54 - public Sampler? Sampler { init; get; } 55 - 56 - /// <summary> 57 - /// Controls which face will be culled. 58 - /// By default the sprite are rendered with forward normal, negatives scales can 59 - /// flips that normal. 60 - /// </summary> 61 - public FaceCullMode CullMode { init; get; } 62 - 63 - /// <summary> 64 - /// The blend state description for creating the pipeline. 65 - /// If null, will use SingleAlphaBlend. 66 - /// </summary> 67 - public BlendStateDescription? BlendState { init; get; } 68 - 69 - /// <summary> 70 - /// The depth stencil state description for creating the pipeline. 71 - /// If null, will use depth test, depth write enable and comparison kind GreaterEqual. 72 - /// </summary> 73 - public DepthStencilStateDescription? DepthStencil { init; get; } 74 - 75 - /// <summary> 76 - /// The sort mode used by SpriteBatch when drawing. 77 - /// </summary> 78 - public SortMode SortMode { init; get; } 79 - } 23 + public SpriteBatchDescriptor( 24 + OutputDescription outputDescription, 25 + Shader[] shaders, 26 + Sampler? sampler = null, 27 + FaceCullMode cullMode = FaceCullMode.None, 28 + BlendStateDescription? blendState = null, 29 + DepthStencilStateDescription? depthStencil = null) 30 + { 31 + OutputDescription = outputDescription; 32 + Shaders = shaders; 33 + Sampler = sampler; 34 + CullMode = cullMode; 35 + BlendState = blendState; 36 + DepthStencil = depthStencil; 37 + } 38 + 39 + /// <summary> 40 + /// The output description of target framebuffer. 41 + /// </summary> 42 + public OutputDescription OutputDescription { init; get; } 43 + 44 + /// <summary> 45 + /// The shaders to use to render. 46 + /// Uses <seealso cref="VPeridot.LoadDefaultShaders(GraphicsDevice)"/> for default. 47 + /// </summary> 48 + public Shader[] Shaders { init; get; } 49 + 50 + /// <summary> 51 + /// The samppler used to sample. 52 + /// If null, will use LinearSampler. 53 + /// </summary> 54 + public Sampler? Sampler { init; get; } 55 + 56 + /// <summary> 57 + /// Controls which face will be culled. 58 + /// By default the sprite are rendered with forward normal, negatives scales can 59 + /// flips that normal. 60 + /// </summary> 61 + public FaceCullMode CullMode { init; get; } 62 + 63 + /// <summary> 64 + /// The blend state description for creating the pipeline. 65 + /// If null, will use SingleAlphaBlend. 66 + /// </summary> 67 + public BlendStateDescription? BlendState { init; get; } 68 + 69 + /// <summary> 70 + /// The depth stencil state description for creating the pipeline. 71 + /// If null, will use depth test, depth write enable and comparison kind GreaterEqual. 72 + /// </summary> 73 + public DepthStencilStateDescription? DepthStencil { init; get; } 74 + } 80 75 }
+52 -52
src/Peridot.Veldrid/VImage.cs
··· 12 12 /// </summary> 13 13 internal class VImage : Image, IEquatable<VImage> 14 14 { 15 - /// <summary> 16 - /// Creates a new instance of <see cref="VImage"/>. 17 - /// </summary> 18 - /// <param name="texture">The texture.</param> 19 - /// <exception cref="ArgumentNullException"></exception> 20 - public VImage(Texture texture) 21 - { 22 - Texture = texture ?? throw new ArgumentNullException(nameof(texture)); 23 - } 24 - 25 - /// <summary> 26 - /// Texture 27 - /// </summary> 28 - public Texture Texture { get; } 15 + /// <summary> 16 + /// Creates a new instance of <see cref="VImage"/>. 17 + /// </summary> 18 + /// <param name="texture">The texture.</param> 19 + /// <exception cref="ArgumentNullException"></exception> 20 + public VImage(Texture texture) 21 + { 22 + Texture = texture ?? throw new ArgumentNullException(nameof(texture)); 23 + } 29 24 30 - /// <summary> 31 - /// Size of texture 32 - /// </summary> 33 - public Size Size => new((int)Texture.Width, (int)Texture.Height); 25 + /// <summary> 26 + /// Texture 27 + /// </summary> 28 + public Texture Texture { get; } 34 29 35 - /// <inheritdoc/> 36 - public bool IsDisposed => Texture.IsDisposed; 30 + /// <summary> 31 + /// Size of texture 32 + /// </summary> 33 + public Size Size => new((int)Texture.Width, (int)Texture.Height); 37 34 38 - /// <inheritdoc/> 39 - public PixelFormat Format => Texture.Format switch 40 - { 41 - Veldrid.PixelFormat.R8_UNorm => PixelFormat.R8, 42 - Veldrid.PixelFormat.R16_UNorm => PixelFormat.R16, 43 - Veldrid.PixelFormat.B8_G8_R8_A8_UNorm => PixelFormat.BGRA8, 44 - Veldrid.PixelFormat.R32_G32_B32_A32_Float => PixelFormat.RGBAF32, 45 - Veldrid.PixelFormat.R8_G8_UNorm => PixelFormat.RG8, 46 - Veldrid.PixelFormat.R16_G16_UNorm => PixelFormat.RG16, 47 - Veldrid.PixelFormat.R32_G32_B32_A32_SInt => PixelFormat.RGBAI32, 48 - Veldrid.PixelFormat.R8_G8_B8_A8_UNorm => PixelFormat.RGBA8, 49 - _ => PixelFormat.Undefined 50 - }; 35 + /// <inheritdoc/> 36 + public bool IsDisposed => Texture.IsDisposed; 51 37 52 - /// <inheritdoc/> 53 - public override int GetHashCode() => Texture.GetHashCode(); 38 + /// <inheritdoc/> 39 + public PixelFormat Format => Texture.Format switch 40 + { 41 + Veldrid.PixelFormat.R8_UNorm => PixelFormat.R8, 42 + Veldrid.PixelFormat.R16_UNorm => PixelFormat.R16, 43 + Veldrid.PixelFormat.B8_G8_R8_A8_UNorm => PixelFormat.BGRA8, 44 + Veldrid.PixelFormat.R32_G32_B32_A32_Float => PixelFormat.RGBAF32, 45 + Veldrid.PixelFormat.R8_G8_UNorm => PixelFormat.RG8, 46 + Veldrid.PixelFormat.R16_G16_UNorm => PixelFormat.RG16, 47 + Veldrid.PixelFormat.R32_G32_B32_A32_SInt => PixelFormat.RGBAI32, 48 + Veldrid.PixelFormat.R8_G8_B8_A8_UNorm => PixelFormat.RGBA8, 49 + _ => PixelFormat.Undefined 50 + }; 54 51 55 - /// <inheritdoc/> 56 - public bool Equals(VImage? other) => Texture == other?.Texture; 52 + /// <inheritdoc/> 53 + public override int GetHashCode() => Texture.GetHashCode(); 57 54 58 - /// <inheritdoc/> 59 - public override bool Equals([NotNullWhen(true)] object? obj) => 60 - obj is VImage tw && Equals(tw); 55 + /// <inheritdoc/> 56 + public bool Equals(VImage? other) => Texture == other?.Texture; 61 57 62 - /// <inheritdoc/> 63 - public override string? ToString() => Texture.ToString(); 58 + /// <inheritdoc/> 59 + public override bool Equals([NotNullWhen(true)] object? obj) => 60 + obj is VImage tw && Equals(tw); 64 61 65 - /// <inheritdoc/> 66 - public void Dispose() 67 - { 68 - Texture.Dispose(); 69 - GC.SuppressFinalize(this); 70 - } 62 + /// <inheritdoc/> 63 + public override string? ToString() => Texture.ToString(); 71 64 72 - public static implicit operator VImage(Texture t) => new(t); 65 + /// <inheritdoc/> 66 + public void Dispose() 67 + { 68 + Texture.Dispose(); 69 + GC.SuppressFinalize(this); 70 + } 73 71 74 - public static implicit operator Texture(VImage t) => t.Texture; 72 + public static implicit operator VImage(Texture t) => new(t); 75 73 76 - public static bool operator ==(VImage left, VImage right) => left.Equals(right); 74 + public static implicit operator Texture(VImage t) => t.Texture; 75 + 76 + public static bool operator ==(VImage left, VImage right) => left.Equals(right); 77 77 78 - public static bool operator !=(VImage left, VImage right) => !(left == right); 78 + public static bool operator !=(VImage left, VImage right) => !(left == right); 79 79 }
+86 -112
src/Peridot.Veldrid/VPeridot.cs
··· 1 1 using System.Diagnostics; 2 - using System.Drawing; 3 2 using System.Text; 4 3 using Veldrid; 5 4 using Veldrid.SPIRV; ··· 8 7 9 8 public class VPeridot : IPeridot<Texture, SpriteBatchDescriptor> 10 9 { 11 - private readonly GraphicsDevice m_gd; 12 - private readonly Image m_whiteImage; 13 - public VPeridot(GraphicsDevice gd) 14 - { 15 - m_gd = gd; 16 - m_whiteImage = CreateImage(new ImageDescription() 17 - { 18 - Format = PixelFormat.BGRA8, 19 - Width = 1, 20 - Height = 1, 21 - }); 22 - 23 - UpdateImage<byte>(m_whiteImage, new byte[] { 255, 255, 255, 255 }, 0, 0, 1, 1); 24 - } 25 - 26 - internal GraphicsDevice GraphicsDevice => m_gd; 10 + private readonly GraphicsDevice m_gd; 11 + private readonly Image m_whiteImage; 12 + public VPeridot(GraphicsDevice gd) 13 + { 14 + m_gd = gd; 15 + m_whiteImage = CreateImage(new ImageDescription() 16 + { 17 + Format = PixelFormat.BGRA8, 18 + Width = 1, 19 + Height = 1, 20 + }); 27 21 28 - /// <inheritdoc/> 29 - public Image CreateImage(ImageDescription description) 30 - { 31 - var pf = description.Format switch 32 - { 33 - PixelFormat.R8 => VPF.R8_UNorm, 34 - PixelFormat.R16 => VPF.R16_UNorm, 35 - PixelFormat.BGRA8 => VPF.B8_G8_R8_A8_UNorm, 36 - PixelFormat.RGBAF32 => VPF.R32_G32_B32_A32_Float, 37 - PixelFormat.RG8 => VPF.R8_G8_UNorm, 38 - PixelFormat.RG16 => VPF.R16_G16_UNorm, 39 - PixelFormat.RGBAI32 => VPF.R8_G8_B8_A8_SInt, 40 - PixelFormat.RGBA8 => VPF.R8_G8_B8_A8_UNorm, 41 - _ => throw new ArgumentOutOfRangeException(nameof(description.Format)) 42 - }; 43 - TextureDescription desc = new(description.Width, description.Height, 1, 1, 1, pf, TextureUsage.Sampled, TextureType.Texture2D); 44 - return new VImage(m_gd.ResourceFactory.CreateTexture(desc)); 45 - } 22 + UpdateImage<byte>(m_whiteImage, new byte[] { 255, 255, 255, 255 }, 0, 0, 1, 1); 23 + } 46 24 47 - /// <inheritdoc/> 48 - public void UpdateImage<T>(Image image, ReadOnlySpan<T> source, uint x, uint y, uint width, uint height) where T : unmanaged 49 - { 50 - Debug.Assert(image is VImage); 51 - if (image is not VImage vimage) 52 - throw new ArgumentOutOfRangeException(nameof(image)); 53 - 54 - unsafe 55 - { 56 - uint size = (uint)source.Length * (uint)sizeof(T); 57 - fixed (T* ptr = source) 58 - { 59 - m_gd.UpdateTexture(vimage, (IntPtr)ptr, size, x, y, 0, width, height, 1, 0, 0); 60 - } 61 - } 62 - } 63 - 64 - /// <inheritdoc/> 65 - public ISpriteBatch<Texture> CreateSpriteBatch(SpriteBatchDescriptor descriptor) 66 - { 67 - var s = descriptor.Sampler ?? GraphicsDevice.LinearSampler; 68 - var bs = descriptor.BlendState ?? BlendStateDescription.SingleAlphaBlend; 69 - var ds = descriptor.DepthStencil ?? new( 70 - depthTestEnabled: true, 71 - depthWriteEnabled: true, 72 - comparisonKind: ComparisonKind.GreaterEqual); 73 - 74 - return new VSpriteBatch( 75 - this, 76 - m_whiteImage, 77 - descriptor.OutputDescription, 78 - descriptor.Shaders, 79 - s, 80 - descriptor.CullMode, 81 - bs, 82 - ds, 83 - descriptor.SortMode); 84 - } 85 - 86 - /// <summary> 87 - /// Loads default shaders for <see cref="ISpriteBatch"/>. 88 - /// </summary> 89 - /// <returns>Shaders for use in <see cref="ISpriteBatch"/>.</returns> 90 - public Shader[] LoadDefaultShaders() 91 - { 92 - 93 - var vertexShaderDesc = new ShaderDescription( 94 - ShaderStages.Vertex, 95 - Encoding.UTF8.GetBytes(Resource.shader_vert), 96 - "main"); 25 + internal GraphicsDevice GraphicsDevice => m_gd; 97 26 98 - var fragmentShaderDesc = new ShaderDescription( 99 - ShaderStages.Fragment, 100 - Encoding.UTF8.GetBytes(Resource.shader_frag), 101 - "main"); 27 + /// <inheritdoc/> 28 + public Image CreateImage(ImageDescription description) 29 + { 30 + var pf = description.Format switch 31 + { 32 + PixelFormat.R8 => VPF.R8_UNorm, 33 + PixelFormat.R16 => VPF.R16_UNorm, 34 + PixelFormat.BGRA8 => VPF.B8_G8_R8_A8_UNorm, 35 + PixelFormat.RGBAF32 => VPF.R32_G32_B32_A32_Float, 36 + PixelFormat.RG8 => VPF.R8_G8_UNorm, 37 + PixelFormat.RG16 => VPF.R16_G16_UNorm, 38 + PixelFormat.RGBAI32 => VPF.R8_G8_B8_A8_SInt, 39 + PixelFormat.RGBA8 => VPF.R8_G8_B8_A8_UNorm, 40 + _ => throw new ArgumentOutOfRangeException(nameof(description.Format)) 41 + }; 42 + TextureDescription desc = new(description.Width, description.Height, 1, 1, 1, pf, TextureUsage.Sampled, TextureType.Texture2D); 43 + return new VImage(m_gd.ResourceFactory.CreateTexture(desc)); 44 + } 102 45 103 - return GraphicsDevice.ResourceFactory.CreateFromSpirv(vertexShaderDesc, fragmentShaderDesc); 104 - } 46 + /// <inheritdoc/> 47 + public void UpdateImage<T>(Image image, ReadOnlySpan<T> source, uint x, uint y, uint width, uint height) where T : unmanaged 48 + { 49 + Debug.Assert(image is VImage); 50 + if (image is not VImage vimage) 51 + throw new ArgumentOutOfRangeException(nameof(image)); 105 52 106 - ISpriteBatch IPeridot<SpriteBatchDescriptor>.CreateSpriteBatch(SpriteBatchDescriptor description) 107 - { 108 - return CreateSpriteBatch(description); 109 - } 53 + unsafe 54 + { 55 + uint size = (uint)source.Length * (uint)sizeof(T); 56 + fixed (T* ptr = source) 57 + { 58 + m_gd.UpdateTexture(vimage, (IntPtr)ptr, size, x, y, 0, width, height, 1, 0, 0); 59 + } 60 + } 61 + } 110 62 111 - public void CopyImage(Image source, Image destination, uint sx, uint sy, uint dx, uint dy, uint width, uint height) 112 - { 113 - Debug.Assert(source is VImage); 114 - if (source is not VImage vsrc) 115 - throw new ArgumentOutOfRangeException(nameof(source)); 63 + /// <inheritdoc/> 64 + public ISpriteBatch<Texture> CreateSpriteBatch(SpriteBatchDescriptor descriptor) 65 + { 66 + var s = descriptor.Sampler ?? GraphicsDevice.LinearSampler; 67 + var bs = descriptor.BlendState ?? BlendStateDescription.SingleAlphaBlend; 68 + var ds = descriptor.DepthStencil ?? new( 69 + depthTestEnabled: true, 70 + depthWriteEnabled: true, 71 + comparisonKind: ComparisonKind.GreaterEqual); 116 72 117 - if (destination is not VImage vdst) 118 - throw new ArgumentOutOfRangeException(nameof(destination)); 73 + return new VSpriteBatch( 74 + this, 75 + m_whiteImage, 76 + descriptor.OutputDescription, 77 + descriptor.Shaders, 78 + s, 79 + descriptor.CullMode, 80 + bs, 81 + ds); 82 + } 119 83 84 + /// <summary> 85 + /// Loads default shaders for <see cref="ISpriteBatch"/>. 86 + /// </summary> 87 + /// <returns>Shaders for use in <see cref="ISpriteBatch"/>.</returns> 88 + public Shader[] LoadDefaultShaders() 89 + { 120 90 121 - var cmd = m_gd.ResourceFactory.CreateCommandList(); 122 - var fence = m_gd.ResourceFactory.CreateFence(false); 91 + var vertexShaderDesc = new ShaderDescription( 92 + ShaderStages.Vertex, 93 + Encoding.UTF8.GetBytes(Resource.shader_vert), 94 + "main"); 123 95 124 - cmd.Begin(); 125 - cmd.CopyTexture(vsrc, sx, sy, 0, 0, 0, vdst, dx, dy, 0, 0, 0, width, height, 1, 1); 126 - cmd.End(); 96 + var fragmentShaderDesc = new ShaderDescription( 97 + ShaderStages.Fragment, 98 + Encoding.UTF8.GetBytes(Resource.shader_frag), 99 + "main"); 127 100 128 - m_gd.SubmitCommands(cmd, fence); 129 - m_gd.WaitForFence(fence); 101 + return GraphicsDevice.ResourceFactory.CreateFromSpirv(vertexShaderDesc, fragmentShaderDesc); 102 + } 130 103 131 - cmd.Dispose(); 132 - fence.Dispose(); 133 - } 104 + ISpriteBatch IPeridot<SpriteBatchDescriptor>.CreateSpriteBatch(SpriteBatchDescriptor description) 105 + { 106 + return CreateSpriteBatch(description); 107 + } 134 108 }
+164 -204
src/Peridot.Veldrid/VSpriteBatch.cs
··· 1 - ๏ปฟusing System.Collections.Generic; 2 1 // Copyright (c) 2021 ezequias2d <ezequiasmoises@gmail.com> and the Peridot contributors 3 2 // This code is licensed under MIT license (see LICENSE for details) 4 3 ··· 10 9 11 10 namespace Peridot 12 11 { 13 - /// <inheritdoc/> 14 - internal class VSpriteBatch : SpriteBatch<Texture> 15 - { 16 - private readonly GraphicsDevice m_device; 17 - private readonly DeviceBuffer m_vertexBuffer; 18 - private readonly Sampler m_sampler; 19 - private readonly SortMode m_sortMode; 20 - private Pipeline m_pipeline; 21 - private readonly ResourceLayout[] m_resourceLayouts; 22 - 23 - private readonly DeviceBuffer m_viewBuffer; 24 - private readonly ResourceSet m_viewSet; 25 - private DeviceBuffer m_buffer; 26 - private ResourceSet m_bufferSet; 27 - 28 - private Dictionary<Texture, ResourceSet> m_textureSets; 29 - 30 - internal VSpriteBatch( 31 - VPeridot peridot, 32 - Image whiteImage, 33 - OutputDescription outputDescription, 34 - Shader[] shaders, 35 - Sampler sampler, 36 - FaceCullMode cullMode, 37 - BlendStateDescription blendState, 38 - DepthStencilStateDescription depthStencil, 39 - SortMode sortMode) : base(whiteImage) 40 - { 41 - m_device = peridot.GraphicsDevice; 42 - m_sampler = sampler ?? m_device.LinearSampler; 43 - m_vertexBuffer = CreateVertexBuffer(m_device); 44 - m_resourceLayouts = CreateResourceLayouts(m_device); 45 - m_textureSets = new(); 46 - 47 - var bs = blendState; 48 - var ds = depthStencil; 49 - m_pipeline = CreatePipeline(m_device, outputDescription, cullMode, bs, ds, shaders, m_resourceLayouts); 50 - m_sortMode = sortMode; 51 - 52 - m_viewBuffer = m_device.ResourceFactory.CreateBuffer(new BufferDescription(MemUtil.SizeOf<Matrix4x4>(), BufferUsage.UniformBuffer | BufferUsage.Dynamic)); 53 - m_viewSet = m_device.ResourceFactory.CreateResourceSet(new(m_resourceLayouts[2], m_viewBuffer)); 54 - } 55 - 56 - /// <summary> 57 - /// Draw this branch into a <see cref="CommandList"/>. 58 - /// Call this after calling <see cref="SpriteBatch{TTexture}.End"/> 59 - /// </summary> 60 - /// <param name="commandList"></param> 61 - public void DrawBatch(CommandList commandList) 62 - { 63 - var matrixSize = (int)MemUtil.SizeOf<Matrix4x4>(); 64 - commandList.SetPipeline(m_pipeline); 12 + /// <inheritdoc/> 13 + internal class VSpriteBatch : SpriteBatch<Texture> 14 + { 15 + private readonly GraphicsDevice m_device; 16 + private readonly DeviceBuffer m_vertexBuffer; 17 + private readonly Sampler m_sampler; 18 + private Pipeline m_pipeline; 19 + private readonly ResourceLayout[] m_resourceLayouts; 20 + private Dictionary<Texture, (DeviceBuffer buffer, ResourceSet set, ResourceSet textureSet)> m_buffers; 65 21 66 - m_batcher.Build(m_sortMode); 67 - var (buffer, bufferSet) = GetBuffer(m_batcher.Items.Length); 68 - var itemSize = MemUtil.SizeOf<BatchItem>(); 22 + internal VSpriteBatch( 23 + VPeridot peridot, 24 + Image whiteImage, 25 + OutputDescription outputDescription, 26 + Shader[] shaders, 27 + Sampler sampler, 28 + FaceCullMode cullMode, 29 + BlendStateDescription blendState, 30 + DepthStencilStateDescription depthStencil) : base(whiteImage) 31 + { 32 + m_device = peridot.GraphicsDevice; 33 + m_sampler = sampler ?? m_device.LinearSampler; 34 + m_vertexBuffer = CreateVertexBuffer(m_device); 35 + m_resourceLayouts = CreateResourceLayouts(m_device); 36 + m_buffers = new(); 69 37 70 - var mapped = m_device.Map(m_viewBuffer, MapMode.Write); 71 - MemUtil.Set(mapped.Data, ViewMatrix, 1); 72 - m_device.Unmap(m_viewBuffer); 38 + var bs = blendState; 39 + var ds = depthStencil; 40 + m_pipeline = CreatePipeline(m_device, outputDescription, cullMode, bs, ds, shaders, m_resourceLayouts); 41 + } 73 42 74 - mapped = m_device.Map(buffer, MapMode.Write); 75 - MemUtil.Copy(mapped.Data, m_batcher.Items); 76 - m_device.Unmap(buffer); 43 + /// <summary> 44 + /// Draw this branch into a <see cref="CommandList"/>. 45 + /// Call this after calling <see cref="SpriteBatch{TTexture}.End"/> 46 + /// </summary> 47 + /// <param name="commandList"></param> 48 + public void DrawBatch(CommandList commandList) 49 + { 50 + var matrixSize = MemUtil.SizeOf<Matrix4x4>(); 51 + commandList.SetPipeline(m_pipeline); 52 + foreach (var item in m_batcher) 53 + { 54 + var texture = item.Key; 55 + var group = item.Value; 77 56 78 - foreach (var slice in m_batcher.Slices) 79 - { 80 - var textureSet = GetTextureSet(slice.Texture); 57 + var structSize = MemUtil.SizeOf<BatchItem>(); 81 58 82 - commandList.SetVertexBuffer(0, m_vertexBuffer); 83 - uint offset = (uint)slice.Start * itemSize; 84 - commandList.SetGraphicsResourceSet(0, bufferSet, 1, ref offset); 85 - commandList.SetGraphicsResourceSet(1, textureSet); 86 - commandList.SetGraphicsResourceSet(2, m_viewSet); 87 - commandList.Draw(4, (uint)slice.Length, 0, 0); 88 - } 89 - } 59 + // align count to 64 items 60 + var count = (((uint)group.Count + 63u) & (~63u)); 61 + var size = count * structSize + matrixSize; 90 62 91 - internal (DeviceBuffer, ResourceSet) GetBuffer(int count) 92 - { 93 - var structSize = MemUtil.SizeOf<BatchItem>(); 94 - var size = ((count + 63) & (~63)) * structSize; 95 - var bci = new BufferDescription((uint)size, BufferUsage.StructuredBufferReadOnly | BufferUsage.Dynamic, structSize); 63 + var pair = GetBuffer(texture, size); 64 + var mapped = m_device.Map(pair.buffer, MapMode.Write); 96 65 97 - if (m_buffer == null || m_buffer.SizeInBytes < size) 98 - { 99 - if (m_buffer != null) 100 - { 101 - m_buffer.Dispose(); 102 - m_bufferSet.Dispose(); 103 - } 104 - m_buffer = m_device.ResourceFactory.CreateBuffer(bci); 105 - m_bufferSet = m_device.ResourceFactory.CreateResourceSet(new(m_resourceLayouts[0], m_buffer)); 106 - m_buffer.Name = "ItemBuffer"; 107 - } 66 + MemUtil.Set(mapped.Data, ViewMatrix, 1); 67 + MemUtil.Copy(mapped.Data + (int)matrixSize, group.GetSpan()); 108 68 109 - return (m_buffer, m_bufferSet); 110 - } 69 + m_device.Unmap(pair.buffer); 111 70 112 - internal uint CalculateStructuredAlignment<T>() where T : unmanaged 113 - { 114 - var minUbo = m_device.StructuredBufferMinOffsetAlignment; 71 + commandList.SetVertexBuffer(0, m_vertexBuffer); 72 + commandList.SetGraphicsResourceSet(0, pair.set); 73 + commandList.SetGraphicsResourceSet(1, pair.textureSet); 74 + commandList.Draw(4, (uint)group.Count, 0, 0); 75 + } 76 + } 115 77 116 - var alignment = MemUtil.SizeOf<T>(); 117 - if (minUbo > 0) 118 - { 119 - alignment = (alignment + minUbo - 1) & ~(minUbo - 1); 120 - } 121 - return alignment; 122 - } 78 + internal (DeviceBuffer buffer, ResourceSet set, ResourceSet textureSet) GetBuffer(Texture t, uint bufferSize) 79 + { 80 + var texture = t as Texture; 81 + var bci = new BufferDescription(bufferSize, BufferUsage.StructuredBufferReadOnly | BufferUsage.Dynamic, bufferSize); 123 82 124 - internal ResourceSet GetTextureSet(Texture t) 125 - { 126 - var texture = t as Texture; 127 - var structSize = MemUtil.SizeOf<BatchItem>(); 83 + if (!m_buffers.TryGetValue(texture, out var pair)) 84 + { 85 + pair.buffer = m_device.ResourceFactory.CreateBuffer(bci); 86 + pair.set = m_device.ResourceFactory.CreateResourceSet(new ResourceSetDescription(m_resourceLayouts[0], pair.buffer)); 87 + pair.textureSet = m_device.ResourceFactory.CreateResourceSet(new ResourceSetDescription(m_resourceLayouts[1], texture, m_sampler)); 88 + m_buffers[texture] = pair; 89 + } 90 + else if (bufferSize > pair.buffer.SizeInBytes) 91 + { 92 + pair.set.Dispose(); 93 + pair.buffer.Dispose(); 128 94 129 - if (!m_textureSets.TryGetValue(texture, out var set)) 130 - { 131 - set = 132 - m_textureSets[texture] = 133 - m_device.ResourceFactory.CreateResourceSet(new ResourceSetDescription(m_resourceLayouts[1], texture, m_sampler)); 134 - } 135 - return set; 136 - } 95 + pair.buffer = m_device.ResourceFactory.CreateBuffer(bci); 96 + pair.set = m_device.ResourceFactory.CreateResourceSet(new ResourceSetDescription(m_resourceLayouts[0], pair.buffer)); 97 + pair.textureSet = m_device.ResourceFactory.CreateResourceSet(new ResourceSetDescription(m_resourceLayouts[1], texture, m_sampler)); 98 + m_buffers[texture] = pair; 99 + } 137 100 138 - /// <inheritdoc/> 139 - protected override void Dispose(bool disposing) 140 - { 141 - if (disposing) 142 - { 143 - m_vertexBuffer.Dispose(); 144 - } 145 - } 101 + return pair; 102 + } 146 103 147 - private static DeviceBuffer CreateVertexBuffer(GraphicsDevice device) 148 - { 149 - var bd = new BufferDescription() 150 - { 151 - SizeInBytes = 4 * MemUtil.SizeOf<Vector2>(), 152 - Usage = BufferUsage.VertexBuffer, 153 - }; 104 + /// <inheritdoc/> 105 + protected override void Dispose(bool disposing) 106 + { 107 + if (disposing) 108 + { 109 + m_vertexBuffer.Dispose(); 110 + } 111 + } 154 112 155 - var buffer = device.ResourceFactory.CreateBuffer(bd); 113 + private static DeviceBuffer CreateVertexBuffer(GraphicsDevice device) 114 + { 115 + var bd = new BufferDescription() 116 + { 117 + SizeInBytes = 4 * MemUtil.SizeOf<Vector2>(), 118 + Usage = BufferUsage.VertexBuffer, 119 + }; 156 120 157 - var vertices = new Vector2[] 158 - { 159 - new( 0, 0), 160 - new( 1, 0), 161 - new( 0, 1), 162 - new( 1, 1) 163 - }; 121 + var buffer = device.ResourceFactory.CreateBuffer(bd); 164 122 165 - device.UpdateBuffer(buffer, 0, vertices); 123 + var vertices = new Vector2[] 124 + { 125 + new( 0, 0), 126 + new( 1, 0), 127 + new( 0, 1), 128 + new( 1, 1) 129 + }; 166 130 167 - return buffer; 168 - } 131 + device.UpdateBuffer(buffer, 0, vertices); 169 132 170 - private static ResourceLayout[] CreateResourceLayouts(GraphicsDevice device) 171 - { 172 - var layouts = new ResourceLayout[3]; 133 + return buffer; 134 + } 173 135 174 - var elements = new ResourceLayoutElementDescription[] 175 - { 176 - new("Items", ResourceKind.StructuredBufferReadOnly, ShaderStages.Vertex, ResourceLayoutElementOptions.DynamicBinding), 177 - }; 178 - var rld = new ResourceLayoutDescription(elements); 179 - layouts[0] = device.ResourceFactory.CreateResourceLayout(rld); 136 + private static ResourceLayout[] CreateResourceLayouts(GraphicsDevice device) 137 + { 138 + var layouts = new ResourceLayout[2]; 180 139 181 - elements = new ResourceLayoutElementDescription[] 182 - { 183 - new("Tex", ResourceKind.TextureReadOnly, ShaderStages.Fragment), 184 - new("Sampler", ResourceKind.Sampler, ShaderStages.Fragment) 185 - }; 186 - rld = new ResourceLayoutDescription(elements); 187 - layouts[1] = device.ResourceFactory.CreateResourceLayout(rld); 140 + var elements = new ResourceLayoutElementDescription[] 141 + { 142 + new("Items", ResourceKind.StructuredBufferReadOnly, ShaderStages.Vertex), 143 + }; 144 + var rld = new ResourceLayoutDescription(elements); 188 145 189 - elements = new ResourceLayoutElementDescription[] 190 - { 191 - new("View", ResourceKind.UniformBuffer, ShaderStages.Vertex) 192 - }; 193 - rld = new ResourceLayoutDescription(elements); 194 - layouts[2] = device.ResourceFactory.CreateResourceLayout(rld); 146 + layouts[0] = device.ResourceFactory.CreateResourceLayout(rld); 195 147 196 - return layouts; 197 - } 148 + elements = new ResourceLayoutElementDescription[] 149 + { 150 + new("Tex", ResourceKind.TextureReadOnly, ShaderStages.Fragment), 151 + new("Sampler", ResourceKind.Sampler, ShaderStages.Fragment) 152 + }; 153 + rld = new ResourceLayoutDescription(elements); 198 154 199 - private static Pipeline CreatePipeline(GraphicsDevice device, 200 - OutputDescription outputDescription, 201 - FaceCullMode cullMode, 202 - BlendStateDescription blendState, 203 - DepthStencilStateDescription depthStencil, 204 - Shader[] shaders, 205 - params ResourceLayout[] layouts) 206 - { 207 - var vertexLayout = new VertexLayoutDescription( 208 - new VertexElementDescription("Position", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float2)); 155 + layouts[1] = device.ResourceFactory.CreateResourceLayout(rld); 156 + return layouts; 157 + } 209 158 210 - var pipelineDescription = new GraphicsPipelineDescription 211 - { 212 - BlendState = blendState, 213 - DepthStencilState = depthStencil, 214 - RasterizerState = new( 215 - cullMode: cullMode, 216 - fillMode: PolygonFillMode.Solid, 217 - frontFace: FrontFace.Clockwise, 218 - depthClipEnabled: true, 219 - scissorTestEnabled: false), 220 - PrimitiveTopology = PrimitiveTopology.TriangleStrip, 221 - ResourceLayouts = layouts, 222 - ShaderSet = new( 223 - vertexLayouts: new[] { vertexLayout }, 224 - shaders: shaders, 225 - specializations: new[] { new SpecializationConstant(0, device.IsClipSpaceYInverted) }), 226 - Outputs = outputDescription, 227 - }; 159 + private static Pipeline CreatePipeline(GraphicsDevice device, 160 + OutputDescription outputDescription, 161 + FaceCullMode cullMode, 162 + BlendStateDescription blendState, 163 + DepthStencilStateDescription depthStencil, 164 + Shader[] shaders, 165 + params ResourceLayout[] layouts) 166 + { 167 + var vertexLayout = new VertexLayoutDescription( 168 + new VertexElementDescription("Position", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float2)); 228 169 229 - return device.ResourceFactory.CreateGraphicsPipeline(pipelineDescription); 230 - } 170 + var pipelineDescription = new GraphicsPipelineDescription 171 + { 172 + BlendState = blendState, 173 + DepthStencilState = depthStencil, 174 + RasterizerState = new( 175 + cullMode: cullMode, 176 + fillMode: PolygonFillMode.Solid, 177 + frontFace: FrontFace.Clockwise, 178 + depthClipEnabled: true, 179 + scissorTestEnabled: false), 180 + PrimitiveTopology = PrimitiveTopology.TriangleStrip, 181 + ResourceLayouts = layouts, 182 + ShaderSet = new( 183 + vertexLayouts: new[] { vertexLayout }, 184 + shaders: shaders, 185 + specializations: new[] { new SpecializationConstant(0, device.IsClipSpaceYInverted) }), 186 + Outputs = outputDescription, 187 + }; 231 188 232 - protected override Size GetSize(Texture image) 233 - { 234 - return new((int)image.Width, (int)image.Height); 235 - } 189 + return device.ResourceFactory.CreateGraphicsPipeline(pipelineDescription); 190 + } 236 191 237 - protected override Texture GetHandle(Image image) 238 - { 239 - if (image is not VImage vimage) 240 - throw new InvalidCastException($"The {image} is not supported by this implementation."); 241 - return vimage.Texture; 242 - } 243 - } 192 + protected override Size GetSize(Texture image) 193 + { 194 + return new((int)image.Width, (int)image.Height); 195 + } 196 + 197 + protected override Texture GetHandle(Image image) 198 + { 199 + if (image is not VImage vimage) 200 + throw new InvalidCastException($"The {image} is not supported by this implementation."); 201 + return vimage.Texture; 202 + } 203 + } 244 204 }