diff --git a/crates/ecolor/src/color32.rs b/crates/ecolor/src/color32.rs index 939626425178..09e68116f09b 100644 --- a/crates/ecolor/src/color32.rs +++ b/crates/ecolor/src/color32.rs @@ -198,4 +198,19 @@ impl Color32 { // we need a somewhat expensive conversion to linear space and back. Rgba::from(self).multiply(factor).into() } + + /// Converts to floating point values in the range 0-1 without any gamma space conversion. + /// + /// Use this with great care! In almost all cases, you want to convert to [`crate::Rgba`] instead + /// in order to obtain linear space color values. + #[inline] + pub fn to_normalized_gamma_f32(self) -> [f32; 4] { + let Self([r, g, b, a]) = self; + [ + r as f32 / 255.0, + g as f32 / 255.0, + b as f32 / 255.0, + a as f32 / 255.0, + ] + } } diff --git a/crates/eframe/CHANGELOG.md b/crates/eframe/CHANGELOG.md index 0f67c3db33e6..9dfbb6fc728b 100644 --- a/crates/eframe/CHANGELOG.md +++ b/crates/eframe/CHANGELOG.md @@ -5,6 +5,7 @@ NOTE: [`egui-winit`](../egui-winit/CHANGELOG.md), [`egui_glium`](../egui_glium/C ## Unreleased +* ⚠️ BREAKING: `App::clear_color` now expects you to return a raw float array ([#2666](https://github.com/emilk/egui/pull/2666)): #### Desktop/Native: * `eframe::run_native` now returns a `Result` ([#2433](https://github.com/emilk/egui/pull/2433)). diff --git a/crates/eframe/src/epi.rs b/crates/eframe/src/epi.rs index 5f2f903ab881..084845a0d00f 100644 --- a/crates/eframe/src/epi.rs +++ b/crates/eframe/src/epi.rs @@ -149,13 +149,21 @@ pub trait App { egui::Vec2::INFINITY } - /// Background color for the app, e.g. what is sent to `gl.clearColor`. + /// Background color values for the app, e.g. what is sent to `gl.clearColor`. + /// /// This is the background of your windows if you don't set a central panel. - fn clear_color(&self, _visuals: &egui::Visuals) -> egui::Rgba { + /// + /// ATTENTION: + /// Since these float values go to the render as-is, any color space conversion as done + /// e.g. by converting from [`egui::Color32`] to [`egui::Rgba`] may cause incorrect results. + /// egui recommends that rendering backends use a normal "gamma-space" (non-sRGB-aware) blending, + /// which means the values you return here should also be in `sRGB` gamma-space in the 0-1 range. + /// You can use [`egui::Color32::to_normalized_gamma_f32`] for this. + fn clear_color(&self, _visuals: &egui::Visuals) -> [f32; 4] { // NOTE: a bright gray makes the shadows of the windows look weird. // We use a bit of transparency so that if the user switches on the // `transparent()` option they get immediate results. - egui::Color32::from_rgba_unmultiplied(12, 12, 12, 180).into() + egui::Color32::from_rgba_unmultiplied(12, 12, 12, 180).to_normalized_gamma_f32() // _visuals.window_fill() would also be a natural choice } diff --git a/crates/eframe/src/web/web_painter.rs b/crates/eframe/src/web/web_painter.rs index 4ced22f46de3..9c7631b90eb9 100644 --- a/crates/eframe/src/web/web_painter.rs +++ b/crates/eframe/src/web/web_painter.rs @@ -1,4 +1,3 @@ -use egui::Rgba; use wasm_bindgen::JsValue; /// Renderer for a browser canvas. @@ -19,7 +18,7 @@ pub(crate) trait WebPainter { /// Update all internal textures and paint gui. fn paint_and_update_textures( &mut self, - clear_color: Rgba, + clear_color: [f32; 4], clipped_primitives: &[egui::ClippedPrimitive], pixels_per_point: f32, textures_delta: &egui::TexturesDelta, diff --git a/crates/eframe/src/web/web_painter_glow.rs b/crates/eframe/src/web/web_painter_glow.rs index 36f42692637b..0fe7e12743db 100644 --- a/crates/eframe/src/web/web_painter_glow.rs +++ b/crates/eframe/src/web/web_painter_glow.rs @@ -2,7 +2,6 @@ use wasm_bindgen::JsCast; use wasm_bindgen::JsValue; use web_sys::HtmlCanvasElement; -use egui::Rgba; use egui_glow::glow; use crate::{WebGlContextOption, WebOptions}; @@ -49,7 +48,7 @@ impl WebPainter for WebPainterGlow { fn paint_and_update_textures( &mut self, - clear_color: Rgba, + clear_color: [f32; 4], clipped_primitives: &[egui::ClippedPrimitive], pixels_per_point: f32, textures_delta: &egui::TexturesDelta, diff --git a/crates/eframe/src/web/web_painter_wgpu.rs b/crates/eframe/src/web/web_painter_wgpu.rs index d6445f0ef86c..ab55373f33e5 100644 --- a/crates/eframe/src/web/web_painter_wgpu.rs +++ b/crates/eframe/src/web/web_painter_wgpu.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use wasm_bindgen::JsValue; use web_sys::HtmlCanvasElement; -use egui::{mutex::RwLock, Rgba}; +use egui::mutex::RwLock; use egui_wgpu::{renderer::ScreenDescriptor, RenderState, SurfaceErrorAction}; use crate::WebOptions; @@ -135,7 +135,7 @@ impl WebPainter for WebPainterWgpu { fn paint_and_update_textures( &mut self, - clear_color: Rgba, + clear_color: [f32; 4], clipped_primitives: &[egui::ClippedPrimitive], pixels_per_point: f32, textures_delta: &egui::TexturesDelta, @@ -228,10 +228,10 @@ impl WebPainter for WebPainterWgpu { resolve_target: None, ops: wgpu::Operations { load: wgpu::LoadOp::Clear(wgpu::Color { - r: clear_color.r() as f64, - g: clear_color.g() as f64, - b: clear_color.b() as f64, - a: clear_color.a() as f64, + r: clear_color[0] as f64, + g: clear_color[1] as f64, + b: clear_color[2] as f64, + a: clear_color[3] as f64, }), store: true, }, diff --git a/crates/egui-wgpu/src/winit.rs b/crates/egui-wgpu/src/winit.rs index 5159304047ce..d10f119457fe 100644 --- a/crates/egui-wgpu/src/winit.rs +++ b/crates/egui-wgpu/src/winit.rs @@ -255,7 +255,7 @@ impl Painter { pub fn paint_and_update_textures( &mut self, pixels_per_point: f32, - clear_color: epaint::Rgba, + clear_color: [f32; 4], clipped_primitives: &[epaint::ClippedPrimitive], textures_delta: &epaint::textures::TexturesDelta, ) { @@ -335,10 +335,10 @@ impl Painter { resolve_target: None, ops: wgpu::Operations { load: wgpu::LoadOp::Clear(wgpu::Color { - r: clear_color.r() as f64, - g: clear_color.g() as f64, - b: clear_color.b() as f64, - a: clear_color.a() as f64, + r: clear_color[0] as f64, + g: clear_color[1] as f64, + b: clear_color[2] as f64, + a: clear_color[3] as f64, }), store: true, }, diff --git a/crates/egui_demo_app/src/wrap_app.rs b/crates/egui_demo_app/src/wrap_app.rs index 2bbf31ebde5e..3f2f5a0a2f50 100644 --- a/crates/egui_demo_app/src/wrap_app.rs +++ b/crates/egui_demo_app/src/wrap_app.rs @@ -175,8 +175,8 @@ impl eframe::App for WrapApp { eframe::set_value(storage, eframe::APP_KEY, &self.state); } - fn clear_color(&self, visuals: &egui::Visuals) -> egui::Rgba { - visuals.panel_fill.into() + fn clear_color(&self, visuals: &egui::Visuals) -> [f32; 4] { + visuals.panel_fill.to_normalized_gamma_f32() } fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) { diff --git a/crates/egui_glow/src/painter.rs b/crates/egui_glow/src/painter.rs index 27f5571c86ea..574ff1e7726d 100644 --- a/crates/egui_glow/src/painter.rs +++ b/crates/egui_glow/src/painter.rs @@ -5,7 +5,7 @@ use std::{collections::HashMap, sync::Arc}; use egui::{ emath::Rect, - epaint::{Color32, Mesh, PaintCallbackInfo, Primitive, Vertex}, + epaint::{Mesh, PaintCallbackInfo, Primitive, Vertex}, }; use glow::HasContext as _; use memoffset::offset_of; @@ -665,7 +665,7 @@ impl Painter { } } -pub fn clear(gl: &glow::Context, screen_size_in_pixels: [u32; 2], clear_color: egui::Rgba) { +pub fn clear(gl: &glow::Context, screen_size_in_pixels: [u32; 2], clear_color: [f32; 4]) { crate::profile_function!(); unsafe { gl.disable(glow::SCISSOR_TEST); @@ -676,24 +676,12 @@ pub fn clear(gl: &glow::Context, screen_size_in_pixels: [u32; 2], clear_color: e screen_size_in_pixels[0] as i32, screen_size_in_pixels[1] as i32, ); - - if true { - // verified to be correct on eframe native (on Mac). - gl.clear_color( - clear_color[0], - clear_color[1], - clear_color[2], - clear_color[3], - ); - } else { - let clear_color: Color32 = clear_color.into(); - gl.clear_color( - clear_color[0] as f32 / 255.0, - clear_color[1] as f32 / 255.0, - clear_color[2] as f32 / 255.0, - clear_color[3] as f32 / 255.0, - ); - } + gl.clear_color( + clear_color[0], + clear_color[1], + clear_color[2], + clear_color[3], + ); gl.clear(glow::COLOR_BUFFER_BIT); } } diff --git a/examples/custom_window_frame/src/main.rs b/examples/custom_window_frame/src/main.rs index d6a35416bdd8..284451db7ea7 100644 --- a/examples/custom_window_frame/src/main.rs +++ b/examples/custom_window_frame/src/main.rs @@ -25,8 +25,8 @@ fn main() -> Result<(), eframe::Error> { struct MyApp {} impl eframe::App for MyApp { - fn clear_color(&self, _visuals: &egui::Visuals) -> egui::Rgba { - egui::Rgba::TRANSPARENT // Make sure we don't paint anything behind the rounded corners + fn clear_color(&self, _visuals: &egui::Visuals) -> [f32; 4] { + egui::Rgba::TRANSPARENT.to_array() // Make sure we don't paint anything behind the rounded corners } fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {