From 9554c78f3adc9846b76e9d3b96af06e98fb69aa0 Mon Sep 17 00:00:00 2001 From: Bingus Date: Tue, 6 Jun 2023 17:06:40 -0700 Subject: Updated color packing into u32 to consider incorrect web-colors. --- core/src/color.rs | 19 +++++++++++++++++++ graphics/src/gradient.rs | 33 ++++++++++++++++++++------------- wgpu/src/shader/quad.wgsl | 29 +++++++++++------------------ wgpu/src/shader/triangle.wgsl | 29 +++++++++++------------------ 4 files changed, 61 insertions(+), 49 deletions(-) diff --git a/core/src/color.rs b/core/src/color.rs index 9ea6ccbf..9ef66b28 100644 --- a/core/src/color.rs +++ b/core/src/color.rs @@ -132,6 +132,25 @@ impl Color { r | g | b | a } + /// Converts the [`Color`] into a `u32` value containing its linear RGBA8 components. + pub fn into_linear_u32(self) -> u32 { + let [r, g, b, a] = self.into_linear(); + + let [r, g, b, a] = [ + (r * 255.0).round() as u8, + (g * 255.0).round() as u8, + (b * 255.0).round() as u8, + (a * 255.0).round() as u8, + ]; + + let r = (r as u32) << 24; + let g = (g as u32) << 16; + let b = (b as u32) << 8; + let a = a as u32; + + r | g | b | a + } + /// Inverts the [`Color`] in-place. pub fn invert(&mut self) { self.r = 1.0f32 - self.r; diff --git a/graphics/src/gradient.rs b/graphics/src/gradient.rs index 57cc007f..97b0a6d7 100644 --- a/graphics/src/gradient.rs +++ b/graphics/src/gradient.rs @@ -103,11 +103,17 @@ impl Linear { let mut offsets = [0.0f32; 8]; for (index, stop) in self.stops.iter().enumerate() { - let (color, offset) = stop - .map_or((Color::default().into_u32(), 2.0), |s| { - (s.color.into_u32(), s.offset) - }); - colors[index] = color; + let (color, offset) = + stop.map_or((Color::default(), 2.0), |s| (s.color, s.offset)); + + if color::GAMMA_CORRECTION { + //correct colors, convert to linear before uploading to GPU + colors[index] = color.into_linear_u32(); + } else { + //web colors, don't convert to linear before uploading to GPU + colors[index] = color.into_u32(); + } + offsets[index] = offset; } @@ -139,16 +145,17 @@ pub fn pack(gradient: &core::Gradient, bounds: Rectangle) -> Packed { let mut offsets = [0.0f32; 8]; for (index, stop) in linear.stops.iter().enumerate() { - // let [r, g, b, a] = - // color::pack(stop.map_or(Color::default(), |s| s.color)) - // .components(); - let (color, offset) = stop - .map_or((Color::default().into_u32(), 2.0), |s| { - (s.color.into_u32(), s.offset) - }); + .map_or((Color::default(), 2.0), |s| (s.color, s.offset)); + + if color::GAMMA_CORRECTION { + //correct colors, convert to linear before uploading to GPU + colors[index] = color.into_linear_u32(); + } else { + //web colors, don't convert to linear before uploading to GPU + colors[index] = color.into_u32(); + } - colors[index] = color; offsets[index] = offset; } diff --git a/wgpu/src/shader/quad.wgsl b/wgpu/src/shader/quad.wgsl index fdcc6743..5a1237e6 100644 --- a/wgpu/src/shader/quad.wgsl +++ b/wgpu/src/shader/quad.wgsl @@ -38,17 +38,10 @@ fn select_border_radius(radi: vec4, position: vec2, center: vec2) return rx; } -fn l(c: f32) -> f32 { - if (c < 0.04045) { - return c / 12.92; - } else { - return pow(((c + 0.055) / 1.055), 2.4); - }; -} +fn unpack_u32(color: u32) -> vec4 { + let u = unpack4x8unorm(color); -fn to_linear(color: u32) -> vec4 { - let c = unpack4x8unorm(color); //unpacks as a b g r - return vec4(l(c.w), l(c.z), l(c.y), c.x); + return vec4(u.w, u.z, u.y, u.x); } struct SolidVertexInput { @@ -269,14 +262,14 @@ fn gradient( @fragment fn gradient_fs_main(input: GradientVertexOutput) -> @location(0) vec4 { let colors = array, 8>( - to_linear(input.colors_1.x), - to_linear(input.colors_1.y), - to_linear(input.colors_1.z), - to_linear(input.colors_1.w), - to_linear(input.colors_2.x), - to_linear(input.colors_2.y), - to_linear(input.colors_2.z), - to_linear(input.colors_2.w), + unpack_u32(input.colors_1.x), + unpack_u32(input.colors_1.y), + unpack_u32(input.colors_1.z), + unpack_u32(input.colors_1.w), + unpack_u32(input.colors_2.x), + unpack_u32(input.colors_2.y), + unpack_u32(input.colors_2.z), + unpack_u32(input.colors_2.w), ); var offsets = array( diff --git a/wgpu/src/shader/triangle.wgsl b/wgpu/src/shader/triangle.wgsl index 5a73a77f..f1bb2733 100644 --- a/wgpu/src/shader/triangle.wgsl +++ b/wgpu/src/shader/triangle.wgsl @@ -4,17 +4,10 @@ struct Globals { @group(0) @binding(0) var globals: Globals; -fn l(c: f32) -> f32 { - if (c < 0.04045) { - return c / 12.92; - } else { - return pow(((c + 0.055) / 1.055), 2.4); - }; -} +fn unpack_u32(color: u32) -> vec4 { + let u = unpack4x8unorm(color); -fn to_linear(color: u32) -> vec4 { - let c = unpack4x8unorm(color); //unpacks as a b g r - return vec4(l(c.w), l(c.z), l(c.y), c.x); + return vec4(u.w, u.z, u.y, u.x); } struct SolidVertexInput { @@ -130,14 +123,14 @@ fn gradient( @fragment fn gradient_fs_main(input: GradientVertexOutput) -> @location(0) vec4 { let colors = array, 8>( - to_linear(input.colors_1.x), - to_linear(input.colors_1.y), - to_linear(input.colors_1.z), - to_linear(input.colors_1.w), - to_linear(input.colors_2.x), - to_linear(input.colors_2.y), - to_linear(input.colors_2.z), - to_linear(input.colors_2.w), + unpack_u32(input.colors_1.x), + unpack_u32(input.colors_1.y), + unpack_u32(input.colors_1.z), + unpack_u32(input.colors_1.w), + unpack_u32(input.colors_2.x), + unpack_u32(input.colors_2.y), + unpack_u32(input.colors_2.z), + unpack_u32(input.colors_2.w), ); var offsets = array( -- cgit