local lib = {} ---@param x number ---@return number local function fromLinear(x) if x >= 0.0031308 then return 1.055 * math.pow(x, 1.0/2.4) - 0.055 else return 12.92 * x end end ---@param x number ---@return number local function toLinear(x) if x >= 0.04045 then return math.pow((x + 0.055)/(1 + 0.055), 2.4) else return x / 12.92 end end ---Converts from sRGB to Linear sRGB ---@param color Vector3 ---@return Vector3 function lib.srgbToLinear(color) return vec(toLinear(color.x), toLinear(color.y), toLinear(color.z)) end ---Converts from Linear sRGB to sRGB ---@param color Vector3 ---@return Vector3 function lib.linearToSrgb(color) return vec(fromLinear(color.x), fromLinear(color.y), fromLinear(color.z)) end ---Converts from Linear sRGB to OKLAB ---@param color Vector3 ---@return Vector3 function lib.linearToOklab(color) local l = 0.4122214708 * color.r + 0.5363325363 * color.g + 0.0514459929 * color.b local m = 0.2119034982 * color.r + 0.6806995451 * color.g + 0.1073969566 * color.b local s = 0.0883024619 * color.r + 0.2817188376 * color.g + 0.6299787005 * color.b local l_ = math.pow(l, 1/3) local m_ = math.pow(m, 1/3) local s_ = math.pow(s, 1/3) return vec( 0.2104542553*l_ + 0.7936177850*m_ - 0.0040720468*s_, 1.9779984951*l_ - 2.4285922050*m_ + 0.4505937099*s_, 0.0259040371*l_ + 0.7827717662*m_ - 0.8086757660*s_ ) end ---Converts from OKLAB to Linear sRGB ---@param color Vector3 ---@return Vector3 function lib.oklabToLinear(color) local l_ = color.x + 0.3963377774 * color.y + 0.2158037573 * color.z; local m_ = color.x - 0.1055613458 * color.y - 0.0638541728 * color.z; local s_ = color.x - 0.0894841775 * color.y - 1.2914855480 * color.z; local l = l_*l_*l_; local m = m_*m_*m_; local s = s_*s_*s_; return vec( 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s, -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s, -0.0041960863 * l - 0.7034186147 * m + 1.7076147010 * s ) end ---Converts from LAB to LCh ---@param color Vector3 ---@return Vector3 function lib.labToLch(color) return vec( color.x, math.sqrt(color.y * color.y + color.z * color.z), math.deg(math.atan2(color.z, color.y)) ) end ---Converts from LCh to LAB ---@param color Vector3 ---@return Vector3 function lib.lchToLab(color) return vec( color.x, color.y * math.cos(math.rad(color.z)), color.y * math.sin(math.rad(color.z)) ) end ---Converts from sRGB to OKLCh ---@param color Vector3 ---@return Vector3 function lib.srgbToOklch(color) return lib.labToLch(lib.linearToOklab(lib.srgbToLinear(color))) end ---Converts from OKLCh to sRGB ---@param color Vector3 ---@return Vector3 function lib.oklchToSrgb(color) return lib.linearToSrgb(lib.oklabToLinear(lib.lchToLab(color))) end return lib