mirror of
https://github.com/bevyengine/bevy
synced 2024-11-21 20:23:28 +00:00
Color maths 4 (#12575)
# Objective - Fixes #12202 ## Solution - This PR implements componentwise (including alpha) addition, subtraction and scalar multiplication/division for some color types. - The mentioned color types are `Laba`, `Oklaba`, `LinearRgba` and `Xyza` as all of them are either physically or perceptually linear as mentioned by @alice-i-cecile in the issue. --- ## Changelog - Scalar mul/div for `LinearRgba` may modify alpha now. ## Migration Guide - Users of scalar mul/div for `LinearRgba` need to be aware of the change and maybe use the `.clamp()` methods or manually set the `alpha` channel.
This commit is contained in:
parent
e7a31d000e
commit
d7372f2c75
5 changed files with 81 additions and 50 deletions
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
Alpha, ClampColor, Hsla, Hsva, Hwba, LinearRgba, Luminance, Mix, Oklaba, Srgba, StandardColor,
|
||||
Xyza,
|
||||
impl_componentwise_point, Alpha, ClampColor, Hsla, Hsva, Hwba, LinearRgba, Luminance, Mix,
|
||||
Oklaba, Srgba, StandardColor, Xyza,
|
||||
};
|
||||
use bevy_reflect::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -25,6 +25,8 @@ pub struct Laba {
|
|||
|
||||
impl StandardColor for Laba {}
|
||||
|
||||
impl_componentwise_point!(Laba, [lightness, a, b, alpha]);
|
||||
|
||||
impl Laba {
|
||||
/// Construct a new [`Laba`] color from components.
|
||||
///
|
||||
|
|
|
@ -65,6 +65,12 @@
|
|||
//! types in this crate. This is useful when you need to store a color in a data structure
|
||||
//! that can't be generic over the color type.
|
||||
//!
|
||||
//! Color types that are either physically or perceptually linear also implement `Add<Self>`, `Sub<Self>`, `Mul<f32>` and `Div<f32>`
|
||||
//! allowing you to use them with splines.
|
||||
//!
|
||||
//! Please note that most often adding or subtracting colors is not what you may want.
|
||||
//! Please have a look at other operations like blending, lightening or mixing colors using e.g. [`Mix`] or [`Luminance`] instead.
|
||||
//!
|
||||
//! # Example
|
||||
//!
|
||||
//! ```
|
||||
|
@ -151,3 +157,61 @@ where
|
|||
Self: Alpha,
|
||||
{
|
||||
}
|
||||
|
||||
macro_rules! impl_componentwise_point {
|
||||
($ty: ident, [$($element: ident),+]) => {
|
||||
impl std::ops::Add<Self> for $ty {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
Self::Output {
|
||||
$($element: self.$element + rhs.$element,)+
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Sub<Self> for $ty {
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, rhs: Self) -> Self::Output {
|
||||
Self::Output {
|
||||
$($element: self.$element - rhs.$element,)+
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Mul<f32> for $ty {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, rhs: f32) -> Self::Output {
|
||||
Self::Output {
|
||||
$($element: self.$element * rhs,)+
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Mul<$ty> for f32 {
|
||||
type Output = $ty;
|
||||
|
||||
fn mul(self, rhs: $ty) -> Self::Output {
|
||||
Self::Output {
|
||||
$($element: self * rhs.$element,)+
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Div<f32> for $ty {
|
||||
type Output = Self;
|
||||
|
||||
fn div(self, rhs: f32) -> Self::Output {
|
||||
Self::Output {
|
||||
$($element: self.$element / rhs,)+
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl bevy_math::cubic_splines::Point for $ty {}
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) use impl_componentwise_point;
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use std::ops::{Div, Mul};
|
||||
|
||||
use crate::{
|
||||
color_difference::EuclideanDistance, Alpha, ClampColor, Luminance, Mix, StandardColor,
|
||||
color_difference::EuclideanDistance, impl_componentwise_point, Alpha, ClampColor, Luminance,
|
||||
Mix, StandardColor,
|
||||
};
|
||||
use bevy_math::Vec4;
|
||||
use bevy_reflect::prelude::*;
|
||||
|
@ -29,6 +28,8 @@ pub struct LinearRgba {
|
|||
|
||||
impl StandardColor for LinearRgba {}
|
||||
|
||||
impl_componentwise_point!(LinearRgba, [red, green, blue, alpha]);
|
||||
|
||||
impl LinearRgba {
|
||||
/// A fully black color with full alpha.
|
||||
pub const BLACK: Self = Self {
|
||||
|
@ -299,48 +300,6 @@ impl From<LinearRgba> for wgpu::Color {
|
|||
}
|
||||
}
|
||||
|
||||
/// All color channels are scaled directly,
|
||||
/// but alpha is unchanged.
|
||||
///
|
||||
/// Values are not clamped.
|
||||
impl Mul<f32> for LinearRgba {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, rhs: f32) -> Self {
|
||||
Self {
|
||||
red: self.red * rhs,
|
||||
green: self.green * rhs,
|
||||
blue: self.blue * rhs,
|
||||
alpha: self.alpha,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<LinearRgba> for f32 {
|
||||
type Output = LinearRgba;
|
||||
|
||||
fn mul(self, rhs: LinearRgba) -> LinearRgba {
|
||||
rhs * self
|
||||
}
|
||||
}
|
||||
|
||||
/// All color channels are scaled directly,
|
||||
/// but alpha is unchanged.
|
||||
///
|
||||
/// Values are not clamped.
|
||||
impl Div<f32> for LinearRgba {
|
||||
type Output = Self;
|
||||
|
||||
fn div(self, rhs: f32) -> Self {
|
||||
Self {
|
||||
red: self.red / rhs,
|
||||
green: self.green / rhs,
|
||||
blue: self.blue / rhs,
|
||||
alpha: self.alpha,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// [`LinearRgba`] is intended to be used with shaders
|
||||
// So it's the only color type that implements [`ShaderType`] to make it easier to use inside shaders
|
||||
impl encase::ShaderType for LinearRgba {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
color_difference::EuclideanDistance, Alpha, ClampColor, Hsla, Hsva, Hwba, Lcha, LinearRgba,
|
||||
Luminance, Mix, Srgba, StandardColor, Xyza,
|
||||
color_difference::EuclideanDistance, impl_componentwise_point, Alpha, ClampColor, Hsla, Hsva,
|
||||
Hwba, Lcha, LinearRgba, Luminance, Mix, Srgba, StandardColor, Xyza,
|
||||
};
|
||||
use bevy_reflect::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -25,6 +25,8 @@ pub struct Oklaba {
|
|||
|
||||
impl StandardColor for Oklaba {}
|
||||
|
||||
impl_componentwise_point!(Oklaba, [lightness, a, b, alpha]);
|
||||
|
||||
impl Oklaba {
|
||||
/// Construct a new [`Oklaba`] color from components.
|
||||
///
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
use crate::{Alpha, ClampColor, LinearRgba, Luminance, Mix, StandardColor};
|
||||
use crate::{
|
||||
impl_componentwise_point, Alpha, ClampColor, LinearRgba, Luminance, Mix, StandardColor,
|
||||
};
|
||||
use bevy_reflect::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
@ -22,6 +24,8 @@ pub struct Xyza {
|
|||
|
||||
impl StandardColor for Xyza {}
|
||||
|
||||
impl_componentwise_point!(Xyza, [x, y, z, alpha]);
|
||||
|
||||
impl Xyza {
|
||||
/// Construct a new [`Xyza`] color from components.
|
||||
///
|
||||
|
|
Loading…
Reference in a new issue