From cb56563d86fbc44d3c7fb2a39269834b0c70547c Mon Sep 17 00:00:00 2001 From: Alix Bott Date: Tue, 8 Mar 2022 00:46:03 +0000 Subject: [PATCH] Add conversions from Color to u32 (#4088) # Objective - `Mesh::ATTRIBUTE_COLOR` expects colors as `u32`s but there is no function for easy conversion. - See https://github.com/bevyengine/bevy/pull/4037#pullrequestreview-894448677 ## Solution - Added `Color::as_rgba_u32` and `Color::as_linear_rgba_u32` --- crates/bevy_render/src/color/mod.rs | 94 ++++++++++++++++++++++++++++- 1 file changed, 93 insertions(+), 1 deletion(-) diff --git a/crates/bevy_render/src/color/mod.rs b/crates/bevy_render/src/color/mod.rs index bdfe03dd44d771..834f2b3aae978e 100644 --- a/crates/bevy_render/src/color/mod.rs +++ b/crates/bevy_render/src/color/mod.rs @@ -414,7 +414,7 @@ impl Color { } } - /// Converts a `Color` to a `[f32; 4]` from linear RBG colorspace + /// Converts a `Color` to a `[f32; 4]` from linear RGB colorspace #[inline] pub fn as_linear_rgba_f32(self: Color) -> [f32; 4] { match self { @@ -487,6 +487,98 @@ impl Color { } => [hue, saturation, lightness, alpha], } } + + /// Converts Color to a u32 from sRGB colorspace. + /// + /// Maps the RGBA channels in RGBA order to a little-endian byte array (GPUs are little-endian). + /// A will be the most significant byte and R the least significant. + pub fn as_rgba_u32(self: Color) -> u32 { + match self { + Color::Rgba { + red, + green, + blue, + alpha, + } => u32::from_le_bytes([ + (red * 255.0) as u8, + (green * 255.0) as u8, + (blue * 255.0) as u8, + (alpha * 255.0) as u8, + ]), + Color::RgbaLinear { + red, + green, + blue, + alpha, + } => u32::from_le_bytes([ + (red.linear_to_nonlinear_srgb() * 255.0) as u8, + (green.linear_to_nonlinear_srgb() * 255.0) as u8, + (blue.linear_to_nonlinear_srgb() * 255.0) as u8, + (alpha * 255.0) as u8, + ]), + Color::Hsla { + hue, + saturation, + lightness, + alpha, + } => { + let [red, green, blue] = + HslRepresentation::hsl_to_nonlinear_srgb(hue, saturation, lightness); + u32::from_le_bytes([ + (red * 255.0) as u8, + (green * 255.0) as u8, + (blue * 255.0) as u8, + (alpha * 255.0) as u8, + ]) + } + } + } + + /// Converts Color to a u32 from linear RGB colorspace. + /// + /// Maps the RGBA channels in RGBA order to a little-endian byte array (GPUs are little-endian). + /// A will be the most significant byte and R the least significant. + pub fn as_linear_rgba_u32(self: Color) -> u32 { + match self { + Color::Rgba { + red, + green, + blue, + alpha, + } => u32::from_le_bytes([ + (red.nonlinear_to_linear_srgb() * 255.0) as u8, + (green.nonlinear_to_linear_srgb() * 255.0) as u8, + (blue.nonlinear_to_linear_srgb() * 255.0) as u8, + (alpha * 255.0) as u8, + ]), + Color::RgbaLinear { + red, + green, + blue, + alpha, + } => u32::from_le_bytes([ + (red * 255.0) as u8, + (green * 255.0) as u8, + (blue * 255.0) as u8, + (alpha * 255.0) as u8, + ]), + Color::Hsla { + hue, + saturation, + lightness, + alpha, + } => { + let [red, green, blue] = + HslRepresentation::hsl_to_nonlinear_srgb(hue, saturation, lightness); + u32::from_le_bytes([ + (red.nonlinear_to_linear_srgb() * 255.0) as u8, + (green.nonlinear_to_linear_srgb() * 255.0) as u8, + (blue.nonlinear_to_linear_srgb() * 255.0) as u8, + (alpha * 255.0) as u8, + ]) + } + } + } } impl Default for Color {