85 ice::f32 const l2 = (from.v[0][0] * 1.0f) + (from.v[0][1] * 0.3963377774f) + (from.v[0][2] * 0.2158037573f);
86 ice::f32 const m2 = (from.v[0][0] * 1.0f) + (from.v[0][1] * -0.1055613458f) + (from.v[0][2] * -0.0638541728f);
87 ice::f32 const s2 = (from.v[0][0] * 1.0f) + (from.v[0][1] * -0.0894841775f) + (from.v[0][2] * -1.291485548f);
94 ice::f32 const r_lin = (+4.0767416621f * l3) - (3.3077115913f * m3) + (0.2309699292f * s3);
95 ice::f32 const g_lin = (-1.2684380046f * l3) + (2.6097574011f * m3) - (0.3413193965f * s3);
96 ice::f32 const b_lin = (-0.0041960863f * l3) - (0.7034186147f * m3) + (1.7076147010f * s3);
99 return { r_lin, g_lin, b_lin };
110 ice::f32 k0, k1, k2, k3, k4, wl, wm, ws;
112 if (-1.88170328f * a - 0.80936493f * b > 1)
115 k0 = +1.19086277f; k1 = +1.76576728f; k2 = +0.59662641f; k3 = +0.75515197f; k4 = +0.56771245f;
116 wl = +4.0767416621f; wm = -3.3077115913f; ws = +0.2309699292f;
118 else if (1.81444104f * a - 1.19445276f * b > 1)
121 k0 = +0.73956515f; k1 = -0.45954404f; k2 = +0.08285427f; k3 = +0.12541070f; k4 = +0.14503204f;
122 wl = -1.2684380046f; wm = +2.6097574011f; ws = -0.3413193965f;
127 k0 = +1.35733652f; k1 = -0.00915799f; k2 = -1.15130210f; k3 = -0.50559606f; k4 = +0.00692167f;
128 wl = -0.0041960863f; wm = -0.7034186147f; ws = +1.7076147010f;
132 ice::f32 const s_initial = k0 + k1 * a + k2 * b + k3 * a * a + k4 * a * b;
137 ice::f32 const k_l = +0.3963377774f * a + 0.2158037573f * b;
138 ice::f32 const k_m = -0.1055613458f * a - 0.0638541728f * b;
139 ice::f32 const k_s = -0.0894841775f * a - 1.2914855480f * b;
142 ice::f32 const l_ = 1.f + s_initial * k_l;
143 ice::f32 const m_ = 1.f + s_initial * k_m;
144 ice::f32 const s_ = 1.f + s_initial * k_s;
150 ice::f32 const l_ds = 3.f * k_l * l_ * l_;
151 ice::f32 const m_ds = 3.f * k_m * m_ * m_;
152 ice::f32 const s_ds = 3.f * k_s * s_ * s_;
154 ice::f32 const l_ds2 = 6.f * k_l * k_l * l_;
155 ice::f32 const m_ds2 = 6.f * k_m * k_m * m_;
156 ice::f32 const s_ds2 = 6.f * k_s * k_s * s_;
158 ice::f32 const f = wl * l + wm * m + ws * s;
159 ice::f32 const f1 = wl * l_ds + wm * m_ds + ws * s_ds;
160 ice::f32 const f2 = wl * l_ds2 + wm * m_ds2 + ws * s_ds2;
162 return s_initial - f * f1 / (f1*f1 - 0.5f * f * f2);
177 1.f /
ice::max_of(rgb_at_max.
v[0][0], rgb_at_max.
v[0][1], rgb_at_max.
v[0][2])
180 ice::f32 const c_cusp = l_cusp * s_cusp;
181 return { a, b, l_cusp , c_cusp };
191 ice::f32 const oklab_a_ = oklab_a / C;
192 ice::f32 const oklab_b_ = oklab_b / C;
198 static constexpr std::array<ice::vec2f, 3600> Constant_HueCuspTable = []()
noexcept -> std::array<ice::vec2f, 3600>
202 std::array<ice::vec2f, 3600> result{};
203 while (hue.value < hue_last)
213 result[
ice::u32(hue.value * 10.f)] = { cusp.lightness, cusp.chroma };
225 return Constant_HueCuspTable[
ice::u32(hue.value * 10.f)];
243 if (((L1 - L0) * cusp.chroma - (cusp.lightness - L0) * C1) <= 0.f)
246 t = cusp.chroma * L0 / (C1 * cusp.lightness + cusp.chroma * (L0 - L1));
253 t = cusp.chroma * (L0 - 1.f) / (C1 * (cusp.lightness - 1.f) + cusp.chroma * (L0 - L1));
260 ice::f32 const k_l = +0.3963377774f * cusp.a + 0.2158037573f * cusp.b;
261 ice::f32 const k_m = -0.1055613458f * cusp.a - 0.0638541728f * cusp.b;
262 ice::f32 const k_s = -0.0894841775f * cusp.a - 1.2914855480f * cusp.b;
264 ice::f32 const l_dt = dL + dC * k_l;
265 ice::f32 const m_dt = dL + dC * k_m;
266 ice::f32 const s_dt = dL + dC * k_s;
272 ice::f32 const L = L0 * (1.f - t) + t * L1;
283 ice::f32 const ldt = 3 * l_dt * l_ * l_;
284 ice::f32 const mdt = 3 * m_dt * m_ * m_;
285 ice::f32 const sdt = 3 * s_dt * s_ * s_;
287 ice::f32 const ldt2 = 6 * l_dt * l_dt * l_;
288 ice::f32 const mdt2 = 6 * m_dt * m_dt * m_;
289 ice::f32 const sdt2 = 6 * s_dt * s_dt * s_;
291 ice::f32 const r = 4.0767416621f * l - 3.3077115913f * m + 0.2309699292f * s - 1;
292 ice::f32 const r1 = 4.0767416621f * ldt - 3.3077115913f * mdt + 0.2309699292f * sdt;
293 ice::f32 const r2 = 4.0767416621f * ldt2 - 3.3077115913f * mdt2 + 0.2309699292f * sdt2;
295 ice::f32 const u_r = r1 / (r1 * r1 - 0.5f * r * r2);
298 ice::f32 const g = -1.2684380046f * l + 2.6097574011f * m - 0.3413193965f * s - 1;
299 ice::f32 const g1 = -1.2684380046f * ldt + 2.6097574011f * mdt - 0.3413193965f * sdt;
300 ice::f32 const g2 = -1.2684380046f * ldt2 + 2.6097574011f * mdt2 - 0.3413193965f * sdt2;
302 ice::f32 const u_g = g1 / (g1 * g1 - 0.5f * g * g2);
305 ice::f32 const b0 = -0.0041960863f * l - 0.7034186147f * m + 1.7076147010f * s - 1;
306 ice::f32 const b1 = -0.0041960863f * ldt - 0.7034186147f * mdt + 1.7076147010f * sdt;
307 ice::f32 const b2 = -0.0041960863f * ldt2 - 0.7034186147f * mdt2 + 1.7076147010f * sdt2;
309 ice::f32 const u_b = b1 / (b1 * b1 - 0.5f * b0 * b2);
Definition hashmap_details.hxx:13
constexpr auto find_cusp(ice::f32 a, ice::f32 b) noexcept -> ice::detail::OkLCH_HueCusp
Finds L_cusp and C_cusp for a given 'a' and 'b' values of OKLAB color.
Definition color_details.hxx:168
constexpr auto find_cusp_ch(ice::f32 chroma, ice::rad hue) noexcept -> ice::detail::OkLCH_HueCusp
Finds L_cusp and C_cusp for a given 'a' and 'b' values of OKLAB color.
Definition color_details.hxx:186
constexpr auto from_oklab_to_lrgb(ice::math::vec3f from) noexcept -> ice::math::vec3f
from: https://bottosson.github.io/posts/oklab/
Definition color_details.hxx:81
constexpr auto linear_to_srgb(ice::f32 x) noexcept -> ice::f32
Definition color_details.hxx:29
constexpr auto compute_max_saturation(ice::f32 a, ice::f32 b) noexcept -> ice::f32
Compute max saturation for sRGB.
Definition color_details.hxx:106
constexpr auto srgb_to_linear(ice::f32 x) noexcept -> ice::f32
Definition color_details.hxx:45
constexpr auto find_gamut_intersection(ice::detail::OkLCH_HueCusp cusp, ice::f32 L1, ice::f32 C1, ice::f32 L0) noexcept -> ice::f32
Definition color_details.hxx:234
rad32 rad
Definition angles.hxx:170
constexpr auto max(arr_t< Size, T > left, arr_t< Size, U > right) noexcept -> arr_t< Size, T >
Definition array_operations.hxx:49
deg32 deg
Definition angles.hxx:169
constexpr auto cbrt(f32 val) noexcept -> f32
Definition common.hxx:68
constexpr auto max_of(U first, Args... args) noexcept
Definition algorithm.hxx:54
constexpr auto min_of(U first, Args... args) noexcept
Definition algorithm.hxx:73
constexpr auto sin(rad radians) noexcept -> f32
Definition common.hxx:156
static constexpr ice::f32 f32_eps
Definition constants.hxx:10
constexpr auto cos(rad radians) noexcept -> f32
Definition common.hxx:186
auto pow(f32 base, f32 exp) noexcept -> f32
Definition common.hxx:63
vec< 2, f32 > vec2f
Definition vector.hxx:178
constexpr auto sqrt(f32 val) noexcept -> f32
Definition common.hxx:93
constexpr auto radians(deg degrees) noexcept -> rad
Definition common.hxx:33
vec< 3, f32 > vec3f
Definition vector.hxx:182
constexpr ice::f32 const f32_max
Definition constants.hxx:29
std::uint32_t u32
Definition types.hxx:26
float f32
Definition types.hxx:16
#define IPT_ZONE_SCOPED
Definition profiler.hxx:57
Holds information where the 'lightness' and 'chroma' are at the highest point of the OkLCH color curv...
Definition color_details.hxx:19
ice::f32 chroma
Definition color_details.hxx:22
ice::f32 lightness
Definition color_details.hxx:21
ice::f32 b
Definition color_details.hxx:20
ice::f32 a
Definition color_details.hxx:20
T v[count_columns][count_rows]
Definition matrix.hxx:17