Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds back in way to convert color to u8 array, implemented for the two RGB color types, also renames Color::linear to Color::to_linear. #13759

Merged
merged 6 commits into from
Jun 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion crates/bevy_color/src/color.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,12 @@ impl StandardColor for Color {}

impl Color {
/// Return the color as a linear RGBA color.
pub fn linear(&self) -> LinearRgba {
pub fn to_linear(&self) -> LinearRgba {
(*self).into()
}

/// Return the color as an SRGBA color.
pub fn to_srgba(&self) -> Srgba {
(*self).into()
}

Expand Down
12 changes: 12 additions & 0 deletions crates/bevy_color/src/color_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,18 @@ pub trait ColorToComponents {
fn from_vec3(color: Vec3) -> Self;
}

/// Trait with methods for converting colors to packed non-color types
pub trait ColorToPacked {
/// Convert to [u8; 4] where that makes sense (Srgba is most relevant)
fn to_u8_array(self) -> [u8; 4];
/// Convert to [u8; 3] where that makes sense (Srgba is most relevant)
fn to_u8_array_no_alpha(self) -> [u8; 3];
/// Convert from [u8; 4] where that makes sense (Srgba is most relevant)
fn from_u8_array(color: [u8; 4]) -> Self;
/// Convert to [u8; 3] where that makes sense (Srgba is most relevant)
fn from_u8_array_no_alpha(color: [u8; 3]) -> Self;
}

/// Utility function for interpolating hue values. This ensures that the interpolation
/// takes the shortest path around the color wheel, and that the result is always between
/// 0 and 360.
Expand Down
63 changes: 49 additions & 14 deletions crates/bevy_color/src/linear_rgba.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
color_difference::EuclideanDistance, impl_componentwise_vector_space, Alpha, ColorToComponents,
Gray, Luminance, Mix, StandardColor,
ColorToPacked, Gray, Luminance, Mix, StandardColor,
};
use bevy_math::{Vec3, Vec4};
use bevy_reflect::prelude::*;
Expand Down Expand Up @@ -149,24 +149,12 @@ impl LinearRgba {
}
}

/// Converts the color into a [f32; 4] array in RGBA order.
///
/// This is useful for passing the color to a shader.
pub fn to_f32_array(&self) -> [f32; 4] {
[self.red, self.green, self.blue, self.alpha]
}

/// Converts this color to a u32.
///
/// 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_u32(&self) -> u32 {
u32::from_le_bytes([
(self.red * 255.0) as u8,
(self.green * 255.0) as u8,
(self.blue * 255.0) as u8,
(self.alpha * 255.0) as u8,
])
u32::from_le_bytes(self.to_u8_array())
}
}

Expand Down Expand Up @@ -310,6 +298,25 @@ impl ColorToComponents for LinearRgba {
}
}

impl ColorToPacked for LinearRgba {
fn to_u8_array(self) -> [u8; 4] {
[self.red, self.green, self.blue, self.alpha]
.map(|v| (v.clamp(0.0, 1.0) * 255.0).round() as u8)
}

fn to_u8_array_no_alpha(self) -> [u8; 3] {
[self.red, self.green, self.blue].map(|v| (v.clamp(0.0, 1.0) * 255.0).round() as u8)
}

fn from_u8_array(color: [u8; 4]) -> Self {
Self::from_f32_array(color.map(|u| u as f32 / 255.0))
}

fn from_u8_array_no_alpha(color: [u8; 3]) -> Self {
Self::from_f32_array_no_alpha(color.map(|u| u as f32 / 255.0))
}
}

