A game framework written with osu! in mind.
1// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
2// See the LICENCE file in the repository root for full licence text.
3
4using System;
5using System.Diagnostics.CodeAnalysis;
6using osuTK.Graphics.ES30;
7
8namespace osu.Framework.Graphics
9{
10 /// <summary>
11 /// Contains information about how an <see cref="IDrawable"/> should be blended into its destination.
12 /// </summary>
13 public struct BlendingParameters : IEquatable<BlendingParameters>
14 {
15 #region Public Members
16
17 /// <summary>
18 /// The blending factor for the source color of the blend.
19 /// </summary>
20 public BlendingType Source;
21
22 /// <summary>
23 /// The blending factor for the destination color of the blend.
24 /// </summary>
25 public BlendingType Destination;
26
27 /// <summary>
28 /// The blending factor for the source alpha of the blend.
29 /// </summary>
30 public BlendingType SourceAlpha;
31
32 /// <summary>
33 /// The blending factor for the destination alpha of the blend.
34 /// </summary>
35 public BlendingType DestinationAlpha;
36
37 /// <summary>
38 /// Gets or sets the <see cref="BlendingEquation"/> to use for the RGB components of the blend.
39 /// </summary>
40 public BlendingEquation RGBEquation;
41
42 /// <summary>
43 /// Gets or sets the <see cref="BlendingEquation"/> to use for the alpha component of the blend.
44 /// </summary>
45 public BlendingEquation AlphaEquation;
46
47 #endregion
48
49 #region Default Blending Parameter Types
50
51 public static BlendingParameters None => new BlendingParameters
52 {
53 Source = BlendingType.One,
54 Destination = BlendingType.Zero,
55 SourceAlpha = BlendingType.One,
56 DestinationAlpha = BlendingType.Zero,
57 RGBEquation = BlendingEquation.Add,
58 AlphaEquation = BlendingEquation.Add,
59 };
60
61 public static BlendingParameters Inherit => new BlendingParameters
62 {
63 Source = BlendingType.Inherit,
64 Destination = BlendingType.Inherit,
65 SourceAlpha = BlendingType.Inherit,
66 DestinationAlpha = BlendingType.Inherit,
67 RGBEquation = BlendingEquation.Inherit,
68 AlphaEquation = BlendingEquation.Inherit,
69 };
70
71 public static BlendingParameters Mixture => new BlendingParameters
72 {
73 Source = BlendingType.SrcAlpha,
74 Destination = BlendingType.OneMinusSrcAlpha,
75 SourceAlpha = BlendingType.One,
76 DestinationAlpha = BlendingType.One,
77 RGBEquation = BlendingEquation.Add,
78 AlphaEquation = BlendingEquation.Add,
79 };
80
81 public static BlendingParameters Additive => new BlendingParameters
82 {
83 Source = BlendingType.SrcAlpha,
84 Destination = BlendingType.One,
85 SourceAlpha = BlendingType.One,
86 DestinationAlpha = BlendingType.One,
87 RGBEquation = BlendingEquation.Add,
88 AlphaEquation = BlendingEquation.Add,
89 };
90
91 #endregion
92
93 /// <summary>
94 /// Copy all properties that are marked as inherited from a parent <see cref="BlendingParameters"/> object.
95 /// </summary>
96 /// <param name="parent">The parent <see cref="BlendingParameters"/> from which to copy inherited properties.</param>
97 public void CopyFromParent(BlendingParameters parent)
98 {
99 if (Source == BlendingType.Inherit)
100 Source = parent.Source;
101
102 if (Destination == BlendingType.Inherit)
103 Destination = parent.Destination;
104
105 if (SourceAlpha == BlendingType.Inherit)
106 SourceAlpha = parent.SourceAlpha;
107
108 if (DestinationAlpha == BlendingType.Inherit)
109 DestinationAlpha = parent.DestinationAlpha;
110
111 if (RGBEquation == BlendingEquation.Inherit)
112 RGBEquation = parent.RGBEquation;
113
114 if (AlphaEquation == BlendingEquation.Inherit)
115 AlphaEquation = parent.AlphaEquation;
116 }
117
118 /// <summary>
119 /// Any properties marked as inherited will have their blending mode changed to the default type. This can occur when a root element is set to inherited.
120 /// </summary>
121 public void ApplyDefaultToInherited()
122 {
123 if (Source == BlendingType.Inherit)
124 Source = BlendingType.SrcAlpha;
125
126 if (Destination == BlendingType.Inherit)
127 Destination = BlendingType.OneMinusSrcAlpha;
128
129 if (SourceAlpha == BlendingType.Inherit)
130 SourceAlpha = BlendingType.One;
131
132 if (DestinationAlpha == BlendingType.Inherit)
133 DestinationAlpha = BlendingType.One;
134
135 if (RGBEquation == BlendingEquation.Inherit)
136 RGBEquation = BlendingEquation.Add;
137
138 if (AlphaEquation == BlendingEquation.Inherit)
139 AlphaEquation = BlendingEquation.Add;
140 }
141
142 public readonly bool Equals(BlendingParameters other) =>
143 other.Source == Source
144 && other.Destination == Destination
145 && other.SourceAlpha == SourceAlpha
146 && other.DestinationAlpha == DestinationAlpha
147 && other.RGBEquation == RGBEquation
148 && other.AlphaEquation == AlphaEquation;
149
150 public static bool operator ==(in BlendingParameters left, in BlendingParameters right) =>
151 left.Source == right.Source &&
152 left.Destination == right.Destination &&
153 left.SourceAlpha == right.SourceAlpha &&
154 left.DestinationAlpha == right.DestinationAlpha &&
155 left.RGBEquation == right.RGBEquation &&
156 left.AlphaEquation == right.AlphaEquation;
157
158 public static bool operator !=(in BlendingParameters left, in BlendingParameters right) => !(left == right);
159
160 public override readonly bool Equals(object obj) => obj is BlendingParameters other && this == other;
161
162 [SuppressMessage("ReSharper", "NonReadonlyMemberInGetHashCode")]
163 public override readonly int GetHashCode() => HashCode.Combine(Source, Destination, SourceAlpha, DestinationAlpha, RGBEquation, AlphaEquation);
164
165 public readonly bool IsDisabled =>
166 Source == BlendingType.One
167 && Destination == BlendingType.Zero
168 && SourceAlpha == BlendingType.One
169 && DestinationAlpha == BlendingType.Zero
170 && RGBEquation == BlendingEquation.Add
171 && AlphaEquation == BlendingEquation.Add;
172
173 public override readonly string ToString() => $"BlendingParameter: Factor: {Source}/{Destination}/{SourceAlpha}/{DestinationAlpha} RGBEquation: {RGBEquation} AlphaEquation: {AlphaEquation}";
174
175 #region GL Type Getters
176
177 /// <summary>
178 /// Gets the <see cref="BlendEquationMode"/> for the currently specified RGB Equation.
179 /// </summary>
180 public readonly BlendEquationMode RGBEquationMode => translateEquation(RGBEquation);
181
182 /// <summary>
183 /// Gets the <see cref="BlendEquationMode"/> for the currently specified Alpha Equation.
184 /// </summary>
185 public readonly BlendEquationMode AlphaEquationMode => translateEquation(AlphaEquation);
186
187 /// <summary>
188 /// Gets the <see cref="BlendingFactorSrc"/> for the currently specified source blending mode.
189 /// </summary>
190 public readonly BlendingFactorSrc SourceBlendingFactor => translateBlendingFactorSrc(Source);
191
192 /// <summary>
193 /// Gets the <see cref="BlendingFactorDest"/> for the currently specified destination blending mode.
194 /// </summary>
195 public readonly BlendingFactorDest DestinationBlendingFactor => translateBlendingFactorDest(Destination);
196
197 /// <summary>
198 /// Gets the <see cref="BlendingFactorSrc"/> for the currently specified source alpha mode.
199 /// </summary>
200 public readonly BlendingFactorSrc SourceAlphaBlendingFactor => translateBlendingFactorSrc(SourceAlpha);
201
202 /// <summary>
203 /// Gets the <see cref="BlendingFactorDest"/> for the currently specified destination alpha mode.
204 /// </summary>
205 public readonly BlendingFactorDest DestinationAlphaBlendingFactor => translateBlendingFactorDest(DestinationAlpha);
206
207 private static BlendingFactorSrc translateBlendingFactorSrc(BlendingType factor)
208 {
209 switch (factor)
210 {
211 case BlendingType.ConstantAlpha:
212 return BlendingFactorSrc.ConstantAlpha;
213
214 case BlendingType.ConstantColor:
215 return BlendingFactorSrc.ConstantColor;
216
217 case BlendingType.DstAlpha:
218 return BlendingFactorSrc.DstAlpha;
219
220 case BlendingType.DstColor:
221 return BlendingFactorSrc.DstColor;
222
223 case BlendingType.One:
224 return BlendingFactorSrc.One;
225
226 case BlendingType.OneMinusConstantAlpha:
227 return BlendingFactorSrc.OneMinusConstantAlpha;
228
229 case BlendingType.OneMinusConstantColor:
230 return BlendingFactorSrc.OneMinusConstantColor;
231
232 case BlendingType.OneMinusDstAlpha:
233 return BlendingFactorSrc.OneMinusDstAlpha;
234
235 case BlendingType.OneMinusDstColor:
236 return BlendingFactorSrc.OneMinusDstColor;
237
238 case BlendingType.OneMinusSrcAlpha:
239 return BlendingFactorSrc.OneMinusSrcColor;
240
241 case BlendingType.SrcAlpha:
242 return BlendingFactorSrc.SrcAlpha;
243
244 case BlendingType.SrcAlphaSaturate:
245 return BlendingFactorSrc.SrcAlphaSaturate;
246
247 case BlendingType.SrcColor:
248 return BlendingFactorSrc.SrcColor;
249
250 default:
251 case BlendingType.Zero:
252 return BlendingFactorSrc.Zero;
253 }
254 }
255
256 private static BlendingFactorDest translateBlendingFactorDest(BlendingType factor)
257 {
258 switch (factor)
259 {
260 case BlendingType.ConstantAlpha:
261 return BlendingFactorDest.ConstantAlpha;
262
263 case BlendingType.ConstantColor:
264 return BlendingFactorDest.ConstantColor;
265
266 case BlendingType.DstAlpha:
267 return BlendingFactorDest.DstAlpha;
268
269 case BlendingType.DstColor:
270 return BlendingFactorDest.DstColor;
271
272 case BlendingType.One:
273 return BlendingFactorDest.One;
274
275 case BlendingType.OneMinusConstantAlpha:
276 return BlendingFactorDest.OneMinusConstantAlpha;
277
278 case BlendingType.OneMinusConstantColor:
279 return BlendingFactorDest.OneMinusConstantColor;
280
281 case BlendingType.OneMinusDstAlpha:
282 return BlendingFactorDest.OneMinusDstAlpha;
283
284 case BlendingType.OneMinusDstColor:
285 return BlendingFactorDest.OneMinusDstColor;
286
287 case BlendingType.OneMinusSrcAlpha:
288 return BlendingFactorDest.OneMinusSrcAlpha;
289
290 case BlendingType.OneMinusSrcColor:
291 return BlendingFactorDest.OneMinusSrcColor;
292
293 case BlendingType.SrcAlpha:
294 return BlendingFactorDest.SrcAlpha;
295
296 case BlendingType.SrcAlphaSaturate:
297 return BlendingFactorDest.SrcAlphaSaturate;
298
299 case BlendingType.SrcColor:
300 return BlendingFactorDest.SrcColor;
301
302 default:
303 case BlendingType.Zero:
304 return BlendingFactorDest.Zero;
305 }
306 }
307
308 private static BlendEquationMode translateEquation(BlendingEquation blendingEquation)
309 {
310 switch (blendingEquation)
311 {
312 default:
313 case BlendingEquation.Inherit:
314 case BlendingEquation.Add:
315 return BlendEquationMode.FuncAdd;
316
317 case BlendingEquation.Min:
318 return BlendEquationMode.Min;
319
320 case BlendingEquation.Max:
321 return BlendEquationMode.Max;
322
323 case BlendingEquation.Subtract:
324 return BlendEquationMode.FuncSubtract;
325
326 case BlendingEquation.ReverseSubtract:
327 return BlendEquationMode.FuncReverseSubtract;
328 }
329 }
330
331 #endregion
332 }
333}