From 4df7441cbe5941ebffc3f6704d60e80e64056d80 Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Fri, 2 Oct 2020 17:29:58 +0200 Subject: [PATCH 01/11] Color is now sRGB aware, added SrgbColorSpace trait for f32 --- crates/bevy_render/src/color.rs | 84 ++++++++++++++++++++++++---- crates/bevy_render/src/colorspace.rs | 48 ++++++++++++++++ crates/bevy_render/src/lib.rs | 1 + 3 files changed, 122 insertions(+), 11 deletions(-) create mode 100644 crates/bevy_render/src/colorspace.rs diff --git a/crates/bevy_render/src/color.rs b/crates/bevy_render/src/color.rs index 6c626231d953a..2dc5365a0337d 100644 --- a/crates/bevy_render/src/color.rs +++ b/crates/bevy_render/src/color.rs @@ -1,5 +1,6 @@ use super::texture::Texture; use crate::{ + colorspace::*, impl_render_resource_bytes, renderer::{RenderResource, RenderResourceType}, }; @@ -10,7 +11,7 @@ use bevy_property::Property; use serde::{Deserialize, Serialize}; use std::ops::{Add, AddAssign, Mul, MulAssign}; -/// A RGBA color +/// RGBA color in linear colorspace and 32-bit per component. #[repr(C)] #[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Property)] pub struct Color { @@ -23,18 +24,60 @@ pub struct Color { unsafe impl Byteable for Color {} impl Color { - pub const BLACK: Color = Color::rgb(0.0, 0.0, 0.0); - pub const BLUE: Color = Color::rgb(0.0, 0.0, 1.0); - pub const GREEN: Color = Color::rgb(0.0, 1.0, 0.0); - pub const NONE: Color = Color::rgba(0.0, 0.0, 0.0, 0.0); - pub const RED: Color = Color::rgb(1.0, 0.0, 0.0); - pub const WHITE: Color = Color::rgb(1.0, 1.0, 1.0); - - pub const fn rgb(r: f32, g: f32, b: f32) -> Color { + pub const BLACK: Color = Color { + r: 0.0, + g: 0.0, + b: 0.0, + a: 1.0, + }; + pub const BLUE: Color = Color { + r: 0.0, + g: 0.0, + b: 1.0, + a: 1.0, + }; + pub const GREEN: Color = Color { + r: 0.0, + g: 1.0, + b: 0.0, + a: 1.0, + }; + pub const NONE: Color = Color { + r: 0.0, + g: 0.0, + b: 0.0, + a: 0.0, + }; + pub const RED: Color = Color { + r: 1.0, + g: 0.0, + b: 0.0, + a: 1.0, + }; + pub const WHITE: Color = Color { + r: 1.0, + g: 1.0, + b: 1.0, + a: 1.0, + }; + + /// New ``Color`` from sRGB colorspace. + pub fn rgb(r: f32, g: f32, b: f32) -> Color { + Color { r, g, b, a: 1.0 }.as_srgb_to_linear() + } + + /// New ``Color`` from sRGB colorspace. + pub fn rgba(r: f32, g: f32, b: f32, a: f32) -> Color { + Color { r, g, b, a }.as_srgb_to_linear() + } + + /// New ``Color`` from linear colorspace. + pub fn rgb_linear(r: f32, g: f32, b: f32) -> Color { Color { r, g, b, a: 1.0 } } - pub const fn rgba(r: f32, g: f32, b: f32, a: f32) -> Color { + /// New ``Color`` from linear colorspace. + pub fn rgba_linear(r: f32, g: f32, b: f32, a: f32) -> Color { Color { r, g, b, a } } @@ -73,13 +116,14 @@ impl Color { Err(HexColorError::Length) } - + /// New ``Color`` from sRGB colorspace. pub fn rgb_u8(r: u8, g: u8, b: u8) -> Color { Color::rgba_u8(r, g, b, u8::MAX) } // Float operations in const fn are not stable yet // see https://github.com/rust-lang/rust/issues/57241 + /// New ``Color`` from sRGB colorspace. pub fn rgba_u8(r: u8, g: u8, b: u8, a: u8) -> Color { Color::rgba( r as f32 / u8::MAX as f32, @@ -88,6 +132,24 @@ impl Color { a as f32 / u8::MAX as f32, ) } + + fn as_srgb_to_linear(self) -> Color { + Color { + r: self.r.srgb_to_linear(), + g: self.g.srgb_to_linear(), + b: self.b.srgb_to_linear(), + a: self.a, //alpha is always linear + } + } + + pub fn to_srgb(self) -> Color { + Color { + r: self.r.linear_to_srgb(), + g: self.g.linear_to_srgb(), + b: self.b.linear_to_srgb(), + a: self.a, //alpha is always linear + } + } } impl Default for Color { diff --git a/crates/bevy_render/src/colorspace.rs b/crates/bevy_render/src/colorspace.rs new file mode 100644 index 0000000000000..aaa1eff1783a6 --- /dev/null +++ b/crates/bevy_render/src/colorspace.rs @@ -0,0 +1,48 @@ +// sRGB +//================================================================================================== +pub trait SrgbColorSpace { + fn linear_to_srgb(self) -> Self; + fn srgb_to_linear(self) -> Self; +} + +//source: https://entropymine.com/imageworsener/srgbformula/ +impl SrgbColorSpace for f32 { + fn linear_to_srgb(self) -> f32 { + if self <= 0.0 { + return self; + } + + if self <= 0.0031308 { + self * 12.92 // linear falloff in dark values + } else { + (1.055 * self.powf(1.0 / 2.4)) - 0.055 //gamma curve in other area + } + } + + fn srgb_to_linear(self) -> f32 { + if self <= 0.0 { + return self; + } + if self <= 0.04045 { + self / 12.92 // linear falloff in dark values + } else { + ((self + 0.055) / 1.055).powf(2.4) //gamma curve in other area + } + } +} + +#[test] +fn test_srgb_full_roundtrip() { + let u8max: f32 = u8::max_value() as f32; + for color in 0..u8::max_value() { + let color01 = color as f32 / u8max; + let color_roundtrip = color01.linear_to_srgb().srgb_to_linear(); + // roundtrip is not perfect due to numeric precision, even with f64 + // so ensure the error is at least ready for u8 (where sRGB is used) + assert_eq!( + (color01 * u8max).round() as u8, + (color_roundtrip * u8max).round() as u8 + ); + } +} +//================================================================================================== diff --git a/crates/bevy_render/src/lib.rs b/crates/bevy_render/src/lib.rs index 0bdcf8a7bbde1..ebcdf04c4f9a6 100644 --- a/crates/bevy_render/src/lib.rs +++ b/crates/bevy_render/src/lib.rs @@ -1,6 +1,7 @@ pub mod batch; pub mod camera; pub mod color; +pub mod colorspace; pub mod draw; pub mod entity; pub mod mesh; From 6aa48bfe0e97bb4972fdd3b910a175cb93d43d46 Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Fri, 2 Oct 2020 17:37:26 +0200 Subject: [PATCH 02/11] improved constant color values --- crates/bevy_render/src/color.rs | 51 ++++++++------------------------- 1 file changed, 12 insertions(+), 39 deletions(-) diff --git a/crates/bevy_render/src/color.rs b/crates/bevy_render/src/color.rs index 2dc5365a0337d..5455110a1bbcf 100644 --- a/crates/bevy_render/src/color.rs +++ b/crates/bevy_render/src/color.rs @@ -24,43 +24,15 @@ pub struct Color { unsafe impl Byteable for Color {} impl Color { - pub const BLACK: Color = Color { - r: 0.0, - g: 0.0, - b: 0.0, - a: 1.0, - }; - pub const BLUE: Color = Color { - r: 0.0, - g: 0.0, - b: 1.0, - a: 1.0, - }; - pub const GREEN: Color = Color { - r: 0.0, - g: 1.0, - b: 0.0, - a: 1.0, - }; - pub const NONE: Color = Color { - r: 0.0, - g: 0.0, - b: 0.0, - a: 0.0, - }; - pub const RED: Color = Color { - r: 1.0, - g: 0.0, - b: 0.0, - a: 1.0, - }; - pub const WHITE: Color = Color { - r: 1.0, - g: 1.0, - b: 1.0, - a: 1.0, - }; - + pub const BLACK: Color = Color::rgb_linear(0.0, 0.0, 0.0); + pub const BLUE: Color = Color::rgb_linear(0.0, 0.0, 1.0); + pub const GREEN: Color = Color::rgb_linear(0.0, 1.0, 0.0); + pub const NONE: Color = Color::rgba_linear(0.0, 0.0, 0.0, 0.0); + pub const RED: Color = Color::rgb_linear(1.0, 0.0, 0.0); + pub const WHITE: Color = Color::rgb_linear(1.0, 1.0, 1.0); + + // TODO: cant make rgb and rgba const due traits not allowed in const functions + // see issue #57563 https://github.com/rust-lang/rust/issues/57563 /// New ``Color`` from sRGB colorspace. pub fn rgb(r: f32, g: f32, b: f32) -> Color { Color { r, g, b, a: 1.0 }.as_srgb_to_linear() @@ -72,12 +44,12 @@ impl Color { } /// New ``Color`` from linear colorspace. - pub fn rgb_linear(r: f32, g: f32, b: f32) -> Color { + pub const fn rgb_linear(r: f32, g: f32, b: f32) -> Color { Color { r, g, b, a: 1.0 } } /// New ``Color`` from linear colorspace. - pub fn rgba_linear(r: f32, g: f32, b: f32, a: f32) -> Color { + pub const fn rgba_linear(r: f32, g: f32, b: f32, a: f32) -> Color { Color { r, g, b, a } } @@ -116,6 +88,7 @@ impl Color { Err(HexColorError::Length) } + /// New ``Color`` from sRGB colorspace. pub fn rgb_u8(r: u8, g: u8, b: u8) -> Color { Color::rgba_u8(r, g, b, u8::MAX) From 42f79c835d54619d4d6190f16e8f8d61d592a841 Mon Sep 17 00:00:00 2001 From: julhe Date: Fri, 2 Oct 2020 22:54:20 +0200 Subject: [PATCH 03/11] Update crates/bevy_render/src/color.rs Co-authored-by: Gray Olson --- crates/bevy_render/src/color.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_render/src/color.rs b/crates/bevy_render/src/color.rs index 5455110a1bbcf..392b58f780017 100644 --- a/crates/bevy_render/src/color.rs +++ b/crates/bevy_render/src/color.rs @@ -11,7 +11,7 @@ use bevy_property::Property; use serde::{Deserialize, Serialize}; use std::ops::{Add, AddAssign, Mul, MulAssign}; -/// RGBA color in linear colorspace and 32-bit per component. +/// RGBA color in the Linear sRGB colorspace (often colloquially referred to as "linear", "RGB", or "linear RGB"). #[repr(C)] #[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Property)] pub struct Color { From 854446b3e0047bd06f8418581fe631f82d69692f Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Sat, 3 Oct 2020 02:01:23 +0200 Subject: [PATCH 04/11] removed to_srgb, improved naming Co-Authored-By: Gray Olson --- crates/bevy_render/src/color.rs | 21 ++++++--------------- crates/bevy_render/src/colorspace.rs | 10 +++++----- 2 files changed, 11 insertions(+), 20 deletions(-) diff --git a/crates/bevy_render/src/color.rs b/crates/bevy_render/src/color.rs index 392b58f780017..0fab5eca4f217 100644 --- a/crates/bevy_render/src/color.rs +++ b/crates/bevy_render/src/color.rs @@ -35,12 +35,12 @@ impl Color { // see issue #57563 https://github.com/rust-lang/rust/issues/57563 /// New ``Color`` from sRGB colorspace. pub fn rgb(r: f32, g: f32, b: f32) -> Color { - Color { r, g, b, a: 1.0 }.as_srgb_to_linear() + Color { r, g, b, a: 1.0 }.as_nonlinear_srgb_to_linear_srgb() } /// New ``Color`` from sRGB colorspace. pub fn rgba(r: f32, g: f32, b: f32, a: f32) -> Color { - Color { r, g, b, a }.as_srgb_to_linear() + Color { r, g, b, a }.as_nonlinear_srgb_to_linear_srgb() } /// New ``Color`` from linear colorspace. @@ -106,20 +106,11 @@ impl Color { ) } - fn as_srgb_to_linear(self) -> Color { + fn as_nonlinear_srgb_to_linear_srgb(self) -> Color { Color { - r: self.r.srgb_to_linear(), - g: self.g.srgb_to_linear(), - b: self.b.srgb_to_linear(), - a: self.a, //alpha is always linear - } - } - - pub fn to_srgb(self) -> Color { - Color { - r: self.r.linear_to_srgb(), - g: self.g.linear_to_srgb(), - b: self.b.linear_to_srgb(), + r: self.r.nonlinear_to_linear_srgb(), + g: self.g.nonlinear_to_linear_srgb(), + b: self.b.nonlinear_to_linear_srgb(), a: self.a, //alpha is always linear } } diff --git a/crates/bevy_render/src/colorspace.rs b/crates/bevy_render/src/colorspace.rs index aaa1eff1783a6..4027a1c6484cc 100644 --- a/crates/bevy_render/src/colorspace.rs +++ b/crates/bevy_render/src/colorspace.rs @@ -1,13 +1,13 @@ // sRGB //================================================================================================== pub trait SrgbColorSpace { - fn linear_to_srgb(self) -> Self; - fn srgb_to_linear(self) -> Self; + fn linear_to_nonlinear_srgb(self) -> Self; + fn nonlinear_to_linear_srgb(self) -> Self; } //source: https://entropymine.com/imageworsener/srgbformula/ impl SrgbColorSpace for f32 { - fn linear_to_srgb(self) -> f32 { + fn linear_to_nonlinear_srgb(self) -> f32 { if self <= 0.0 { return self; } @@ -19,7 +19,7 @@ impl SrgbColorSpace for f32 { } } - fn srgb_to_linear(self) -> f32 { + fn nonlinear_to_linear_srgb(self) -> f32 { if self <= 0.0 { return self; } @@ -36,7 +36,7 @@ fn test_srgb_full_roundtrip() { let u8max: f32 = u8::max_value() as f32; for color in 0..u8::max_value() { let color01 = color as f32 / u8max; - let color_roundtrip = color01.linear_to_srgb().srgb_to_linear(); + let color_roundtrip = color01.linear_to_nonlinear_srgb().nonlinear_to_linear_srgb(); // roundtrip is not perfect due to numeric precision, even with f64 // so ensure the error is at least ready for u8 (where sRGB is used) assert_eq!( From eab5a6f5a910896e7a16e9111416f8c684c86556 Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Sat, 3 Oct 2020 02:05:04 +0200 Subject: [PATCH 05/11] clippy --- crates/bevy_render/src/colorspace.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/bevy_render/src/colorspace.rs b/crates/bevy_render/src/colorspace.rs index 4027a1c6484cc..3f789b25d4b9c 100644 --- a/crates/bevy_render/src/colorspace.rs +++ b/crates/bevy_render/src/colorspace.rs @@ -36,7 +36,9 @@ fn test_srgb_full_roundtrip() { let u8max: f32 = u8::max_value() as f32; for color in 0..u8::max_value() { let color01 = color as f32 / u8max; - let color_roundtrip = color01.linear_to_nonlinear_srgb().nonlinear_to_linear_srgb(); + let color_roundtrip = color01 + .linear_to_nonlinear_srgb() + .nonlinear_to_linear_srgb(); // roundtrip is not perfect due to numeric precision, even with f64 // so ensure the error is at least ready for u8 (where sRGB is used) assert_eq!( From 003c5333ed5baf6b723cd20c1cbd97cacc7a4421 Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Mon, 5 Oct 2020 01:11:35 +0200 Subject: [PATCH 06/11] added getters and setters for linear- and non-linear color components --- crates/bevy_render/src/color.rs | 204 +++++++++++++++----- crates/bevy_text/src/font.rs | 16 +- crates/bevy_wgpu/src/wgpu_type_converter.rs | 8 +- 3 files changed, 164 insertions(+), 64 deletions(-) diff --git a/crates/bevy_render/src/color.rs b/crates/bevy_render/src/color.rs index 0fab5eca4f217..911a9bf04e05c 100644 --- a/crates/bevy_render/src/color.rs +++ b/crates/bevy_render/src/color.rs @@ -15,10 +15,10 @@ use std::ops::{Add, AddAssign, Mul, MulAssign}; #[repr(C)] #[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Property)] pub struct Color { - pub r: f32, - pub g: f32, - pub b: f32, - pub a: f32, + red: f32, + green: f32, + blue: f32, + alpha: f32, } unsafe impl Byteable for Color {} @@ -35,22 +35,44 @@ impl Color { // see issue #57563 https://github.com/rust-lang/rust/issues/57563 /// New ``Color`` from sRGB colorspace. pub fn rgb(r: f32, g: f32, b: f32) -> Color { - Color { r, g, b, a: 1.0 }.as_nonlinear_srgb_to_linear_srgb() + Color { + red: r, + green: g, + blue: b, + alpha: 1.0, + } + .as_nonlinear_srgb_to_linear_srgb() } /// New ``Color`` from sRGB colorspace. pub fn rgba(r: f32, g: f32, b: f32, a: f32) -> Color { - Color { r, g, b, a }.as_nonlinear_srgb_to_linear_srgb() + Color { + red: r, + green: g, + blue: b, + alpha: a, + } + .as_nonlinear_srgb_to_linear_srgb() } /// New ``Color`` from linear colorspace. pub const fn rgb_linear(r: f32, g: f32, b: f32) -> Color { - Color { r, g, b, a: 1.0 } + Color { + red: r, + green: g, + blue: b, + alpha: 1.0, + } } /// New ``Color`` from linear colorspace. pub const fn rgba_linear(r: f32, g: f32, b: f32, a: f32) -> Color { - Color { r, g, b, a } + Color { + red: r, + green: g, + blue: b, + alpha: a, + } } pub fn hex>(hex: T) -> Result { @@ -108,12 +130,79 @@ impl Color { fn as_nonlinear_srgb_to_linear_srgb(self) -> Color { Color { - r: self.r.nonlinear_to_linear_srgb(), - g: self.g.nonlinear_to_linear_srgb(), - b: self.b.nonlinear_to_linear_srgb(), - a: self.a, //alpha is always linear + red: self.red.nonlinear_to_linear_srgb(), + green: self.green.nonlinear_to_linear_srgb(), + blue: self.blue.nonlinear_to_linear_srgb(), + alpha: self.alpha, //alpha is always linear } } + + // non-linear-sRGB Component Getter + pub fn r(&self) -> f32 { + self.red.linear_to_nonlinear_srgb() + } + + pub fn g(&self) -> f32 { + self.red.linear_to_nonlinear_srgb() + } + + pub fn b(&self) -> f32 { + self.red.linear_to_nonlinear_srgb() + } + + // linear-sRGB Component Getter + pub fn g_linear(&self) -> f32 { + self.green + } + + pub fn r_linear(&self) -> f32 { + self.red + } + + pub fn b_linear(&self) -> f32 { + self.blue + } + + pub fn a_linear(&self) -> f32 { + self.alpha + } + + // non-linear-sRGB Component Setter + pub fn set_r(&mut self, r: f32) -> &mut Self { + self.red = r.nonlinear_to_linear_srgb(); + self + } + + pub fn set_g(&mut self, g: f32) -> &mut Self { + self.green = g.nonlinear_to_linear_srgb(); + self + } + + pub fn set_b(&mut self, b: f32) -> &mut Self { + self.blue = b.nonlinear_to_linear_srgb(); + self + } + + // linear-sRGB Component Setter + pub fn set_r_linear(&mut self, r: f32) -> &mut Self { + self.red = r; + self + } + + pub fn set_g_linear(&mut self, g: f32) -> &mut Self { + self.green = g; + self + } + + pub fn set_b_linear(&mut self, b: f32) -> &mut Self { + self.blue = b; + self + } + + pub fn set_a_linear(&mut self, a: f32) -> &mut Self { + self.alpha = a; + self + } } impl Default for Color { @@ -125,10 +214,10 @@ impl Default for Color { impl AddAssign for Color { fn add_assign(&mut self, rhs: Color) { *self = Color { - r: self.r + rhs.r, - g: self.g + rhs.g, - b: self.b + rhs.b, - a: self.a + rhs.a, + red: self.red + rhs.red, + green: self.green + rhs.green, + blue: self.blue + rhs.blue, + alpha: self.alpha + rhs.alpha, } } } @@ -138,10 +227,10 @@ impl Add for Color { fn add(self, rhs: Color) -> Self::Output { Color { - r: self.r + rhs.r, - g: self.g + rhs.g, - b: self.b + rhs.b, - a: self.a + rhs.a, + red: self.red + rhs.red, + green: self.green + rhs.green, + blue: self.blue + rhs.blue, + alpha: self.alpha + rhs.alpha, } } } @@ -151,10 +240,10 @@ impl Add for Color { fn add(self, rhs: Vec4) -> Self::Output { Color { - r: self.r + rhs.x(), - g: self.g + rhs.y(), - b: self.b + rhs.z(), - a: self.a + rhs.w(), + red: self.red + rhs.x(), + green: self.green + rhs.y(), + blue: self.blue + rhs.z(), + alpha: self.alpha + rhs.w(), } } } @@ -162,17 +251,17 @@ impl Add for Color { impl From for Color { fn from(vec4: Vec4) -> Self { Color { - r: vec4.x(), - g: vec4.y(), - b: vec4.z(), - a: vec4.w(), + red: vec4.x(), + green: vec4.y(), + blue: vec4.z(), + alpha: vec4.w(), } } } impl Into<[f32; 4]> for Color { fn into(self) -> [f32; 4] { - [self.r, self.g, self.b, self.a] + [self.red, self.green, self.blue, self.alpha] } } impl Mul for Color { @@ -180,20 +269,20 @@ impl Mul for Color { fn mul(self, rhs: f32) -> Self::Output { Color { - r: self.r * rhs, - g: self.g * rhs, - b: self.b * rhs, - a: self.a * rhs, + red: self.red * rhs, + green: self.green * rhs, + blue: self.blue * rhs, + alpha: self.alpha * rhs, } } } impl MulAssign for Color { fn mul_assign(&mut self, rhs: f32) { - self.r *= rhs; - self.g *= rhs; - self.b *= rhs; - self.a *= rhs; + self.red *= rhs; + self.green *= rhs; + self.blue *= rhs; + self.alpha *= rhs; } } @@ -202,20 +291,20 @@ impl Mul for Color { fn mul(self, rhs: Vec4) -> Self::Output { Color { - r: self.r * rhs.x(), - g: self.g * rhs.y(), - b: self.b * rhs.z(), - a: self.a * rhs.w(), + red: self.red * rhs.x(), + green: self.green * rhs.y(), + blue: self.blue * rhs.z(), + alpha: self.alpha * rhs.w(), } } } impl MulAssign for Color { fn mul_assign(&mut self, rhs: Vec4) { - self.r *= rhs.x(); - self.g *= rhs.y(); - self.b *= rhs.z(); - self.a *= rhs.w(); + self.red *= rhs.x(); + self.green *= rhs.y(); + self.blue *= rhs.z(); + self.alpha *= rhs.w(); } } @@ -224,19 +313,19 @@ impl Mul for Color { fn mul(self, rhs: Vec3) -> Self::Output { Color { - r: self.r * rhs.x(), - g: self.g * rhs.y(), - b: self.b * rhs.z(), - a: self.a, + red: self.red * rhs.x(), + green: self.green * rhs.y(), + blue: self.blue * rhs.z(), + alpha: self.alpha, } } } impl MulAssign for Color { fn mul_assign(&mut self, rhs: Vec3) { - self.r *= rhs.x(); - self.g *= rhs.y(); - self.b *= rhs.z(); + self.red *= rhs.x(); + self.green *= rhs.y(); + self.blue *= rhs.z(); } } @@ -315,6 +404,17 @@ fn decode_rgba(data: &[u8]) -> Result { } } +#[test] +fn test_color_components_roundtrip() { + let mut color = Color::NONE; + color.set_r(0.5).set_g(0.5).set_b(0.5).set_a_linear(0.5); + const EPS: f32 = 0.001; + assert!((color.r() - 0.5).abs() < EPS); + assert!((color.g() - 0.5).abs() < EPS); + assert!((color.b() - 0.5).abs() < EPS); + assert!((color.a_linear() - 0.5).abs() < EPS); +} + #[test] fn test_hex_color() { assert_eq!(Color::hex("FFF").unwrap(), Color::rgb(1.0, 1.0, 1.0)); diff --git a/crates/bevy_text/src/font.rs b/crates/bevy_text/src/font.rs index 93e61248acdd5..2d389cf4015f0 100644 --- a/crates/bevy_text/src/font.rs +++ b/crates/bevy_text/src/font.rs @@ -30,9 +30,9 @@ impl Font { // TODO: make this texture grayscale let color = Color::WHITE; let color_u8 = [ - (color.r * 255.0) as u8, - (color.g * 255.0) as u8, - (color.b * 255.0) as u8, + (color.r() * 255.0) as u8, + (color.g() * 255.0) as u8, + (color.b() * 255.0) as u8, ]; Texture::new( Vec2::new(width as f32, height as f32), @@ -43,7 +43,7 @@ impl Font { color_u8[0], color_u8[1], color_u8[2], - (color.a * a * 255.0) as u8, + (color.a_linear() * a * 255.0) as u8, ] }) .flatten() @@ -75,9 +75,9 @@ impl Font { ); let color_u8 = [ - (color.r * 255.0) as u8, - (color.g * 255.0) as u8, - (color.b * 255.0) as u8, + (color.r() * 255.0) as u8, + (color.g() * 255.0) as u8, + (color.b() * 255.0) as u8, ]; // TODO: this offset is a bit hackey @@ -108,7 +108,7 @@ impl Font { color_u8[0], color_u8[1], color_u8[2], - (color.a * a * 255.0) as u8, + (color.a_linear() * a * 255.0) as u8, ] }) .flatten() diff --git a/crates/bevy_wgpu/src/wgpu_type_converter.rs b/crates/bevy_wgpu/src/wgpu_type_converter.rs index 083c48a158c85..dfa194d83460e 100644 --- a/crates/bevy_wgpu/src/wgpu_type_converter.rs +++ b/crates/bevy_wgpu/src/wgpu_type_converter.rs @@ -124,10 +124,10 @@ impl<'a> From<&'a OwnedWgpuVertexBufferDescriptor> for wgpu::VertexBufferDescrip impl WgpuFrom for wgpu::Color { fn from(color: Color) -> Self { wgpu::Color { - r: color.r as f64, - g: color.g as f64, - b: color.b as f64, - a: color.a as f64, + r: color.r_linear() as f64, + g: color.g_linear() as f64, + b: color.b_linear() as f64, + a: color.a_linear() as f64, } } } From ea2f0737c24e946ce964275efce63343e203437f Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Mon, 5 Oct 2020 22:21:16 +0200 Subject: [PATCH 07/11] renamed a_linear to a --- crates/bevy_render/src/color.rs | 8 ++++---- crates/bevy_text/src/font.rs | 4 ++-- crates/bevy_wgpu/src/wgpu_type_converter.rs | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/bevy_render/src/color.rs b/crates/bevy_render/src/color.rs index 911a9bf04e05c..5e1ff1e0bf742 100644 --- a/crates/bevy_render/src/color.rs +++ b/crates/bevy_render/src/color.rs @@ -163,7 +163,7 @@ impl Color { self.blue } - pub fn a_linear(&self) -> f32 { + pub fn a(&self) -> f32 { self.alpha } @@ -199,7 +199,7 @@ impl Color { self } - pub fn set_a_linear(&mut self, a: f32) -> &mut Self { + pub fn set_a(&mut self, a: f32) -> &mut Self { self.alpha = a; self } @@ -407,12 +407,12 @@ fn decode_rgba(data: &[u8]) -> Result { #[test] fn test_color_components_roundtrip() { let mut color = Color::NONE; - color.set_r(0.5).set_g(0.5).set_b(0.5).set_a_linear(0.5); + color.set_r(0.5).set_g(0.5).set_b(0.5).set_a(0.5); const EPS: f32 = 0.001; assert!((color.r() - 0.5).abs() < EPS); assert!((color.g() - 0.5).abs() < EPS); assert!((color.b() - 0.5).abs() < EPS); - assert!((color.a_linear() - 0.5).abs() < EPS); + assert!((color.a() - 0.5).abs() < EPS); } #[test] diff --git a/crates/bevy_text/src/font.rs b/crates/bevy_text/src/font.rs index 2d389cf4015f0..a98acd0076a4c 100644 --- a/crates/bevy_text/src/font.rs +++ b/crates/bevy_text/src/font.rs @@ -43,7 +43,7 @@ impl Font { color_u8[0], color_u8[1], color_u8[2], - (color.a_linear() * a * 255.0) as u8, + (color.a() * a * 255.0) as u8, ] }) .flatten() @@ -108,7 +108,7 @@ impl Font { color_u8[0], color_u8[1], color_u8[2], - (color.a_linear() * a * 255.0) as u8, + (color.a() * a * 255.0) as u8, ] }) .flatten() diff --git a/crates/bevy_wgpu/src/wgpu_type_converter.rs b/crates/bevy_wgpu/src/wgpu_type_converter.rs index dfa194d83460e..7a27620eadc34 100644 --- a/crates/bevy_wgpu/src/wgpu_type_converter.rs +++ b/crates/bevy_wgpu/src/wgpu_type_converter.rs @@ -127,7 +127,7 @@ impl WgpuFrom for wgpu::Color { r: color.r_linear() as f64, g: color.g_linear() as f64, b: color.b_linear() as f64, - a: color.a_linear() as f64, + a: color.a() as f64, } } } From 125e49937499d167b8179f193530fe522db9a26b Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Thu, 8 Oct 2020 02:44:36 +0200 Subject: [PATCH 08/11] added PR to changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d56cb46f13cd..e15c0b1576848 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,8 +5,10 @@ ### Added - [Another fast compile flag for macOS][552] +- [sRGB awareness for ``Color``][616] [552]: https://github.com/bevyengine/bevy/pull/552 +[616]: https://github.com/bevyengine/bevy/pull/616 ## Version 0.2.1 (2020-9-20) From 40ebe14f1f462f6f05baf2de20459ab4692d36ef Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Thu, 8 Oct 2020 02:46:44 +0200 Subject: [PATCH 09/11] correct section --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e15c0b1576848..5ddb750c59f6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,14 +1,14 @@ # Changelog ## Unreleased +- [sRGB awareness for ``Color``][616] +[616]: https://github.com/bevyengine/bevy/pull/616 ### Added - [Another fast compile flag for macOS][552] -- [sRGB awareness for ``Color``][616] [552]: https://github.com/bevyengine/bevy/pull/552 -[616]: https://github.com/bevyengine/bevy/pull/616 ## Version 0.2.1 (2020-9-20) From f00e01313a017e0ff882b2cb1a6aea6fcd6d5b7e Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Thu, 8 Oct 2020 12:45:42 +0200 Subject: [PATCH 10/11] Update CHANGELOG.md Co-Authored-By: Nathan Stocks --- CHANGELOG.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ddb750c59f6d..fc30a0b060303 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,14 +1,20 @@ # Changelog ## Unreleased -- [sRGB awareness for ``Color``][616] -[616]: https://github.com/bevyengine/bevy/pull/616 ### Added - [Another fast compile flag for macOS][552] +### Changed + +- Breaking Change: [sRGB awareness for `Color`][616] + - Color is now assumed to be provided in the non-linear sRGB colorspace, and constructors such as `Color::rgb` and `Color::rgba` will be converted to linear sRGB under-the-hood. This allows drop-in use of colors from most application. + - New methods `Color::rgb_linear` and `Color::rgba_linear` will accept colors already in linear sRGB (the old behavior) + - Individual color-components must now be accessed through setters and getters: `.r`, `.g`, `.b`, `.a`, `.set_r`, `.set_g`, `.set_b`, `.set_a`, and the corresponding methods with the `*_linear` suffix. + [552]: https://github.com/bevyengine/bevy/pull/552 +[616]: https://github.com/bevyengine/bevy/pull/616 ## Version 0.2.1 (2020-9-20) From c53792d3bf0aad73bc3114653b6ed50e329b5f1a Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Thu, 8 Oct 2020 12:46:45 +0200 Subject: [PATCH 11/11] Update CHANGELOG.md Co-Authored-By: Nathan Stocks --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fc30a0b060303..2caa067898624 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,8 @@ ### Changed - Breaking Change: [sRGB awareness for `Color`][616] - - Color is now assumed to be provided in the non-linear sRGB colorspace, and constructors such as `Color::rgb` and `Color::rgba` will be converted to linear sRGB under-the-hood. This allows drop-in use of colors from most application. + - Color is now assumed to be provided in the non-linear sRGB colorspace, and constructors such as `Color::rgb` and `Color::rgba` will be converted to linear sRGB under-the-hood. + - This allows drop-in use of colors from most applications. - New methods `Color::rgb_linear` and `Color::rgba_linear` will accept colors already in linear sRGB (the old behavior) - Individual color-components must now be accessed through setters and getters: `.r`, `.g`, `.b`, `.a`, `.set_r`, `.set_g`, `.set_b`, `.set_a`, and the corresponding methods with the `*_linear` suffix.