1 /*
2  * DSFML - The Simple and Fast Multimedia Library for D
3  *
4  * Copyright (c) 2013 - 2018 Jeremy DeHaan (dehaan.jeremiah@gmail.com)
5  *
6  * This software is provided 'as-is', without any express or implied warranty.
7  * In no event will the authors be held liable for any damages arising from the
8  * use of this software.
9  *
10  * Permission is granted to anyone to use this software for any purpose,
11  * including commercial applications, and to alter it and redistribute it
12  * freely, subject to the following restrictions:
13  *
14  * 1. The origin of this software must not be misrepresented; you must not claim
15  * that you wrote the original software. If you use this software in a product,
16  * an acknowledgment in the product documentation would be appreciated but is
17  * not required.
18  *
19  * 2. Altered source versions must be plainly marked as such, and must not be
20  * misrepresented as being the original software.
21  *
22  * 3. This notice may not be removed or altered from any source distribution
23  *
24  *
25  * DSFML is based on SFML (Copyright Laurent Gomila)
26  */
27 
28 /**
29  * $(U BlendMode) is a structure that represents a blend mode. A blend mode
30  * determines how the colors of an object you draw are mixed with the colors
31  * that are already in the buffer.
32  *
33  * The structure is composed of 6 components, each of which has its
34  * own public member variable:
35  * $(UL
36  * $(LI Color Source Factor (colorSrcFactor))
37  * $(LI Color Destination Factor (colorDstFactor))
38  * $(LI Color Blend Equation (colorEquation))
39  * $(LI Alpha Source Factor (alphaSrcFactor))
40  * $(LI Alpha Destination Factor (alphaDstFactor))
41  * $(LI Alpha Blend Equation (alphaEquation)))
42  * $(PARA
43  * The source factor specifies how the pixel you are drawing contributes to the
44  * final color. The destination factor specifies how the pixel already drawn in
45  * the buffer contributes to the final color.
46  *
47  * The color channels RGB (red, green, blue; simply referred to as color) and A
48  * (alpha; the transparency) can be treated separately. This separation can be
49  * useful for specific blend modes, but most often you won't need it and will
50  * simply treat the color as a single unit.
51  *
52  * The blend factors and equations correspond to their OpenGL equivalents. In
53  * general, the color of the resulting pixel is calculated according to the
54  * following formula ($(I src) is the color of the source pixel, $(I dst) the
55  * color of the destination pixel, the other variables correspond to the
56  * public members, with the equations being `+` or `-` operators):)
57  * ---
58  * dst.rgb = colorSrcFactor * src.rgb (colorEquation) colorDstFactor * dst.rgb
59  * dst.a   = alphaSrcFactor * src.a   (alphaEquation) alphaDstFactor * dst.a
60  * ---
61  *
62  * $(PARA All factors and colors are represented as floating point numbers
63  * between 0 and 1. Where necessary, the result is clamped to fit in that range.
64  *
65  * The most common blending modes are defined as constants inside of
66  * $(U BlendMode):)
67  * ---
68  * auto alphaBlending          = BlendMode.Alpha;
69  * auto additiveBlending       = BlendMode.Add;
70  * auto multiplicativeBlending = BlendMode.Multiply;
71  * auto noBlending             = BlendMode.None;
72  * ---
73  *
74  * $(PARA In DSFML, a blend mode can be specified every time you draw a Drawable
75  * object to a render target. It is part of the RenderStates compound
76  * that is passed to the member function RenderTarget::draw().)
77  *
78  * See_Also:
79  * $(RENDERSTATES_LINK), $(RENDERTARGET_LINK)
80  */
81 module dsfml.graphics.blendmode;
82 
83 /**
84  * Blending modes for drawing.
85  */
86 struct BlendMode
87 {
88     /**
89      * Enumeration of the blending factors.
90      *
91      * The factors are mapped directly to their OpenGL equivalents,
92      * specified by `glBlendFunc()` or `glBlendFuncSeparate()`.
93      */
94     enum Factor
95     {
96         /// (0, 0, 0, 0)
97         Zero,
98         /// (1, 1, 1, 1)
99         One,
100         /// (src.r, src.g, src.b, src.a)
101         SrcColor,
102         /// (1, 1, 1, 1) - (src.r, src.g, src.b, src.a)
103         OneMinunSrcColor,
104         /// (dst.r, dst.g, dst.b, dst.a)
105         DstColor,
106         /// (1, 1, 1, 1) - (dst.r, dst.g, dst.b, dst.a)
107         OneMinusDstColor,
108         /// (src.a, src.a, src.a, src.a)
109         SrcAlpha,
110         /// (1, 1, 1, 1) - (src.a, src.a, src.a, src.a)
111         OneMinusSrcAlpha,
112         /// (dst.a, dst.a, dst.a, dst.a)
113         DstAlpha,
114         /// (1, 1, 1, 1) - (dst.a, dst.a, dst.a, dst.a)
115         OneMinusDstAlpha
116     }
117 
118     /**
119      * Enumeration of the blending equations
120      *
121      * The equations are mapped directly to their OpenGL equivalents,
122      * specified by glBlendEquation() or glBlendEquationSeparate().
123      */
124     enum Equation
125     {
126         /// Pixel = Src * SrcFactor + Dst * DstFactor
127         Add,
128         /// Pixel = Src * SrcFactor - Dst * DstFactor
129         Subtract,
130         /// Pixel = Dst * DstFactor - Src * SrcFactor
131         ReverseSubtract
132     }
133 
134     /// Blend source and dest according to dest alpha.
135     enum Alpha = BlendMode(Factor.SrcAlpha, Factor.OneMinusSrcAlpha,
136                Equation.Add, Factor.One, Factor.OneMinusSrcAlpha, Equation.Add);
137     /// Add source to dest.
138     enum Add = BlendMode(Factor.SrcAlpha, Factor.One, Equation.Add,
139                          Factor.One, Factor.One, Equation.Add);
140     /// Multiply source and dest.
141     enum Multiply = BlendMode(Factor.DstColor, Factor.Zero, Equation.Add,
142                               Factor.DstColor, Factor.Zero, Equation.Add);
143     /// Overwrite dest with source.
144     enum None = BlendMode(Factor.One, Factor.Zero, Equation.Add, Factor.One,
145                           Factor.Zero, Equation.Add);
146 
147 
148     /// Source blending factor for the color channels.
149     Factor colorSrcFactor = Factor.SrcAlpha;
150     /// Destination blending factor for the color channels.
151     Factor colorDstFactor = Factor.OneMinusSrcAlpha;
152     /// Blending equation for the color channels.
153     Equation colorEquation = Equation.Add;
154     /// Source blending factor for the alpha channel.
155     Factor alphaSrcFactor = Factor.One;
156     /// Destination blending factor for the alpha channel.
157     Factor alphaDstFactor = Factor.OneMinusSrcAlpha;
158     /// Blending equation for the alpha channel.
159     Equation alphaEquation = Equation.Add;
160 
161     /**
162      * Construct the blend mode given the factors and equation.
163      *
164      * This constructor uses the same factors and equation for both
165      * color and alpha components. It also defaults to the Add equation.
166      *
167      * Params:
168      * sourceFactor      = Specifies how to compute the source factor for the
169                            color and alpha channels
170      * destinationFactor = Specifies how to compute the destination factor for
171                            the color and alpha channels
172      * blendEquation     = Specifies how to combine the source and destination
173                            colors and alpha
174      */
175     this(Factor sourceFactor, Factor destinationFactor,
176          Equation blendEquation = Equation.Add)
177     {
178         colorSrcFactor = sourceFactor;
179         colorDstFactor = destinationFactor;
180         colorEquation = blendEquation;
181 
182         alphaSrcFactor = sourceFactor;
183         alphaDstFactor = destinationFactor;
184         alphaEquation = blendEquation;
185     }
186 
187     /**
188      * Construct the blend mode given the factors and equation.
189      *
190      * Params:
191      * colorSourceFactor      = Specifies how to compute the source factor for
192                                 the color channels
193      * colorDestinationFactor = Specifies how to compute the destination factor
194                                 for the color channels
195      * colorBlendEquation     = Specifies how to combine the source and
196                                 destination colors
197      * alphaSourceFactor      = Specifies how to compute the source factor
198      * alphaDestinationFactor = Specifies how to compute the destination factor
199      * alphaBlendEquation     = Specifies how to combine the source and
200                                 destination alphas
201      */
202     this(Factor colorSourceFactor, Factor colorDestinationFactor,
203               Equation colorBlendEquation, Factor alphaSourceFactor,
204               Factor alphaDestinationFactor, Equation alphaBlendEquation)
205     {
206         colorSrcFactor = colorSourceFactor;
207         colorDstFactor = colorDestinationFactor;
208         colorEquation = colorBlendEquation;
209 
210         alphaSrcFactor = alphaSourceFactor;
211         alphaDstFactor = alphaDestinationFactor;
212         alphaEquation = alphaBlendEquation;
213     }
214 
215     bool opEquals(BlendMode rhs) const
216 	{
217 		return (colorSrcFactor == rhs.colorSrcFactor &&
218                 colorDstFactor == rhs.colorDstFactor &&
219                 colorEquation == rhs.colorEquation   &&
220                 alphaSrcFactor == rhs.alphaSrcFactor &&
221                 alphaDstFactor == rhs.alphaDstFactor &&
222                 alphaEquation == rhs.alphaEquation );
223 	}
224 }