1 /** color functions and utilities */
2
3 module re.gfx.color_ext;
4
5 import re.gfx.raytypes;
6 import re.math;
7 import std.math;
8 static import raylib;
9
10 // - color functions
11
12 pragma(inline) {
13 /// gets a color that is white with a given alpha
14 public Color color_alpha_white(float alpha) {
15 return raylib.ColorFromNormalized(raylib.Vector4(1, 1, 1, alpha));
16 }
17
18 /// gets a color from floats
19 public Color color_alpha_white(float r, float g, float b, float a = 1) {
20 return raylib.ColorFromNormalized(raylib.Vector4(r, g, b, a));
21 }
22
23 /// fades a color
24 public Color color_fade(Color color, float fade) {
25 return raylib.Fade(color, fade);
26 }
27
28 /// gets a color from hsv
29 public Color color_hsv(float h, float s, float v) {
30 return raylib.ColorFromHSV(h, s, v);
31 }
32
33 /// gets a color from rgb
34 public Color color_rgb(float r, float g, float b, float a = 1.0) {
35 return raylib.ColorFromNormalized(Vector4(r, g, b, a));
36 }
37
38 /// gets a color from rgb
39 public Color color_rgb(ubyte r, ubyte g, ubyte b, ubyte a = 255) {
40 return Color(r, g, b, 255);
41 }
42
43 /// gets a color from rgb in a single value
44 public Color color_rgb(ubyte v) {
45 return color_rgb(v, v, v);
46 }
47 }
48
49 /// color blending algorithm - from https://stackoverflow.com/a/39924008/13240621
50 public Color color_blend(Color c1, Color c2, float mix) {
51 // Mix [0..1]
52 // 0 --> all c1
53 // 0.5 --> equal mix of c1 and c2
54 // 1 --> all c2
55
56 // Invert sRGB gamma compression
57 c1 = inverse_srgb_companding(c1);
58 c2 = inverse_srgb_companding(c2);
59
60 Color result;
61 result.r = cast(ubyte)(c1.r * (1 - mix) + c2.r * (mix));
62 result.g = cast(ubyte)(c1.g * (1 - mix) + c2.g * (mix));
63 result.b = cast(ubyte)(c1.b * (1 - mix) + c2.b * (mix));
64
65 // Reapply sRGB gamma compression
66 result = srgb_companding(result);
67
68 return result;
69 }
70
71 private Color inverse_srgb_companding(Color c) {
72 // Convert color from 0..255 to 0..1
73 float r = c.r / 255;
74 float g = c.g / 255;
75 float b = c.b / 255;
76
77 // Inverse Red, Green, and Blue
78 if (r > 0.04045)
79 r = pow((r + 0.055) / 1.055, 2.4);
80 else
81 r = r / 12.92;
82 if (g > 0.04045)
83 g = pow((g + 0.055) / 1.055, 2.4);
84 else
85 g = g / 12.92;
86 if (b > 0.04045)
87 b = pow((b + 0.055) / 1.055, 2.4);
88 else
89 b = b / 12.92;
90
91 // Convert 0..1 back into 0..255
92 Color result;
93 result.r = cast(ubyte)(r * 255);
94 result.g = cast(ubyte)(g * 255);
95 result.b = cast(ubyte)(b * 255);
96
97 return result;
98 }
99
100 private Color srgb_companding(Color c) {
101 // Convert color from 0..255 to 0..1
102 float r = c.r / 255;
103 float g = c.g / 255;
104 float b = c.b / 255;
105
106 // Apply companding to Red, Green, and Blue
107 if (r > 0.0031308)
108 r = 1.055 * pow(r, 1 / 2.4) - 0.055;
109 else
110 r = r * 12.92;
111 if (g > 0.0031308)
112 g = 1.055 * pow(g, 1 / 2.4) - 0.055;
113 else
114 g = g * 12.92;
115 if (b > 0.0031308)
116 b = 1.055 * pow(b, 1 / 2.4) - 0.055;
117 else
118 b = b * 12.92;
119
120 // Convert 0..1 back into 0..255
121 Color result;
122 result.r = cast(ubyte)(r * 255);
123 result.g = cast(ubyte)(g * 255);
124 result.b = cast(ubyte)(b * 255);
125
126 return result;
127 }