1 module nudsfml.graphics.glsl;
2 
3 import nudsfml.graphics.color;
4 import nudsfml.graphics.transform;
5 
6 import nudsfml.system.vector2;
7 import nudsfml.system.vector3;
8 
9 import std.traits;
10 
11 /// 2D float vector (vec2 in GLSL)
12 alias Vec2 = Vector2!(float);
13 /// 2D int vector (ivec2 in GLSL)
14 alias Ivec2 = Vector2!(int);
15 /// 2D bool vector (bvec2 in GLSL)
16 alias Bvec2 = Vector2!(bool);
17 /// 3D float vector (vec3 in GLSL)
18 alias Vec3 = Vector3!(float);
19 /// 3D int vector (ivec3 in GLSL)
20 alias Ivec3 = Vector3!(int);
21 /// 3D bool vector (bvec3 in GLSL)
22 alias Bvec3 = Vector3!(bool);
23 
24 /**
25  * 4D float vector (vec4 in GLSL)
26  *
27  * 4D float vectors can be converted from sf::Color instances. Each color
28  * channel is normalized from integers in [0, 255] to floating point values
29  * in [0, 1].
30  * ---
31  * Vec4 zeroVector;
32  * auto vector = Vec4(1.f, 2.f, 3.f, 4.f);
33  * auto color = Vec4(Color.Cyan);
34  * ---
35  */
36 alias Vec4 = Vector4!(float);
37 /**
38  * 4D int vector ( ivec4 in GLSL)
39  *
40  * 4D int vectors can be converted from sf::Color instances. Each color channel
41  * remains unchanged inside the integer interval [0, 255].
42  * $(LI test)
43  * ---
44  * Ivec4 zeroVector;
45  * auto vector = Ivec4(1, 2, 3, 4);
46  * auto color = Ivec4(Color.Cyan);
47  * ---
48  */
49 alias Ivec4 = Vector4!(int);
50 
51 /// 4D bool vector (bvec4 in GLSL)
52 alias Bvec4 = Vector4!(bool);
53 
54 /**
55  * 3x3 float matrix (mat3 in GLSL)
56  *
57  * The matrix can be constructed from an array with 3x3 elements, aligned in
58  * column-major order. For example,a translation by (x, y) looks as follows:
59  * ---
60  * float[9] array =
61  * [
62  *     1, 0, 0,
63  *     0, 1, 0,
64  *     x, y, 1
65  * ];
66  *
67  * auto matrix = Mat3(array);
68  * ---
69  *
70  * $(PARA Mat4 can also be converted from a $(TRANSFORM_LINK Transform).)
71  * ---
72  * Transform transform;
73  * auto matrix = Mat3(transform);
74  * ---
75  */
76 alias Mat3 = Matrix!(3,3);
77 
78 /**
79  * 4x4 float matrix (mat4 in GLSL)
80  *
81  * The matrix can be constructed from an array with 4x4 elements, aligned in
82  * column-major order. For example, a translation by (x, y, z) looks as follows:
83  * ---
84  * float array[16] =
85  * {
86  *     1, 0, 0, 0,
87  *     0, 1, 0, 0,
88  *     0, 0, 1, 0,
89  *     x, y, z, 1
90  * };
91  *
92  * auto matrix = Mat4(array);
93  * ---
94  *
95  * $(PARA Mat4 can also be converted from a $(TRANSFORM_LINK Transform).)
96  * ---
97  * Transform transform;
98  * auto matrix = Mat4(transform);
99  * ---
100  */
101 alias Mat4 = Matrix!(4,4);
102 
103 /**
104  * 4D vector type, used to set uniforms in GLSL.
105  */
106 struct Vector4(T)
107     if(isNumeric!(T) || is(T == bool))
108 {
109     /// 1st component (X) of the 4D vector
110     T x;
111     /// 2nd component (Y) of the 4D vector
112     T y;
113     /// 3rd component (Z) of the 4D vector
114     T z;
115     /// 4th component (W) of the 4D vector
116     T w;
117 
118     /**
119      * Construct from 4 vector components
120      *
121      * Params:
122      * X = Component of the 4D vector
123      * Y = Component of the 4D vector
124      * Z = Component of the 4D vector
125      * W = Component of the 4D vector
126      */
127     this(T X, T Y, T Z, T W)
128     {
129         x = X;
130         y = Y;
131         z = Z;
132         w = W;
133     }
134 
135     /**
136      * Conversion constructor
137      *
138      * Params:
139      * other = 4D vector of different type
140      */
141     this(U)(Vector!(U) other)
142     {
143         x = cast(T)other.x;
144         y = cast(T)other.y;
145         z = cast(T)other.z;
146         w = cast(T)other.w;
147     }
148 
149     /**
150      * Construct vector from color.
151      *
152      * The vector values are normalized to [0, 1] for floats, and left as-is for
153      * ints.
154      *
155      * Params:
156      * source = The Color instance to create the vector from
157      */
158     this(Color source)
159     {
160         static if(is(T == float))
161         {
162             x = source.r / 255f;
163             y = source.g / 255f;
164             z = source.b / 255f;
165             w = source.a / 255f;
166         }
167         else static if(is(T == int))
168         {
169             x = cast(T)source.r;
170             y = cast(T)source.g;
171             z = cast(T)source.b;
172             w = cast(T)source.a;
173         }
174     }
175 }
176 
177 /**
178  * Matrix type, used to set uniforms in GLSL.
179  */
180 struct Matrix(uint C, uint R)
181 {
182     /// Array holding matrix data.
183     float[C * R] array;
184 
185     /**
186      * Construct from DSFML transform.
187      *
188      * This constructor is only supported for 3x3 and 4x4 matrices.
189      *
190      * Params:
191      * source = A DSFML Transform
192      */
193     this(ref const(Transform) source)
194     {
195         static assert(C == R && (C == 3 || C == 4),
196         "This constructor is only supported for 3x3 and 4x4 matrices.");
197 
198         const(float)[] from = source.getMatrix();
199 
200         static if(C == 3)
201         {
202             float[] to = array;                 // 3x3
203         // Use only left-upper 3x3 block (for a 2D transform)
204         to[0] = from[ 0]; to[1] = from[ 1]; to[2] = from[ 3];
205         to[3] = from[ 4]; to[4] = from[ 5]; to[5] = from[ 7];
206         to[6] = from[12]; to[7] = from[13]; to[8] = from[15];
207         }
208         else static if(C == 4)
209         {
210             array[] = from[];
211         }
212     }
213 
214     /**
215      * Construct from raw data.
216      *
217      * The elements in source are copied to the instance.
218      *
219      * Params:
220      * source = An array that has the size of the matrix.
221      */
222     this(const(float)[] source)
223     {
224         assert(array.length == source.length);
225 
226         array[0..$] = source[0 .. $];
227     }
228 }