#[cfg(feature = "wgpu-types")]
impl From<LinearRgba> for wgpu_types::Color {
fn from(color: LinearRgba) -> Self {
Expand Down Expand Up @@ -416,6 +423,34 @@ mod tests {
assert_eq!(a.distance_squared(&b), 1.0);
}

#[test]
fn to_and_from_u8() {
// from_u8_array
let a = LinearRgba::from_u8_array([255, 0, 0, 255]);
let b = LinearRgba::new(1.0, 0.0, 0.0, 1.0);
assert_eq!(a, b);

// from_u8_array_no_alpha
let a = LinearRgba::from_u8_array_no_alpha([255, 255, 0]);
let b = LinearRgba::rgb(1.0, 1.0, 0.0);
assert_eq!(a, b);

// to_u8_array
let a = LinearRgba::new(0.0, 0.0, 1.0, 1.0).to_u8_array();
let b = [0, 0, 255, 255];
assert_eq!(a, b);

// to_u8_array_no_alpha
let a = LinearRgba::rgb(0.0, 1.0, 1.0).to_u8_array_no_alpha();
let b = [0, 255, 255];
assert_eq!(a, b);

// clamping
let a = LinearRgba::rgb(0.0, 100.0, -100.0).to_u8_array_no_alpha();
let b = [0, 255, 0];
assert_eq!(a, b);
}

#[test]
fn darker_lighter() {
// Darker and lighter should be commutative.
Expand Down
37 changes: 24 additions & 13 deletions crates/bevy_color/src/srgba.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::color_difference::EuclideanDistance;
use crate::{
impl_componentwise_vector_space, Alpha, ColorToComponents, Gray, LinearRgba, Luminance, Mix,
StandardColor, Xyza,
impl_componentwise_vector_space, Alpha, ColorToComponents, ColorToPacked, Gray, LinearRgba,
Luminance, Mix, StandardColor, Xyza,
};
use bevy_math::{Vec3, Vec4};
use bevy_reflect::prelude::*;
Expand Down Expand Up @@ -168,10 +168,7 @@ impl Srgba {

/// Convert this color to CSS-style hexadecimal notation.
pub fn to_hex(&self) -> String {
let r = (self.red * 255.0).round() as u8;
let g = (self.green * 255.0).round() as u8;
let b = (self.blue * 255.0).round() as u8;
let a = (self.alpha * 255.0).round() as u8;
let [r, g, b, a] = self.to_u8_array();
match a {
255 => format!("#{:02X}{:02X}{:02X}", r, g, b),
_ => format!("#{:02X}{:02X}{:02X}{:02X}", r, g, b, a),
Expand All @@ -189,7 +186,7 @@ impl Srgba {
/// See also [`Srgba::new`], [`Srgba::rgba_u8`], [`Srgba::hex`].
///
pub fn rgb_u8(r: u8, g: u8, b: u8) -> Self {
Self::rgba_u8(r, g, b, u8::MAX)
Self::from_u8_array_no_alpha([r, g, b])
}

// Float operations in const fn are not stable yet
Expand All @@ -206,12 +203,7 @@ impl Srgba {
/// See also [`Srgba::new`], [`Srgba::rgb_u8`], [`Srgba::hex`].
///
pub fn rgba_u8(r: u8, g: u8, b: u8, a: u8) -> Self {
Self::new(
r as f32 / u8::MAX as f32,
g as f32 / u8::MAX as f32,
b as f32 / u8::MAX as f32,
a as f32 / u8::MAX as f32,
)
Self::from_u8_array([r, g, b, a])
}

/// Converts a non-linear sRGB value to a linear one via [gamma correction](https://en.wikipedia.org/wiki/Gamma_correction).
Expand Down Expand Up @@ -373,6 +365,25 @@ impl ColorToComponents for Srgba {
}
}

impl ColorToPacked for Srgba {
fn to_u8_array(self) -> [u8; 4] {
[self.red, self.green, self.blue, self.alpha]
.map(|v| (v.clamp(0.0, 1.0) * 255.0).round() as u8)
}

fn to_u8_array_no_alpha(self) -> [u8; 3] {
[self.red, self.green, self.blue].map(|v| (v.clamp(0.0, 1.0) * 255.0).round() as u8)
}

fn from_u8_array(color: [u8; 4]) -> Self {
Self::from_f32_array(color.map(|u| u as f32 / 255.0))
}

fn from_u8_array_no_alpha(color: [u8; 3]) -> Self {
Self::from_f32_array_no_alpha(color.map(|u| u as f32 / 255.0))
}
}

impl From<LinearRgba> for Srgba {
#[inline]
fn from(value: LinearRgba) -> Self {
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_pbr/src/fog.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use bevy_color::{Color, LinearRgba};
use bevy_color::{Color, ColorToComponents, LinearRgba};
use bevy_ecs::prelude::*;
use bevy_math::Vec3;
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_pbr/src/render/light.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use bevy_asset::AssetId;
use bevy_color::ColorToComponents;
use bevy_core_pipeline::core_3d::CORE_3D_DEPTH_FORMAT;
use bevy_ecs::entity::EntityHashSet;
use bevy_ecs::prelude::*;
Expand Down
17 changes: 4 additions & 13 deletions crates/bevy_pbr/src/volumetric_fog/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

use bevy_app::{App, Plugin};
use bevy_asset::{load_internal_asset, Handle};
use bevy_color::Color;
use bevy_color::{Color, ColorToComponents};
use bevy_core_pipeline::{
core_3d::{
graph::{Core3d, Node3d},
Expand Down Expand Up @@ -617,18 +617,9 @@ pub fn prepare_volumetric_fog_uniforms(

for (entity, volumetric_fog_settings) in view_targets.iter() {
let offset = writer.write(&VolumetricFogUniform {
fog_color: Vec3::from_slice(
&volumetric_fog_settings.fog_color.linear().to_f32_array()[0..3],
),
light_tint: Vec3::from_slice(
&volumetric_fog_settings.light_tint.linear().to_f32_array()[0..3],
),
ambient_color: Vec3::from_slice(
&volumetric_fog_settings
.ambient_color
.linear()
.to_f32_array()[0..3],
),
fog_color: volumetric_fog_settings.fog_color.to_linear().to_vec3(),
light_tint: volumetric_fog_settings.light_tint.to_linear().to_vec3(),
ambient_color: volumetric_fog_settings.ambient_color.to_linear().to_vec3(),
ambient_intensity: volumetric_fog_settings.ambient_intensity,
step_count: volumetric_fog_settings.step_count,
max_depth: volumetric_fog_settings.max_depth,
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_sprite/src/mesh2d/color_material.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{Material2d, Material2dPlugin, MaterialMesh2dBundle};
use bevy_app::{App, Plugin};
use bevy_asset::{load_internal_asset, Asset, AssetApp, Assets, Handle};
use bevy_color::{Color, LinearRgba};
use bevy_color::{Color, ColorToComponents, LinearRgba};
use bevy_math::Vec4;
use bevy_reflect::prelude::*;
use bevy_render::{
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_sprite/src/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{
ComputedTextureSlices, Sprite, WithSprite, SPRITE_SHADER_HANDLE,
};
use bevy_asset::{AssetEvent, AssetId, Assets, Handle};
use bevy_color::LinearRgba;
use bevy_color::{ColorToComponents, LinearRgba};
use bevy_core_pipeline::{
core_2d::Transparent2d,
tonemapping::{
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_ui/src/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ mod pipeline;
mod render_pass;
mod ui_material_pipeline;

use bevy_color::{Alpha, LinearRgba};
use bevy_color::{Alpha, ColorToComponents, LinearRgba};
use bevy_core_pipeline::core_2d::graph::{Core2d, Node2d};
use bevy_core_pipeline::core_3d::graph::{Core3d, Node3d};
use bevy_core_pipeline::{core_2d::Camera2d, core_3d::Camera3d};
Expand Down