mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
Solve some oklaba inconsistencies (#12526)
# Objective - Even if we have `Laba` and `Oklcha` colorspaces using lightness as the L field name, `Oklaba` doesn't do the same - The shorthand function for creating a new color should be named `Oklaba::lab`, but is named `lch` ## Solution - Rename field l in `Oklaba` to lightness - Rename `Oklaba::lch` to `Oklaba::lab` --- ## Changelog ### Changed - Changed name in l field in `Oklaba` to lightness - Changed method name `Oklaba::lch` to `Oklaba::lab` ## Migration Guide If you were creating a Oklaba instance directly, instead of using L, you should use lightness ```rust // Before let oklaba = Oklaba { l: 1., ..Default::default() }; // Now let oklaba = Oklaba { lightness: 1., ..Default::default() }; ``` if you were using the function `Oklaba::lch`, now the method is named `Oklaba::lab`
This commit is contained in:
parent
1067eaa435
commit
16107385af
3 changed files with 61 additions and 28 deletions
|
@ -266,14 +266,19 @@ impl Color {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new [`Color`] object storing a [`Oklaba`] color.
|
/// Creates a new [`Color`] object storing a [`Oklaba`] color.
|
||||||
pub const fn oklaba(l: f32, a: f32, b: f32, alpha: f32) -> Self {
|
pub const fn oklaba(lightness: f32, a: f32, b: f32, alpha: f32) -> Self {
|
||||||
Self::Oklaba(Oklaba { l, a, b, alpha })
|
Self::Oklaba(Oklaba {
|
||||||
|
lightness,
|
||||||
|
a,
|
||||||
|
b,
|
||||||
|
alpha,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new [`Color`] object storing a [`Oklaba`] color with an alpha of 1.0.
|
/// Creates a new [`Color`] object storing a [`Oklaba`] color with an alpha of 1.0.
|
||||||
pub const fn oklab(l: f32, a: f32, b: f32) -> Self {
|
pub const fn oklab(lightness: f32, a: f32, b: f32) -> Self {
|
||||||
Self::Oklaba(Oklaba {
|
Self::Oklaba(Oklaba {
|
||||||
l,
|
lightness,
|
||||||
a,
|
a,
|
||||||
b,
|
b,
|
||||||
alpha: 1.0,
|
alpha: 1.0,
|
||||||
|
|
|
@ -14,7 +14,7 @@ use serde::{Deserialize, Serialize};
|
||||||
#[reflect(PartialEq, Serialize, Deserialize, Default)]
|
#[reflect(PartialEq, Serialize, Deserialize, Default)]
|
||||||
pub struct Oklaba {
|
pub struct Oklaba {
|
||||||
/// The 'l' channel. [0.0, 1.0]
|
/// The 'l' channel. [0.0, 1.0]
|
||||||
pub l: f32,
|
pub lightness: f32,
|
||||||
/// The 'a' channel. [-1.0, 1.0]
|
/// The 'a' channel. [-1.0, 1.0]
|
||||||
pub a: f32,
|
pub a: f32,
|
||||||
/// The 'b' channel. [-1.0, 1.0]
|
/// The 'b' channel. [-1.0, 1.0]
|
||||||
|
@ -30,24 +30,29 @@ impl Oklaba {
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// * `l` - Lightness channel. [0.0, 1.0]
|
/// * `lightness` - Lightness channel. [0.0, 1.0]
|
||||||
/// * `a` - Green-red channel. [-1.0, 1.0]
|
/// * `a` - Green-red channel. [-1.0, 1.0]
|
||||||
/// * `b` - Blue-yellow channel. [-1.0, 1.0]
|
/// * `b` - Blue-yellow channel. [-1.0, 1.0]
|
||||||
/// * `alpha` - Alpha channel. [0.0, 1.0]
|
/// * `alpha` - Alpha channel. [0.0, 1.0]
|
||||||
pub const fn new(l: f32, a: f32, b: f32, alpha: f32) -> Self {
|
pub const fn new(lightness: f32, a: f32, b: f32, alpha: f32) -> Self {
|
||||||
Self { l, a, b, alpha }
|
Self {
|
||||||
|
lightness,
|
||||||
|
a,
|
||||||
|
b,
|
||||||
|
alpha,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a new [`Oklaba`] color from (l, a, b) components, with the default alpha (1.0).
|
/// Construct a new [`Oklaba`] color from (l, a, b) components, with the default alpha (1.0).
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// * `l` - Lightness channel. [0.0, 1.0]
|
/// * `lightness` - Lightness channel. [0.0, 1.0]
|
||||||
/// * `a` - Green-red channel. [-1.0, 1.0]
|
/// * `a` - Green-red channel. [-1.0, 1.0]
|
||||||
/// * `b` - Blue-yellow channel. [-1.0, 1.0]
|
/// * `b` - Blue-yellow channel. [-1.0, 1.0]
|
||||||
pub const fn lch(l: f32, a: f32, b: f32) -> Self {
|
pub const fn lab(lightness: f32, a: f32, b: f32) -> Self {
|
||||||
Self {
|
Self {
|
||||||
l,
|
lightness,
|
||||||
a,
|
a,
|
||||||
b,
|
b,
|
||||||
alpha: 1.0,
|
alpha: 1.0,
|
||||||
|
@ -55,8 +60,8 @@ impl Oklaba {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a copy of this color with the 'l' channel set to the given value.
|
/// Return a copy of this color with the 'l' channel set to the given value.
|
||||||
pub const fn with_l(self, l: f32) -> Self {
|
pub const fn with_lightness(self, lightness: f32) -> Self {
|
||||||
Self { l, ..self }
|
Self { lightness, ..self }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a copy of this color with the 'a' channel set to the given value.
|
/// Return a copy of this color with the 'a' channel set to the given value.
|
||||||
|
@ -81,7 +86,7 @@ impl Mix for Oklaba {
|
||||||
fn mix(&self, other: &Self, factor: f32) -> Self {
|
fn mix(&self, other: &Self, factor: f32) -> Self {
|
||||||
let n_factor = 1.0 - factor;
|
let n_factor = 1.0 - factor;
|
||||||
Self {
|
Self {
|
||||||
l: self.l * n_factor + other.l * factor,
|
lightness: self.lightness * n_factor + other.lightness * factor,
|
||||||
a: self.a * n_factor + other.a * factor,
|
a: self.a * n_factor + other.a * factor,
|
||||||
b: self.b * n_factor + other.b * factor,
|
b: self.b * n_factor + other.b * factor,
|
||||||
alpha: self.alpha * n_factor + other.alpha * factor,
|
alpha: self.alpha * n_factor + other.alpha * factor,
|
||||||
|
@ -108,27 +113,39 @@ impl Alpha for Oklaba {
|
||||||
|
|
||||||
impl Luminance for Oklaba {
|
impl Luminance for Oklaba {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn with_luminance(&self, l: f32) -> Self {
|
fn with_luminance(&self, lightness: f32) -> Self {
|
||||||
Self { l, ..*self }
|
Self { lightness, ..*self }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn luminance(&self) -> f32 {
|
fn luminance(&self) -> f32 {
|
||||||
self.l
|
self.lightness
|
||||||
}
|
}
|
||||||
|
|
||||||
fn darker(&self, amount: f32) -> Self {
|
fn darker(&self, amount: f32) -> Self {
|
||||||
Self::new((self.l - amount).max(0.), self.a, self.b, self.alpha)
|
Self::new(
|
||||||
|
(self.lightness - amount).max(0.),
|
||||||
|
self.a,
|
||||||
|
self.b,
|
||||||
|
self.alpha,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lighter(&self, amount: f32) -> Self {
|
fn lighter(&self, amount: f32) -> Self {
|
||||||
Self::new((self.l + amount).min(1.), self.a, self.b, self.alpha)
|
Self::new(
|
||||||
|
(self.lightness + amount).min(1.),
|
||||||
|
self.a,
|
||||||
|
self.b,
|
||||||
|
self.alpha,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EuclideanDistance for Oklaba {
|
impl EuclideanDistance for Oklaba {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn distance_squared(&self, other: &Self) -> f32 {
|
fn distance_squared(&self, other: &Self) -> f32 {
|
||||||
(self.l - other.l).powi(2) + (self.a - other.a).powi(2) + (self.b - other.b).powi(2)
|
(self.lightness - other.lightness).powi(2)
|
||||||
|
+ (self.a - other.a).powi(2)
|
||||||
|
+ (self.b - other.b).powi(2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,12 +175,17 @@ impl From<LinearRgba> for Oklaba {
|
||||||
#[allow(clippy::excessive_precision)]
|
#[allow(clippy::excessive_precision)]
|
||||||
impl From<Oklaba> for LinearRgba {
|
impl From<Oklaba> for LinearRgba {
|
||||||
fn from(value: Oklaba) -> Self {
|
fn from(value: Oklaba) -> Self {
|
||||||
let Oklaba { l, a, b, alpha } = value;
|
let Oklaba {
|
||||||
|
lightness,
|
||||||
|
a,
|
||||||
|
b,
|
||||||
|
alpha,
|
||||||
|
} = value;
|
||||||
|
|
||||||
// From https://github.com/Ogeon/palette/blob/e75eab2fb21af579353f51f6229a510d0d50a311/palette/src/oklab.rs#L312-L332
|
// From https://github.com/Ogeon/palette/blob/e75eab2fb21af579353f51f6229a510d0d50a311/palette/src/oklab.rs#L312-L332
|
||||||
let l_ = l + 0.3963377774 * a + 0.2158037573 * b;
|
let l_ = lightness + 0.3963377774 * a + 0.2158037573 * b;
|
||||||
let m_ = l - 0.1055613458 * a - 0.0638541728 * b;
|
let m_ = lightness - 0.1055613458 * a - 0.0638541728 * b;
|
||||||
let s_ = l - 0.0894841775 * a - 1.2914855480 * b;
|
let s_ = lightness - 0.0894841775 * a - 1.2914855480 * b;
|
||||||
|
|
||||||
let l = l_ * l_ * l_;
|
let l = l_ * l_ * l_;
|
||||||
let m = m_ * m_ * m_;
|
let m = m_ * m_ * m_;
|
||||||
|
@ -266,7 +288,7 @@ mod tests {
|
||||||
let oklaba = Oklaba::new(0.5, 0.5, 0.5, 1.0);
|
let oklaba = Oklaba::new(0.5, 0.5, 0.5, 1.0);
|
||||||
let srgba: Srgba = oklaba.into();
|
let srgba: Srgba = oklaba.into();
|
||||||
let oklaba2: Oklaba = srgba.into();
|
let oklaba2: Oklaba = srgba.into();
|
||||||
assert_approx_eq!(oklaba.l, oklaba2.l, 0.001);
|
assert_approx_eq!(oklaba.lightness, oklaba2.lightness, 0.001);
|
||||||
assert_approx_eq!(oklaba.a, oklaba2.a, 0.001);
|
assert_approx_eq!(oklaba.a, oklaba2.a, 0.001);
|
||||||
assert_approx_eq!(oklaba.b, oklaba2.b, 0.001);
|
assert_approx_eq!(oklaba.b, oklaba2.b, 0.001);
|
||||||
assert_approx_eq!(oklaba.alpha, oklaba2.alpha, 0.001);
|
assert_approx_eq!(oklaba.alpha, oklaba2.alpha, 0.001);
|
||||||
|
@ -299,7 +321,7 @@ mod tests {
|
||||||
let oklaba = Oklaba::new(0.5, 0.5, 0.5, 1.0);
|
let oklaba = Oklaba::new(0.5, 0.5, 0.5, 1.0);
|
||||||
let linear: LinearRgba = oklaba.into();
|
let linear: LinearRgba = oklaba.into();
|
||||||
let oklaba2: Oklaba = linear.into();
|
let oklaba2: Oklaba = linear.into();
|
||||||
assert_approx_eq!(oklaba.l, oklaba2.l, 0.001);
|
assert_approx_eq!(oklaba.lightness, oklaba2.lightness, 0.001);
|
||||||
assert_approx_eq!(oklaba.a, oklaba2.a, 0.001);
|
assert_approx_eq!(oklaba.a, oklaba2.a, 0.001);
|
||||||
assert_approx_eq!(oklaba.b, oklaba2.b, 0.001);
|
assert_approx_eq!(oklaba.b, oklaba2.b, 0.001);
|
||||||
assert_approx_eq!(oklaba.alpha, oklaba2.alpha, 0.001);
|
assert_approx_eq!(oklaba.alpha, oklaba2.alpha, 0.001);
|
||||||
|
|
|
@ -175,8 +175,14 @@ impl EuclideanDistance for Oklcha {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Oklaba> for Oklcha {
|
impl From<Oklaba> for Oklcha {
|
||||||
fn from(Oklaba { l, a, b, alpha }: Oklaba) -> Self {
|
fn from(
|
||||||
let lightness = l;
|
Oklaba {
|
||||||
|
lightness,
|
||||||
|
a,
|
||||||
|
b,
|
||||||
|
alpha,
|
||||||
|
}: Oklaba,
|
||||||
|
) -> Self {
|
||||||
let chroma = a.hypot(b);
|
let chroma = a.hypot(b);
|
||||||
let hue = b.atan2(a).to_degrees();
|
let hue = b.atan2(a).to_degrees();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue