From 3653f24e060425831b8addbb6b450e0fd82729e4 Mon Sep 17 00:00:00 2001 From: Shadow Cat Date: Sat, 20 Sep 2025 13:34:04 -0400 Subject: [PATCH] store color in linear --- src/layout/color.rs | 24 ++++++++++++++++++++++-- src/render/shader.wgsl | 19 +------------------ src/testing/mod.rs | 4 ++-- 3 files changed, 25 insertions(+), 22 deletions(-) diff --git a/src/layout/color.rs b/src/layout/color.rs index 8b6e629..d058f5f 100644 --- a/src/layout/color.rs +++ b/src/layout/color.rs @@ -1,5 +1,6 @@ #![allow(clippy::multiple_bound_locations)] +/// stored in linear for sane manipulation #[repr(C)] #[derive(Clone, Copy, bytemuck::Zeroable, Debug)] pub struct Color { @@ -63,6 +64,7 @@ impl ColorNum for f32 { unsafe impl bytemuck::Pod for Color {} +#[const_trait] pub trait F32Conversion { fn to(self) -> f32; fn from(x: f32) -> Self; @@ -87,9 +89,27 @@ impl Color { a: self.a, } } + + pub fn srgb(r: T, g: T, b: T) -> Self { + Self { + r: s_to_l(r), + g: s_to_l(g), + b: s_to_l(b), + a: T::MAX, + } + } } -impl F32Conversion for f32 { +fn s_to_l(x: T) -> T { + let x = x.to(); + T::from(if x <= 0.0405 { + x / 12.92 + } else { + ((x + 0.055) / 1.055).powf(2.4) + }) +} + +impl const F32Conversion for f32 { fn to(self) -> f32 { self } @@ -98,7 +118,7 @@ impl F32Conversion for f32 { } } -impl F32Conversion for u8 { +impl const F32Conversion for u8 { fn to(self) -> f32 { self as f32 / 255.0 } diff --git a/src/render/shader.wgsl b/src/render/shader.wgsl index 9a3ae21..456390b 100644 --- a/src/render/shader.wgsl +++ b/src/render/shader.wgsl @@ -106,7 +106,7 @@ fn draw_texture(region: Region, info: TextureInfo) -> vec4 { } fn draw_rounded_rect(region: Region, rect: Rect) -> vec4 { - var color = read_color(rect.color); + var color = unpack4x8unorm(rect.color); let edge = 0.5; @@ -133,20 +133,3 @@ fn distance_from_rect(pixel_pos: vec2, rect_center: vec2, rect_corner: return length(max(q, vec2(0.0))) - radius; } -fn read_color(c: u32) -> vec4 { - let color = unpack4x8unorm(c); - return vec4( - srgb_to_linear(color.r), - srgb_to_linear(color.g), - srgb_to_linear(color.b), - color.a, - ); -} - -fn srgb_to_linear(c: f32) -> f32 { - if c <= 0.04045 { - return c / 12.92; - } else { - return pow((c + 0.055) / 1.055, 2.4); - } -} diff --git a/src/testing/mod.rs b/src/testing/mod.rs index 97dd9e9..c530b2b 100644 --- a/src/testing/mod.rs +++ b/src/testing/mod.rs @@ -157,10 +157,10 @@ impl Client { let rect = rect(color) .id_on(Sense::click(), move |id, ctx: &mut Client, _| { ctx.ui[main].inner.set_static(to); - ctx.ui[id].color = color.add_rgb(-0.2); + ctx.ui[id].color = color.mul_rgb(0.7); }) .edit_on(Sense::HoverStart | Sense::unclick(), move |r, _| { - r.color = color.add_rgb(0.4); + r.color = color.add_rgb(0.2); }) .edit_on(Sense::HoverEnd, move |r, _| { r.color = color;