1 /*
2  * DSFML - The Simple and Fast Multimedia Library for D
3  *
4  * Copyright (c) 2013 - 2017 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 /**
26  * The glsl module contains types that match their equivalents in GLSL, the
27  * OpenGL shading language. These types are exclusively used by the
28  * $(SHADER_LINK) class.
29  *
30  * Types that already exist in DSFML, such as $(VECTOR2_LINK) and
31  * $(VECTOR3_LINK), are reused as aliases, so you can use the types in this
32  * module as well as the original ones.
33  * Others are newly defined, such as `Vec4` or `Mat3`. Their actual type is an
34  * implementation detail and should not be used.
35  *
36  * All vector types support a default constructor that initializes every
37  * component to zero, in addition to a constructor with one parameter for each
38  * component.
39  * The components are stored in member variables called `x`, `y`, `z`, and `w`.
40  *
41  * All matrix types support a constructor with a `float[]` parameter of the
42  * appropriate size (that is, 9 in a 3x3 matrix, 16 in a 4x4 matrix).
43  * Furthermore, they can be converted from $(TRANSFORM_LINK) objects.
44 */
45 module dsfml.graphics.glsl;
46 
47 import dsfml.graphics.color;
48 import dsfml.graphics.transform;
49 
50 import dsfml.system.vector2;
51 import dsfml.system.vector3;
52 
53 import std.traits;
54 
55 /// 2D float vector (vec2 in GLSL)
56 alias Vec2 = Vector2!(float);
57 /// 2D int vector (ivec2 in GLSL)
58 alias Ivec2 = Vector2!(int);
59 /// 2D bool vector (bvec2 in GLSL)
60 alias Bvec2 = Vector2!(bool);
61 /// 3D float vector (vec3 in GLSL)
62 alias Vec3 = Vector3!(float);
63 /// 3D int vector (ivec3 in GLSL)
64 alias Ivec3 = Vector3!(int);
65 /// 3D bool vector (bvec3 in GLSL)
66 alias Bvec3 = Vector3!(bool);
67 
68 
69 /**
70  * 4D float vector (vec4 in GLSL)
71  *
72  * 4D float vectors can be converted from sf::Color instances. Each color
73  * channel is normalized from integers in [0, 255] to floating point values
74  * in [0, 1].
75  * ---
76  * Vec4 zeroVector;
77  * auto vector = Vec4(1.f, 2.f, 3.f, 4.f);
78  * auto color = Vec4(Color.Cyan);
79  * ---
80  */
81 alias Vec4 = Vector4!(float);
82 /**
83  * 4D int vector ( ivec4 in GLSL)
84  *
85  * 4D int vectors can be converted from sf::Color instances. Each color channel
86  * remains unchanged inside the integer interval [0, 255].
87  * $(LI test)
88  * ---
89  * Ivec4 zeroVector;
90  * auto vector = Ivec4(1, 2, 3, 4);
91  * auto color = Ivec4(Color.Cyan);
92  * ---
93  */
94 alias Ivec4 = Vector4!(int);
95 
96 /// 4D bool vector (bvec4 in GLSL)
97 alias Bvec4 = Vector4!(bool);
98 
99 /**
100  * 3x3 float matrix (mat3 in GLSL)
101  *
102  * The matrix can be constructed from an array with 3x3 elements, aligned in
103  * column-major order. For example,a translation by (x, y) looks as follows:
104  * ---
105  * float[9] array =
106  * [
107  *     1, 0, 0,
108  *     0, 1, 0,
109  *     x, y, 1
110  * ];
111  *
112  * auto matrix = Mat3(array);
113  * ---
114  *
115  * $(PARA Mat4 can also be converted from a $(TRANSFORM_LINK Transform).)
116  * ---
117  * Transform transform;
118  * auto matrix = Mat3(transform);
119  * ---
120  */
121 alias Mat3 = Matrix!(3,3);
122 
123 /**
124  * 4x4 float matrix (mat4 in GLSL)
125  *
126  * The matrix can be constructed from an array with 4x4 elements, aligned in
127  * column-major order. For example, a translation by (x, y, z) looks as follows:
128  * ---
129  * float array[16] =
130  * {
131  *     1, 0, 0, 0,
132  *     0, 1, 0, 0,
133  *     0, 0, 1, 0,
134  *     x, y, z, 1
135  * };
136  *
137  * auto matrix = Mat4(array);
138  * ---
139  *
140  * $(PARA Mat4 can also be converted from a $(TRANSFORM_LINK Transform).)
141  * ---
142  * Transform transform;
143  * auto matrix = Mat4(transform);
144  * ---
145  */
146 alias Mat4 = Matrix!(4,4);
147 
148 /**
149  * 4D vector type, used to set uniforms in GLSL.
150  */
151 struct Vector4(T)
152     if(isNumeric!(T) || is(T == bool))
153 {
154     /// 1st component (X) of the 4D vector
155     T x;
156     /// 2nd component (Y) of the 4D vector
157     T y;
158     /// 3rd component (Z) of the 4D vector
159     T z;
160     /// 4th component (W) of the 4D vector
161     T w;
162 
163     /**
164      * Construct from 4 vector components
165      *
166      * Params:
167      * X = Component of the 4D vector
168      * Y = Component of the 4D vector
169      * Z = Component of the 4D vector
170      * W = Component of the 4D vector
171      */
172     this(T X, T Y, T Z, T W)
173     {
174         x = X;
175         y = Y;
176         z = Z;
177         w = W;
178     }
179 
180     /**
181      * Conversion constructor
182      *
183      * Params:
184      * other = 4D vector of different type
185      */
186     this(U)(Vector!(U) other)
187     {
188         x = cast(T)other.x;
189         y = cast(T)other.y;
190         z = cast(T)other.z;
191         w = cast(T)other.w;
192     }
193 
194     /**
195      * Construct vector from color.
196      *
197      * The vector values are normalized to [0, 1] for floats, and left as-is for
198      * ints.
199      *
200      * Params:
201      * source = The Color instance to create the vector from
202      */
203     this(Color source)
204     {
205         static if(is(T == float))
206         {
207             x = source.r / 255f;
208             y = source.g / 255f;
209             z = source.b / 255f;
210             w = source.a / 255f;
211         }
212         else static if(is(T == int))
213         {
214             x = cast(T)source.r;
215             y = cast(T)source.g;
216             z = cast(T)source.b;
217             w = cast(T)source.a;
218         }
219     }
220 
221 }
222 
223 /**
224  * Matrix type, used to set uniforms in GLSL.
225  */
226 struct Matrix(uint C, uint R)
227 {
228     /// Array holding matrix data.
229     float[C * R] array;
230 
231     /**
232      * Construct from DSFML transform.
233      *
234      * This constructor is only supported for 3x3 and 4x4 matrices.
235      *
236      * Params:
237      * source = A DSFML Transform
238      */
239     this(ref const(Transform) source)
240     {
241         static assert(C == R && (C == 3 || C == 4),
242         "This constructor is only supported for 3x3 and 4x4 matrices.");
243 
244         const(float)[] from = source.getMatrix();
245 
246         static if(C == 3)
247         {
248             float[] to = array;                 // 3x3
249         // Use only left-upper 3x3 block (for a 2D transform)
250         to[0] = from[ 0]; to[1] = from[ 1]; to[2] = from[ 3];
251         to[3] = from[ 4]; to[4] = from[ 5]; to[5] = from[ 7];
252         to[6] = from[12]; to[7] = from[13]; to[8] = from[15];
253         }
254         else static if(C == 4)
255         {
256             array[] = from[];
257         }
258     }
259 
260     /**
261      * Construct from raw data.
262      *
263      * The elements in source are copied to the instance.
264      *
265      * Params:
266      * source = An array that has the size of the matrix.
267      */
268     this(const(float)[] source)
269     {
270         assert(array.length == source.length);
271 
272         array[0..$] = source[0 .. $];
273     }
274 }