]> git.lizzy.rs Git - irrlicht.git/blob - include/SColor.h
Drop ETS_TEXTURE_1
[irrlicht.git] / include / SColor.h
1 // Copyright (C) 2002-2012 Nikolaus Gebhardt\r
2 // This file is part of the "Irrlicht Engine".\r
3 // For conditions of distribution and use, see copyright notice in irrlicht.h\r
4 \r
5 #ifndef __COLOR_H_INCLUDED__\r
6 #define __COLOR_H_INCLUDED__\r
7 \r
8 #include "irrTypes.h"\r
9 #include "irrMath.h"\r
10 \r
11 namespace irr\r
12 {\r
13 namespace video\r
14 {\r
15         //! An enum for the color format of textures used by the Irrlicht Engine.\r
16         /** A color format specifies how color information is stored.\r
17             NOTE: Byte order in memory is usually flipped (it's probably correct in bitmap files, but flipped on reading).\r
18             So for example ECF_A8R8G8B8 is BGRA in memory same as in DX9's D3DFMT_A8R8G8B8 format.\r
19         */\r
20         enum ECOLOR_FORMAT\r
21         {\r
22                 //! 16 bit color format used by the software driver.\r
23                 /** It is thus preferred by all other irrlicht engine video drivers.\r
24                 There are 5 bits for every color component, and a single bit is left\r
25                 for alpha information. */\r
26                 ECF_A1R5G5B5 = 0,\r
27 \r
28                 //! Standard 16 bit color format.\r
29                 ECF_R5G6B5,\r
30 \r
31                 //! 24 bit color, no alpha channel, but 8 bit for red, green and blue.\r
32                 //! Warning: 24 bit formats tend to be badly supported. Depending on driver it's usually converted to another\r
33                 //           format or even not working at all. It's mostly better to use 16-bit or 32-bit formats.\r
34                 ECF_R8G8B8,\r
35 \r
36                 //! Default 32 bit color format. 8 bits are used for every component: red, green, blue and alpha.\r
37                 //! Warning: This tends to be BGRA in memory (it's ARGB on file, but with usual big-endian memory it's flipped)\r
38                 ECF_A8R8G8B8,\r
39 \r
40                 /** Compressed image formats. **/\r
41 \r
42                 //! DXT1 color format.\r
43                 ECF_DXT1,\r
44 \r
45                 //! DXT2 color format.\r
46                 ECF_DXT2,\r
47 \r
48                 //! DXT3 color format.\r
49                 ECF_DXT3,\r
50 \r
51                 //! DXT4 color format.\r
52                 ECF_DXT4,\r
53 \r
54                 //! DXT5 color format.\r
55                 ECF_DXT5,\r
56 \r
57                 //! PVRTC RGB 2bpp.\r
58                 ECF_PVRTC_RGB2,\r
59 \r
60                 //! PVRTC ARGB 2bpp.\r
61                 ECF_PVRTC_ARGB2,\r
62 \r
63                 //! PVRTC RGB 4bpp.\r
64                 ECF_PVRTC_RGB4,\r
65 \r
66                 //! PVRTC ARGB 4bpp.\r
67                 ECF_PVRTC_ARGB4,\r
68 \r
69                 //! PVRTC2 ARGB 2bpp.\r
70                 ECF_PVRTC2_ARGB2,\r
71 \r
72                 //! PVRTC2 ARGB 4bpp.\r
73                 ECF_PVRTC2_ARGB4,\r
74 \r
75                 //! ETC1 RGB.\r
76                 ECF_ETC1,\r
77 \r
78                 //! ETC2 RGB.\r
79                 ECF_ETC2_RGB,\r
80 \r
81                 //! ETC2 ARGB.\r
82                 ECF_ETC2_ARGB,\r
83 \r
84                 /** The following formats may only be used for render target textures. */\r
85 \r
86                 /** Floating point formats. */\r
87 \r
88                 //! 16 bit format using 16 bits for the red channel.\r
89                 ECF_R16F,\r
90 \r
91                 //! 32 bit format using 16 bits for the red and green channels.\r
92                 ECF_G16R16F,\r
93 \r
94                 //! 64 bit format using 16 bits for the red, green, blue and alpha channels.\r
95                 ECF_A16B16G16R16F,\r
96 \r
97                 //! 32 bit format using 32 bits for the red channel.\r
98                 ECF_R32F,\r
99 \r
100                 //! 64 bit format using 32 bits for the red and green channels.\r
101                 ECF_G32R32F,\r
102 \r
103                 //! 128 bit format using 32 bits for the red, green, blue and alpha channels.\r
104                 ECF_A32B32G32R32F,\r
105 \r
106                 /** Unsigned normalized integer formats. */\r
107 \r
108                 //! 8 bit format using 8 bits for the red channel.\r
109                 ECF_R8,\r
110 \r
111                 //! 16 bit format using 8 bits for the red and green channels.\r
112                 ECF_R8G8,\r
113 \r
114                 //! 16 bit format using 16 bits for the red channel.\r
115                 ECF_R16,\r
116 \r
117                 //! 32 bit format using 16 bits for the red and green channels.\r
118                 ECF_R16G16,\r
119 \r
120                 /** Depth and stencil formats. */\r
121 \r
122                 //! 16 bit format using 16 bits for depth.\r
123                 ECF_D16,\r
124 \r
125                 //! 32 bit format using 32 bits for depth.\r
126                 ECF_D32,\r
127 \r
128                 //! 32 bit format using 24 bits for depth and 8 bits for stencil.\r
129                 ECF_D24S8,\r
130 \r
131                 //! Unknown color format:\r
132                 ECF_UNKNOWN\r
133         };\r
134 \r
135         //! Names for ECOLOR_FORMAT types\r
136         const c8* const ColorFormatNames[ECF_UNKNOWN+2] =\r
137         {\r
138                 "A1R5G5B5",\r
139                 "R5G6B5",\r
140                 "R8G8B8",\r
141                 "A8R8G8B8",\r
142                 "DXT1",\r
143                 "DXT2",\r
144                 "DXT3",\r
145                 "DXT4",\r
146                 "DXT5",\r
147                 "PVRTC_RGB2",\r
148                 "PVRTC_ARGB2",\r
149                 "PVRTC_RGB4",\r
150                 "PVRTC_ARGB4",\r
151                 "PVRTC2_ARGB2",\r
152                 "PVRTC2_ARGB4",\r
153                 "ETC1",\r
154                 "ETC2_RGB",\r
155                 "ETC2_ARGB",\r
156                 "R16F",\r
157                 "G16R16F",\r
158                 "A16B16G16R16F",\r
159                 "R32F",\r
160                 "G32R32F",\r
161                 "A32B32G32R32F",\r
162                 "R8",\r
163                 "R8G8",\r
164                 "R16",\r
165                 "R16G16",\r
166                 "D16",\r
167                 "D32",\r
168                 "D24S8",\r
169                 "UNKNOWN",\r
170                 0\r
171         };\r
172 \r
173 \r
174         //! Creates a 16 bit A1R5G5B5 color\r
175         inline u16 RGBA16(u32 r, u32 g, u32 b, u32 a=0xFF)\r
176         {\r
177                 return (u16)((a & 0x80) << 8 |\r
178                         (r & 0xF8) << 7 |\r
179                         (g & 0xF8) << 2 |\r
180                         (b & 0xF8) >> 3);\r
181         }\r
182 \r
183 \r
184         //! Creates a 16 bit A1R5G5B5 color\r
185         inline u16 RGB16(u32 r, u32 g, u32 b)\r
186         {\r
187                 return RGBA16(r,g,b);\r
188         }\r
189 \r
190 \r
191         //! Creates a 16bit A1R5G5B5 color, based on 16bit input values\r
192         inline u16 RGB16from16(u16 r, u16 g, u16 b)\r
193         {\r
194                 return (0x8000 |\r
195                                 (r & 0x1F) << 10 |\r
196                                 (g & 0x1F) << 5  |\r
197                                 (b & 0x1F));\r
198         }\r
199 \r
200 \r
201         //! Converts a 32bit (X8R8G8B8) color to a 16bit A1R5G5B5 color\r
202         inline u16 X8R8G8B8toA1R5G5B5(u32 color)\r
203         {\r
204                 return (u16)(0x8000 |\r
205                         ( color & 0x00F80000) >> 9 |\r
206                         ( color & 0x0000F800) >> 6 |\r
207                         ( color & 0x000000F8) >> 3);\r
208         }\r
209 \r
210 \r
211         //! Converts a 32bit (A8R8G8B8) color to a 16bit A1R5G5B5 color\r
212         inline u16 A8R8G8B8toA1R5G5B5(u32 color)\r
213         {\r
214                 return (u16)(( color & 0x80000000) >> 16|\r
215                         ( color & 0x00F80000) >> 9 |\r
216                         ( color & 0x0000F800) >> 6 |\r
217                         ( color & 0x000000F8) >> 3);\r
218         }\r
219 \r
220 \r
221         //! Converts a 32bit (A8R8G8B8) color to a 16bit R5G6B5 color\r
222         inline u16 A8R8G8B8toR5G6B5(u32 color)\r
223         {\r
224                 return (u16)(( color & 0x00F80000) >> 8 |\r
225                         ( color & 0x0000FC00) >> 5 |\r
226                         ( color & 0x000000F8) >> 3);\r
227         }\r
228 \r
229 \r
230         //! Convert A8R8G8B8 Color from A1R5G5B5 color\r
231         /** build a nicer 32bit Color by extending dest lower bits with source high bits. */\r
232         inline u32 A1R5G5B5toA8R8G8B8(u16 color)\r
233         {\r
234                 return ( (( -( (s32) color & 0x00008000 ) >> (s32) 31 ) & 0xFF000000 ) |\r
235                                 (( color & 0x00007C00 ) << 9) | (( color & 0x00007000 ) << 4) |\r
236                                 (( color & 0x000003E0 ) << 6) | (( color & 0x00000380 ) << 1) |\r
237                                 (( color & 0x0000001F ) << 3) | (( color & 0x0000001C ) >> 2)\r
238                                 );\r
239         }\r
240 \r
241 \r
242         //! Returns A8R8G8B8 Color from R5G6B5 color\r
243         inline u32 R5G6B5toA8R8G8B8(u16 color)\r
244         {\r
245                 return 0xFF000000 |\r
246                         ((color & 0xF800) << 8)|\r
247                         ((color & 0x07E0) << 5)|\r
248                         ((color & 0x001F) << 3);\r
249         }\r
250 \r
251 \r
252         //! Returns A1R5G5B5 Color from R5G6B5 color\r
253         inline u16 R5G6B5toA1R5G5B5(u16 color)\r
254         {\r
255                 return 0x8000 | (((color & 0xFFC0) >> 1) | (color & 0x1F));\r
256         }\r
257 \r
258 \r
259         //! Returns R5G6B5 Color from A1R5G5B5 color\r
260         inline u16 A1R5G5B5toR5G6B5(u16 color)\r
261         {\r
262                 return (((color & 0x7FE0) << 1) | (color & 0x1F));\r
263         }\r
264 \r
265 \r
266 \r
267         //! Returns the alpha component from A1R5G5B5 color\r
268         /** In Irrlicht, alpha refers to opacity.\r
269         \return The alpha value of the color. 0 is transparent, 1 is opaque. */\r
270         inline u32 getAlpha(u16 color)\r
271         {\r
272                 return ((color >> 15)&0x1);\r
273         }\r
274 \r
275 \r
276         //! Returns the red component from A1R5G5B5 color.\r
277         /** Shift left by 3 to get 8 bit value. */\r
278         inline u32 getRed(u16 color)\r
279         {\r
280                 return ((color >> 10)&0x1F);\r
281         }\r
282 \r
283 \r
284         //! Returns the green component from A1R5G5B5 color\r
285         /** Shift left by 3 to get 8 bit value. */\r
286         inline u32 getGreen(u16 color)\r
287         {\r
288                 return ((color >> 5)&0x1F);\r
289         }\r
290 \r
291 \r
292         //! Returns the blue component from A1R5G5B5 color\r
293         /** Shift left by 3 to get 8 bit value. */\r
294         inline u32 getBlue(u16 color)\r
295         {\r
296                 return (color & 0x1F);\r
297         }\r
298 \r
299 \r
300         //! Returns the average from a 16 bit A1R5G5B5 color\r
301         inline s32 getAverage(s16 color)\r
302         {\r
303                 return ((getRed(color)<<3) + (getGreen(color)<<3) + (getBlue(color)<<3)) / 3;\r
304         }\r
305 \r
306 \r
307         //! Class representing a 32 bit ARGB color.\r
308         /** The color values for alpha, red, green, and blue are\r
309         stored in a single u32. So all four values may be between 0 and 255.\r
310         Alpha in Irrlicht is opacity, so 0 is fully transparent, 255 is fully opaque (solid).\r
311         This class is used by most parts of the Irrlicht Engine\r
312         to specify a color. Another way is using the class SColorf, which\r
313         stores the color values in 4 floats.\r
314         This class must consist of only one u32 and must not use virtual functions.\r
315         */\r
316         class SColor\r
317         {\r
318         public:\r
319 \r
320                 //! Constructor of the Color. Does nothing.\r
321                 /** The color value is not initialized to save time. */\r
322                 SColor() {}\r
323 \r
324                 //! Constructs the color from 4 values representing the alpha, red, green and blue component.\r
325                 /** Must be values between 0 and 255. */\r
326                 SColor (u32 a, u32 r, u32 g, u32 b)\r
327                         : color(((a & 0xff)<<24) | ((r & 0xff)<<16) | ((g & 0xff)<<8) | (b & 0xff)) {}\r
328 \r
329                 //! Constructs the color from a 32 bit value. Could be another color.\r
330                 SColor(u32 clr)\r
331                         : color(clr) {}\r
332 \r
333                 //! Returns the alpha component of the color.\r
334                 /** The alpha component defines how opaque a color is.\r
335                 \return The alpha value of the color. 0 is fully transparent, 255 is fully opaque. */\r
336                 u32 getAlpha() const { return color>>24; }\r
337 \r
338                 //! Returns the red component of the color.\r
339                 /** \return Value between 0 and 255, specifying how red the color is.\r
340                 0 means no red, 255 means full red. */\r
341                 u32 getRed() const { return (color>>16) & 0xff; }\r
342 \r
343                 //! Returns the green component of the color.\r
344                 /** \return Value between 0 and 255, specifying how green the color is.\r
345                 0 means no green, 255 means full green. */\r
346                 u32 getGreen() const { return (color>>8) & 0xff; }\r
347 \r
348                 //! Returns the blue component of the color.\r
349                 /** \return Value between 0 and 255, specifying how blue the color is.\r
350                 0 means no blue, 255 means full blue. */\r
351                 u32 getBlue() const { return color & 0xff; }\r
352 \r
353                 //! Get lightness of the color in the range [0,255]\r
354                 f32 getLightness() const\r
355                 {\r
356                         return 0.5f*(core::max_(core::max_(getRed(),getGreen()),getBlue())+core::min_(core::min_(getRed(),getGreen()),getBlue()));\r
357                 }\r
358 \r
359                 //! Get luminance of the color in the range [0,255].\r
360                 f32 getLuminance() const\r
361                 {\r
362                         return 0.3f*getRed() + 0.59f*getGreen() + 0.11f*getBlue();\r
363                 }\r
364 \r
365                 //! Get average intensity of the color in the range [0,255].\r
366                 u32 getAverage() const\r
367                 {\r
368                         return ( getRed() + getGreen() + getBlue() ) / 3;\r
369                 }\r
370 \r
371                 //! Sets the alpha component of the Color.\r
372                 /** The alpha component defines how transparent a color should be.\r
373                 \param a The alpha value of the color. 0 is fully transparent, 255 is fully opaque. */\r
374                 void setAlpha(u32 a) { color = ((a & 0xff)<<24) | (color & 0x00ffffff); }\r
375 \r
376                 //! Sets the red component of the Color.\r
377                 /** \param r: Has to be a value between 0 and 255.\r
378                 0 means no red, 255 means full red. */\r
379                 void setRed(u32 r) { color = ((r & 0xff)<<16) | (color & 0xff00ffff); }\r
380 \r
381                 //! Sets the green component of the Color.\r
382                 /** \param g: Has to be a value between 0 and 255.\r
383                 0 means no green, 255 means full green. */\r
384                 void setGreen(u32 g) { color = ((g & 0xff)<<8) | (color & 0xffff00ff); }\r
385 \r
386                 //! Sets the blue component of the Color.\r
387                 /** \param b: Has to be a value between 0 and 255.\r
388                 0 means no blue, 255 means full blue. */\r
389                 void setBlue(u32 b) { color = (b & 0xff) | (color & 0xffffff00); }\r
390 \r
391                 //! Calculates a 16 bit A1R5G5B5 value of this color.\r
392                 /** \return 16 bit A1R5G5B5 value of this color. */\r
393                 u16 toA1R5G5B5() const { return A8R8G8B8toA1R5G5B5(color); }\r
394 \r
395                 //! Converts color to OpenGL color format\r
396                 /** From ARGB to RGBA in 4 byte components for endian aware\r
397                 passing to OpenGL\r
398                 \param dest: address where the 4x8 bit OpenGL color is stored. */\r
399                 void toOpenGLColor(u8* dest) const\r
400                 {\r
401                         *dest =   (u8)getRed();\r
402                         *++dest = (u8)getGreen();\r
403                         *++dest = (u8)getBlue();\r
404                         *++dest = (u8)getAlpha();\r
405                 }\r
406 \r
407                 //! Sets all four components of the color at once.\r
408                 /** Constructs the color from 4 values representing the alpha,\r
409                 red, green and blue components of the color. Must be values\r
410                 between 0 and 255.\r
411                 \param a: Alpha component of the color. The alpha component\r
412                 defines how transparent a color should be. Has to be a value\r
413                 between 0 and 255. 255 means not transparent (opaque), 0 means\r
414                 fully transparent.\r
415                 \param r: Sets the red component of the Color. Has to be a\r
416                 value between 0 and 255. 0 means no red, 255 means full red.\r
417                 \param g: Sets the green component of the Color. Has to be a\r
418                 value between 0 and 255. 0 means no green, 255 means full\r
419                 green.\r
420                 \param b: Sets the blue component of the Color. Has to be a\r
421                 value between 0 and 255. 0 means no blue, 255 means full blue. */\r
422                 void set(u32 a, u32 r, u32 g, u32 b)\r
423                 {\r
424                         color = (((a & 0xff)<<24) | ((r & 0xff)<<16) | ((g & 0xff)<<8) | (b & 0xff));\r
425                 }\r
426                 void set(u32 col) { color = col; }\r
427 \r
428                 //! Compares the color to another color.\r
429                 /** \return True if the colors are the same, and false if not. */\r
430                 bool operator==(const SColor& other) const { return other.color == color; }\r
431 \r
432                 //! Compares the color to another color.\r
433                 /** \return True if the colors are different, and false if they are the same. */\r
434                 bool operator!=(const SColor& other) const { return other.color != color; }\r
435 \r
436                 //! comparison operator\r
437                 /** \return True if this color is smaller than the other one */\r
438                 bool operator<(const SColor& other) const { return (color < other.color); }\r
439 \r
440                 //! Adds two colors, result is clamped to 0..255 values\r
441                 /** \param other Color to add to this color\r
442                 \return Addition of the two colors, clamped to 0..255 values */\r
443                 SColor operator+(const SColor& other) const\r
444                 {\r
445                         return SColor(core::min_(getAlpha() + other.getAlpha(), 255u),\r
446                                         core::min_(getRed() + other.getRed(), 255u),\r
447                                         core::min_(getGreen() + other.getGreen(), 255u),\r
448                                         core::min_(getBlue() + other.getBlue(), 255u));\r
449                 }\r
450 \r
451                 //! Interpolates the color with a f32 value to another color\r
452                 /** \param other: Other color\r
453                 \param d: value between 0.0f and 1.0f. d=0 returns other, d=1 returns this, values between interpolate.\r
454                 \return Interpolated color. */\r
455                 SColor getInterpolated(const SColor &other, f32 d) const\r
456                 {\r
457                         d = core::clamp(d, 0.f, 1.f);\r
458                         const f32 inv = 1.0f - d;\r
459                         return SColor((u32)core::round32(other.getAlpha()*inv + getAlpha()*d),\r
460                                 (u32)core::round32(other.getRed()*inv + getRed()*d),\r
461                                 (u32)core::round32(other.getGreen()*inv + getGreen()*d),\r
462                                 (u32)core::round32(other.getBlue()*inv + getBlue()*d));\r
463                 }\r
464 \r
465                 //! Returns interpolated color. ( quadratic )\r
466                 /** \param c1: first color to interpolate with\r
467                 \param c2: second color to interpolate with\r
468                 \param d: value between 0.0f and 1.0f. */\r
469                 SColor getInterpolated_quadratic(const SColor& c1, const SColor& c2, f32 d) const\r
470                 {\r
471                         // this*(1-d)*(1-d) + 2 * c1 * (1-d) + c2 * d * d;\r
472                         d = core::clamp(d, 0.f, 1.f);\r
473                         const f32 inv = 1.f - d;\r
474                         const f32 mul0 = inv * inv;\r
475                         const f32 mul1 = 2.f * d * inv;\r
476                         const f32 mul2 = d * d;\r
477 \r
478                         return SColor(\r
479                                         core::clamp( core::floor32(\r
480                                                         getAlpha() * mul0 + c1.getAlpha() * mul1 + c2.getAlpha() * mul2 ), 0, 255 ),\r
481                                         core::clamp( core::floor32(\r
482                                                         getRed()   * mul0 + c1.getRed()   * mul1 + c2.getRed()   * mul2 ), 0, 255 ),\r
483                                         core::clamp ( core::floor32(\r
484                                                         getGreen() * mul0 + c1.getGreen() * mul1 + c2.getGreen() * mul2 ), 0, 255 ),\r
485                                         core::clamp ( core::floor32(\r
486                                                         getBlue()  * mul0 + c1.getBlue()  * mul1 + c2.getBlue()  * mul2 ), 0, 255 ));\r
487                 }\r
488 \r
489                 //! set the color by expecting data in the given format\r
490                 /** \param data: must point to valid memory containing color information in the given format\r
491                         \param format: tells the format in which data is available\r
492                 */\r
493                 void setData(const void *data, ECOLOR_FORMAT format)\r
494                 {\r
495                         switch (format)\r
496                         {\r
497                                 case ECF_A1R5G5B5:\r
498                                         color = A1R5G5B5toA8R8G8B8(*(u16*)data);\r
499                                         break;\r
500                                 case ECF_R5G6B5:\r
501                                         color = R5G6B5toA8R8G8B8(*(u16*)data);\r
502                                         break;\r
503                                 case ECF_A8R8G8B8:\r
504                                         color = *(u32*)data;\r
505                                         break;\r
506                                 case ECF_R8G8B8:\r
507                                         {\r
508                                                 const u8* p = (u8*)data;\r
509                                                 set(255, p[0],p[1],p[2]);\r
510                                         }\r
511                                         break;\r
512                                 default:\r
513                                         color = 0xffffffff;\r
514                                 break;\r
515                         }\r
516                 }\r
517 \r
518                 //! Write the color to data in the defined format\r
519                 /** \param data: target to write the color. Must contain sufficiently large memory to receive the number of bytes neede for format\r
520                         \param format: tells the format used to write the color into data\r
521                 */\r
522                 void getData(void *data, ECOLOR_FORMAT format) const\r
523                 {\r
524                         switch(format)\r
525                         {\r
526                                 case ECF_A1R5G5B5:\r
527                                 {\r
528                                         u16 * dest = (u16*)data;\r
529                                         *dest = video::A8R8G8B8toA1R5G5B5( color );\r
530                                 }\r
531                                 break;\r
532 \r
533                                 case ECF_R5G6B5:\r
534                                 {\r
535                                         u16 * dest = (u16*)data;\r
536                                         *dest = video::A8R8G8B8toR5G6B5( color );\r
537                                 }\r
538                                 break;\r
539 \r
540                                 case ECF_R8G8B8:\r
541                                 {\r
542                                         u8* dest = (u8*)data;\r
543                                         dest[0] = (u8)getRed();\r
544                                         dest[1] = (u8)getGreen();\r
545                                         dest[2] = (u8)getBlue();\r
546                                 }\r
547                                 break;\r
548 \r
549                                 case ECF_A8R8G8B8:\r
550                                 {\r
551                                         u32 * dest = (u32*)data;\r
552                                         *dest = color;\r
553                                 }\r
554                                 break;\r
555 \r
556                                 default:\r
557                                 break;\r
558                         }\r
559                 }\r
560 \r
561                 //! color in A8R8G8B8 Format\r
562                 u32 color;\r
563         };\r
564 \r
565 \r
566         //! Class representing a color with four floats.\r
567         /** The color values for red, green, blue\r
568         and alpha are each stored in a 32 bit floating point variable.\r
569         So all four values may be between 0.0f and 1.0f.\r
570         Another, faster way to define colors is using the class SColor, which\r
571         stores the color values in a single 32 bit integer.\r
572         */\r
573         class SColorf\r
574         {\r
575         public:\r
576                 //! Default constructor for SColorf.\r
577                 /** Sets red, green and blue to 0.0f and alpha to 1.0f. */\r
578                 SColorf() : r(0.0f), g(0.0f), b(0.0f), a(1.0f) {}\r
579 \r
580                 //! Constructs a color from up to four color values: red, green, blue, and alpha.\r
581                 /** \param r: Red color component. Should be a value between\r
582                 0.0f meaning no red and 1.0f, meaning full red.\r
583                 \param g: Green color component. Should be a value between 0.0f\r
584                 meaning no green and 1.0f, meaning full green.\r
585                 \param b: Blue color component. Should be a value between 0.0f\r
586                 meaning no blue and 1.0f, meaning full blue.\r
587                 \param a: Alpha color component of the color. The alpha\r
588                 component defines how transparent a color should be. Has to be\r
589                 a value between 0.0f and 1.0f, 1.0f means not transparent\r
590                 (opaque), 0.0f means fully transparent. */\r
591                 SColorf(f32 r, f32 g, f32 b, f32 a = 1.0f) : r(r), g(g), b(b), a(a) {}\r
592 \r
593                 //! Constructs a color from 32 bit Color.\r
594                 /** \param c: 32 bit color from which this SColorf class is\r
595                 constructed from. */\r
596                 SColorf(SColor c)\r
597                 {\r
598                         const f32 inv = 1.0f / 255.0f;\r
599                         r = c.getRed() * inv;\r
600                         g = c.getGreen() * inv;\r
601                         b = c.getBlue() * inv;\r
602                         a = c.getAlpha() * inv;\r
603                 }\r
604 \r
605                 //! Converts this color to a SColor without floats.\r
606                 SColor toSColor() const\r
607                 {\r
608                         return SColor((u32)core::round32(a*255.0f), (u32)core::round32(r*255.0f), (u32)core::round32(g*255.0f), (u32)core::round32(b*255.0f));\r
609                 }\r
610 \r
611                 //! Sets three color components to new values at once.\r
612                 /** \param rr: Red color component. Should be a value between 0.0f meaning\r
613                 no red (=black) and 1.0f, meaning full red.\r
614                 \param gg: Green color component. Should be a value between 0.0f meaning\r
615                 no green (=black) and 1.0f, meaning full green.\r
616                 \param bb: Blue color component. Should be a value between 0.0f meaning\r
617                 no blue (=black) and 1.0f, meaning full blue. */\r
618                 void set(f32 rr, f32 gg, f32 bb) {r = rr; g =gg; b = bb; }\r
619 \r
620                 //! Sets all four color components to new values at once.\r
621                 /** \param aa: Alpha component. Should be a value between 0.0f meaning\r
622                 fully transparent and 1.0f, meaning opaque.\r
623                 \param rr: Red color component. Should be a value between 0.0f meaning\r
624                 no red and 1.0f, meaning full red.\r
625                 \param gg: Green color component. Should be a value between 0.0f meaning\r
626                 no green and 1.0f, meaning full green.\r
627                 \param bb: Blue color component. Should be a value between 0.0f meaning\r
628                 no blue and 1.0f, meaning full blue. */\r
629                 void set(f32 aa, f32 rr, f32 gg, f32 bb) {a = aa; r = rr; g =gg; b = bb; }\r
630 \r
631                 //! Interpolates the color with a f32 value to another color\r
632                 /** \param other: Other color\r
633                 \param d: value between 0.0f and 1.0f\r
634                 \return Interpolated color. */\r
635                 SColorf getInterpolated(const SColorf &other, f32 d) const\r
636                 {\r
637                         d = core::clamp(d, 0.f, 1.f);\r
638                         const f32 inv = 1.0f - d;\r
639                         return SColorf(other.r*inv + r*d,\r
640                                 other.g*inv + g*d, other.b*inv + b*d, other.a*inv + a*d);\r
641                 }\r
642 \r
643                 //! Returns interpolated color. ( quadratic )\r
644                 /** \param c1: first color to interpolate with\r
645                 \param c2: second color to interpolate with\r
646                 \param d: value between 0.0f and 1.0f. */\r
647                 inline SColorf getInterpolated_quadratic(const SColorf& c1, const SColorf& c2,\r
648                                 f32 d) const\r
649                 {\r
650                         d = core::clamp(d, 0.f, 1.f);\r
651                         // this*(1-d)*(1-d) + 2 * c1 * (1-d) + c2 * d * d;\r
652                         const f32 inv = 1.f - d;\r
653                         const f32 mul0 = inv * inv;\r
654                         const f32 mul1 = 2.f * d * inv;\r
655                         const f32 mul2 = d * d;\r
656 \r
657                         return SColorf (r * mul0 + c1.r * mul1 + c2.r * mul2,\r
658                                         g * mul0 + c1.g * mul1 + c2.g * mul2,\r
659                                         b * mul0 + c1.b * mul1 + c2.b * mul2,\r
660                                         a * mul0 + c1.a * mul1 + c2.a * mul2);\r
661                 }\r
662 \r
663 \r
664                 //! Sets a color component by index. R=0, G=1, B=2, A=3\r
665                 void setColorComponentValue(s32 index, f32 value)\r
666                 {\r
667                         switch(index)\r
668                         {\r
669                         case 0: r = value; break;\r
670                         case 1: g = value; break;\r
671                         case 2: b = value; break;\r
672                         case 3: a = value; break;\r
673                         }\r
674                 }\r
675 \r
676                 //! Returns the alpha component of the color in the range 0.0 (transparent) to 1.0 (opaque)\r
677                 f32 getAlpha() const { return a; }\r
678 \r
679                 //! Returns the red component of the color in the range 0.0 to 1.0\r
680                 f32 getRed() const { return r; }\r
681 \r
682                 //! Returns the green component of the color in the range 0.0 to 1.0\r
683                 f32 getGreen() const { return g; }\r
684 \r
685                 //! Returns the blue component of the color in the range 0.0 to 1.0\r
686                 f32 getBlue() const { return b; }\r
687 \r
688                 //! red color component\r
689                 f32 r;\r
690 \r
691                 //! green color component\r
692                 f32 g;\r
693 \r
694                 //! blue component\r
695                 f32 b;\r
696 \r
697                 //! alpha color component\r
698                 f32 a;\r
699         };\r
700 \r
701 \r
702         //! Class representing a color in HSL format\r
703         /** The color values for hue, saturation, luminance\r
704         are stored in 32bit floating point variables. Hue is in range [0,360],\r
705         Luminance and Saturation are in percent [0,100]\r
706         */\r
707         class SColorHSL\r
708         {\r
709         public:\r
710                 SColorHSL ( f32 h = 0.f, f32 s = 0.f, f32 l = 0.f )\r
711                         : Hue ( h ), Saturation ( s ), Luminance ( l ) {}\r
712 \r
713                 void fromRGB(const SColorf &color);\r
714                 void toRGB(SColorf &color) const;\r
715 \r
716                 f32 Hue;\r
717                 f32 Saturation;\r
718                 f32 Luminance;\r
719 \r
720         private:\r
721                 inline f32 toRGB1(f32 rm1, f32 rm2, f32 rh) const;\r
722 \r
723         };\r
724 \r
725         inline void SColorHSL::fromRGB(const SColorf &color)\r
726         {\r
727                 const f32 maxVal = core::max_(color.getRed(), color.getGreen(), color.getBlue());\r
728                 const f32 minVal = (f32)core::min_(color.getRed(), color.getGreen(), color.getBlue());\r
729                 Luminance = (maxVal+minVal)*50;\r
730                 if (core::equals(maxVal, minVal))\r
731                 {\r
732                         Hue=0.f;\r
733                         Saturation=0.f;\r
734                         return;\r
735                 }\r
736 \r
737                 const f32 delta = maxVal-minVal;\r
738                 if ( Luminance <= 50 )\r
739                 {\r
740                         Saturation = (delta)/(maxVal+minVal);\r
741                 }\r
742                 else\r
743                 {\r
744                         Saturation = (delta)/(2-maxVal-minVal);\r
745                 }\r
746                 Saturation *= 100;\r
747 \r
748                 if (core::equals(maxVal, color.getRed()))\r
749                         Hue = (color.getGreen()-color.getBlue())/delta;\r
750                 else if (core::equals(maxVal, color.getGreen()))\r
751                         Hue = 2+((color.getBlue()-color.getRed())/delta);\r
752                 else // blue is max\r
753                         Hue = 4+((color.getRed()-color.getGreen())/delta);\r
754 \r
755                 Hue *= 60.0f;\r
756                 while ( Hue < 0.f )\r
757                         Hue += 360;\r
758         }\r
759 \r
760 \r
761         inline void SColorHSL::toRGB(SColorf &color) const\r
762         {\r
763                 const f32 l = Luminance/100;\r
764                 if (core::iszero(Saturation)) // grey\r
765                 {\r
766                         color.set(l, l, l);\r
767                         return;\r
768                 }\r
769 \r
770                 f32 rm2;\r
771 \r
772                 if ( Luminance <= 50 )\r
773                 {\r
774                         rm2 = l + l * (Saturation/100);\r
775                 }\r
776                 else\r
777                 {\r
778                         rm2 = l + (1 - l) * (Saturation/100);\r
779                 }\r
780 \r
781                 const f32 rm1 = 2.0f * l - rm2;\r
782 \r
783                 const f32 h = Hue / 360.0f;\r
784                 color.set( toRGB1(rm1, rm2, h + 1.f/3.f),\r
785                         toRGB1(rm1, rm2, h),\r
786                         toRGB1(rm1, rm2, h - 1.f/3.f)\r
787                         );\r
788         }\r
789 \r
790 \r
791         // algorithm from Foley/Van-Dam\r
792         inline f32 SColorHSL::toRGB1(f32 rm1, f32 rm2, f32 rh) const\r
793         {\r
794                 if (rh<0)\r
795                         rh += 1;\r
796                 if (rh>1)\r
797                         rh -= 1;\r
798 \r
799                 if (rh < 1.f/6.f)\r
800                         rm1 = rm1 + (rm2 - rm1) * rh*6.f;\r
801                 else if (rh < 0.5f)\r
802                         rm1 = rm2;\r
803                 else if (rh < 2.f/3.f)\r
804                         rm1 = rm1 + (rm2 - rm1) * ((2.f/3.f)-rh)*6.f;\r
805 \r
806                 return rm1;\r
807         }\r
808 \r
809 } // end namespace video\r
810 } // end namespace irr\r
811 \r
812 #endif\r