1 /*
2  *******************************************************************************************
3  * Dgame (a D game framework) - Copyright (c) Randy Schütt
4  * 
5  * This software is provided 'as-is', without any express or implied warranty.
6  * In no event will the authors be held liable for any damages arising from
7  * the use of this software.
8  * 
9  * Permission is granted to anyone to use this software for any purpose,
10  * including commercial applications, and to alter it and redistribute it
11  * freely, subject to the following restrictions:
12  * 
13  * 1. The origin of this software must not be misrepresented; you must not claim
14  *    that you wrote the original software. If you use this software in a product,
15  *    an acknowledgment in the product documentation would be appreciated but is
16  *    not required.
17  * 
18  * 2. Altered source versions must be plainly marked as such, and must not be
19  *    misrepresented as being the original software.
20  * 
21  * 3. This notice may not be removed or altered from any source distribution.
22  *******************************************************************************************
23  */
24 module Dgame.Graphics.Blend;
25 
26 private {
27 	import derelict.opengl3.gl;
28 	
29 	import Dgame.Graphics.Color;
30 }
31 
32 /**
33  * Enable blending
34  */
35 interface Blendable {
36 	/**
37 	 * Set (or reset) the current Blend instance.
38 	 */
39 	void setBlend(Blend blend) pure nothrow;
40 	/**
41 	 * Returns the current Blend instance, or null.
42 	 */
43 	inout(Blend) getBlend() inout pure nothrow;
44 }
45 
46 /**
47  * The Blend class. If you want that a blendable object get some blend, 
48  * create an instance of this class and give it to your blendable.
49  *
50  * Author: rschuett
51  */
52 class Blend {
53 	/**
54 	 * Supported BlendModes
55 	 */
56 	enum Mode : ubyte {
57 		None,      /// No blending.
58 		Alpha,     /// Pixel = Src * a + Dest * (1 - a)
59 		Add,       /// Pixel = Src + Dest
60 		Multiply   /// Pixel = Src * Dest
61 	}
62 	
63 private:
64 	Mode _mode;
65 	Color _color;
66 	bool _isBlendColor;
67 	
68 public:
69 	/**
70 	 * Apply the blending
71 	 */
72 	void applyBlending() const {
73 		this.enable(true);
74 
75 		if (this._isBlendColor) {
76 			const float[4] col = this._color.asGLColor();
77 			
78 			version(all)
79 				glBlendColor(col[0], col[1], col[2], col[3]);
80 			else
81 				glColor4f(col[0], col[1], col[2], col[3]);
82 		}
83 		
84 		final switch (this._mode) {
85 			case Mode.Alpha: // Alpha blending
86 				glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
87 				break;
88 			case Mode.Add: // Additive blending
89 				glBlendFunc(GL_SRC_ALPHA, GL_ONE);
90 				break;
91 			case Mode.Multiply: // Multiplicative blending
92 				glBlendFunc(GL_DST_COLOR, GL_ZERO);
93 				break;
94 			case Mode.None: // No blending
95 				glBlendFunc(GL_ONE, GL_ZERO);
96 				break;
97 		}
98 	}
99 	
100 final:
101 	/**
102 	 * CTor
103 	 */
104 	this(Mode mode) {
105 		this.setBlendMode(mode);
106 	}
107 
108 	/**
109 	 * CTor
110 	 */
111 	this(Mode mode, ref const Color col) {
112 		this(mode);
113 
114 		this.setBlendColor(col);
115 	}
116 
117 	/**
118 	 * Rvalue version
119 	 */
120 	this(Mode mode, const Color col) {
121 		this(mode, col);
122 	}
123 	
124 	/**
125 	 * Enable or Disable blending
126 	 */
127 	void enable(bool enable) const {
128 		const bool isEnabled = glIsEnabled(GL_BLEND) == GL_TRUE;
129 
130 		if (enable && !isEnabled)
131 			glEnable(GL_BLEND);
132 		else if (!enable && isEnabled)
133 			glDisable(GL_BLEND);
134 	}
135 	
136 	/**
137 	 * Activate or deactivate the using of the blend color.
138 	 */
139 	void enableColor(bool enable) pure nothrow {
140 		this._isBlendColor = enable;
141 	}
142 
143 	/**
144 	 * Set the Blendmode.
145 	 */
146 	void setBlendMode(Mode mode) pure nothrow {
147 		this._mode = mode;
148 	}
149 	
150 	/**
151 	 * Returns the current Blendmode.
152 	 */
153 	Mode getBlendMode() const pure nothrow {
154 		return this._mode;
155 	}
156 	
157 	/**
158 	 * Set the Blend Color.
159 	 */
160 	void setBlendColor(ref const Color col) pure nothrow {
161 		this._isBlendColor = true;
162 		this._color = col;
163 	}
164 	
165 	/**
166 	 * Rvalue version
167 	 */
168 	void setBlendColor(const Color col) pure nothrow {
169 		this.setBlendColor(col);
170 	}
171 	
172 	/**
173 	 * Returns the current Blend Color.
174 	 */
175 	ref const(Color) getBlendColor() const pure nothrow {
176 		return this._color;
177 	}
178 }