-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
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
Convert colors from srgb to linear srgb automatically #585
Comments
Here's some helper workaround functions I made for my little project to make things more ergonomic: use bevy::prelude::Color;
use palette::Srgb;
/// Take a color in non-linear srgb and convert it to the linear srgb format Bevy currently needs
pub fn color_from_f32(r: f32, g: f32, b: f32) -> Color {
let l = Srgb::new(r, g, b).into_linear();
Color::rgb(l.red, l.green, l.blue)
}
/// Take a color in non-linear srgb and convert it to the linear srgb format Bevy currently needs
pub fn color_from_u8(r: u8, g: u8, b: u8) -> Color {
color_from_f32(r as f32 / 255.0, g as f32 / 255.0, b as f32 / 255.0)
} |
I would say we make the default I'm not sure on adding a |
The formulas for linear to sRGB and vice-versa aren't much code. A full dependency on Here's an (untested) transcription of the formulas from the Wikipedia article about sRGB: fn linear_to_srgb(u: f32) -> f32 {
if u <= 0.0031308 {
12.92 * u
} else {
1.055 * f32::powf(u,0.416666) - 0.055
}
}
fn srgb_to_linear(u: f32) -> f32 {
if u <= 0.04045 {
u / 12.92
} else {
f32::powf((u + 0.055) / 1.055, 2.4)
}
} |
I agree that the needed formula is simple enough to not warrant a dependency on an external crate. Here follows an example solution with a macro (using the same formula from wikipedia). I like this solution because the needed code change is very clear and minimal. use bevy::prelude::*;
use bevy::render::pass::ClearColor;
macro_rules! color_rgb {
( $( $x:expr ),* ) => {
Color::rgb( $(
// Without converting srgb to linear
//$x
// With converting srgb to linear
if $x <= 0.04045 {
$x / 12.92
} else {
((($x as f32) + 0.055) / 1.055).powf(2.4)
}
),* )
};
}
fn main() {
App::build()
.add_default_plugins()
//.add_resource(ClearColor(Color::rgb(0.83, 0.474, 0.206)))
.add_resource(ClearColor(color_rgb!(0.83, 0.474, 0.206)))
.run();
} |
Oh good, to be clear I didn't want an additional dependency -- but I also didn't want to figure out the math myself when I was tired. 😄 I'm glad the math ended up being so simple. |
I found one possible problem with my solution above. Using GIMP colorpicker on the resulting color gives me the equivalent of Maybe this is a precision/rounding problem? Or maybe hardware specific? For reference I'm using an Nvidia graphics card in Linux. |
I think we can close this out now that #616 landed |
|
As per this Discord conversation and #419 (comment), assume people are providing raw color values in the non-linear srgb colorspace. Bevy should then convert the provided colors to linear srgb for internal use, for example in the constructors in
bevy_render/src/color.rs
), and automatically convert the colors to linear srgb when it makes sense under the hood.We could have constructors for both non-linear and linear sources as long as we document them wherever there could be ambiguity.
Workaround
Right now this can be worked around by manually converting the colors to linear srgb colorspace before using them with the engine like this:
The text was updated successfully, but these errors were encountered: