mirror of
https://github.com/emilk/egui.git
synced 2026-08-31 05:40:03 -04:00
Fix semi-transparent colors appearing too bright (#5824)
The bug was in `Color32::from_rgba_unmultiplied` and by extension affects: * `Color32::from_rgba_unmultiplied` * `hex_color!` * `HexColor` * `ColorImage::from_rgba_unmultiplied` * All images with transparency (png, webp, …) * `Color32::from_white_alpha` The bug caused translucent colors to appear too bright. ## More Color is hard. When I started out egui I thought "linear space is objectively better, for everything!" and then I've been slowly walking that back for various reasons: * sRGB textures not available everywhere * gamma-space is more _perceptually_ even, so it makes sense to use for anti-aliasing * other applications do everything in gamma space, so that's what people expect (this PR) Similarly, pre-multiplied alpha _makes sense_ for blending colors. It also enables additive colors, which is nice. But it does complicate things. Especially when mixed with sRGB/gamma (As @karhu [points out](https://github.com/emilk/egui/pull/5824#issuecomment-2738099254)). ## Related * Closes https://github.com/emilk/egui/issues/5751 * Closes https://github.com/emilk/egui/issues/5771 ? (probably; hard to tell without a repro) * But not https://github.com/emilk/egui/issues/5810 ## TODO * [x] I broke the RGBA u8 color picker. Fix it --------- Co-authored-by: Andreas Reich <andreas@rerun.io>
This commit is contained in:
@@ -92,8 +92,6 @@ impl ColorTest {
|
||||
|
||||
ui.label("Test that vertex color times texture color is done in gamma space:");
|
||||
ui.scope(|ui| {
|
||||
ui.spacing_mut().item_spacing.y = 0.0; // No spacing between gradients
|
||||
|
||||
let tex_color = Color32::from_rgb(64, 128, 255);
|
||||
let vertex_color = Color32::from_rgb(128, 196, 196);
|
||||
let ground_truth = mul_color_gamma(tex_color, vertex_color);
|
||||
@@ -106,6 +104,9 @@ impl ColorTest {
|
||||
show_color(ui, vertex_color, color_size);
|
||||
ui.label(" vertex color =");
|
||||
});
|
||||
|
||||
ui.spacing_mut().item_spacing.y = 0.0; // No spacing between gradients
|
||||
|
||||
{
|
||||
let g = Gradient::one_color(ground_truth);
|
||||
self.vertex_gradient(ui, "Ground truth (vertices)", WHITE, &g);
|
||||
@@ -129,6 +130,34 @@ impl ColorTest {
|
||||
|
||||
ui.separator();
|
||||
|
||||
ui.label("Test that blending is done in gamma space:");
|
||||
ui.scope(|ui| {
|
||||
let background = Color32::from_rgb(200, 60, 10);
|
||||
let foreground = Color32::from_rgba_unmultiplied(108, 65, 200, 82);
|
||||
let ground_truth = background.blend(foreground);
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
let color_size = ui.spacing().interact_size;
|
||||
ui.label("Background:");
|
||||
show_color(ui, background, color_size);
|
||||
ui.label(", foreground: ");
|
||||
show_color(ui, foreground, color_size);
|
||||
});
|
||||
ui.spacing_mut().item_spacing.y = 0.0; // No spacing between gradients
|
||||
{
|
||||
let g = Gradient::one_color(ground_truth);
|
||||
self.vertex_gradient(ui, "Ground truth (vertices)", WHITE, &g);
|
||||
self.tex_gradient(ui, "Ground truth (texture)", WHITE, &g);
|
||||
}
|
||||
{
|
||||
let g = Gradient::one_color(foreground);
|
||||
self.vertex_gradient(ui, "Vertex blending", background, &g);
|
||||
self.tex_gradient(ui, "Texture blending", background, &g);
|
||||
}
|
||||
});
|
||||
|
||||
ui.separator();
|
||||
|
||||
// TODO(emilk): test color multiplication (image tint),
|
||||
// to make sure vertex and texture color multiplication is done in linear space.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user