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