From 6cc354fdc4eec6576e0591cd3a2ce37155cbfa09 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sun, 3 Sep 2023 00:21:04 +0200 Subject: Update `wgpu` to `0.17` --- wgpu/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'wgpu') diff --git a/wgpu/Cargo.toml b/wgpu/Cargo.toml index 69568099..2fade559 100644 --- a/wgpu/Cargo.toml +++ b/wgpu/Cargo.toml @@ -14,8 +14,8 @@ svg = ["resvg"] web-colors = ["iced_graphics/web-colors"] [dependencies] -wgpu = "0.16" -glyphon = "0.3" +wgpu = "0.17" +glyphon = { git = "https://github.com/grovesNL/glyphon.git", rev = "20f0f8fa80e0d0df4c63634ce9176fa489546ca9" } raw-window-handle = "0.5" guillotiere = "0.6" futures = "0.3" -- cgit From d518e7d423f7069ed72d84e39a08e69ac07680fa Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sun, 3 Sep 2023 00:28:05 +0200 Subject: Update `wgpu` for Wasm --- wgpu/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'wgpu') diff --git a/wgpu/Cargo.toml b/wgpu/Cargo.toml index 2fade559..b0f70220 100644 --- a/wgpu/Cargo.toml +++ b/wgpu/Cargo.toml @@ -25,7 +25,7 @@ rustc-hash = "1.1" log = "0.4" [target.'cfg(target_arch = "wasm32")'.dependencies] -wgpu = { version = "0.16", features = ["webgl"] } +wgpu = { version = "0.17", features = ["webgl"] } [dependencies.twox-hash] version = "1.6" -- cgit From 020fb3c37794fcfa2670c3c0ada949aee95855a0 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sun, 3 Sep 2023 01:01:33 +0200 Subject: Fix `iced_wgpu` device selection on Wasm --- wgpu/src/window/compositor.rs | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) (limited to 'wgpu') diff --git a/wgpu/src/window/compositor.rs b/wgpu/src/window/compositor.rs index cd5b20cc..5202c7ef 100644 --- a/wgpu/src/window/compositor.rs +++ b/wgpu/src/window/compositor.rs @@ -6,8 +6,6 @@ use crate::graphics::compositor; use crate::graphics::{Error, Viewport}; use crate::{Backend, Primitive, Renderer, Settings}; -use futures::stream::{self, StreamExt}; - use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; use std::marker::PhantomData; @@ -95,14 +93,17 @@ impl Compositor { let limits = [wgpu::Limits::default(), wgpu::Limits::downlevel_defaults()]; - let limits = limits.into_iter().map(|limits| wgpu::Limits { - max_bind_groups: 2, - ..limits - }); + let mut limits = limits + .into_iter() + .map(|limits| wgpu::Limits { + max_bind_groups: 2, + ..limits + }) + .into_iter(); - let (device, queue) = stream::iter(limits) - .filter_map(|limits| async { - adapter.request_device( + let (device, queue) = loop { + if let Some(limits) = limits.next() { + let device = adapter.request_device( &wgpu::DeviceDescriptor { label: Some( "iced_wgpu::window::compositor device descriptor", @@ -111,11 +112,15 @@ impl Compositor { limits, }, None, - ).await.ok() - }) - .boxed() - .next() - .await?; + ).await.ok(); + + if let Some(device) = device { + break Some(device); + } + } + + break None; + }?; Some(Compositor { instance, -- cgit From 0b28080d3ebda4dda24c9ac9c38e3195d3499be7 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sun, 3 Sep 2023 01:05:17 +0200 Subject: Remove redundant `into_iter` call in `iced_wgpu` --- wgpu/src/window/compositor.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'wgpu') diff --git a/wgpu/src/window/compositor.rs b/wgpu/src/window/compositor.rs index 5202c7ef..cacfeef2 100644 --- a/wgpu/src/window/compositor.rs +++ b/wgpu/src/window/compositor.rs @@ -93,13 +93,10 @@ impl Compositor { let limits = [wgpu::Limits::default(), wgpu::Limits::downlevel_defaults()]; - let mut limits = limits - .into_iter() - .map(|limits| wgpu::Limits { - max_bind_groups: 2, - ..limits - }) - .into_iter(); + let mut limits = limits.into_iter().map(|limits| wgpu::Limits { + max_bind_groups: 2, + ..limits + }); let (device, queue) = loop { if let Some(limits) = limits.next() { -- cgit From 9b9b37e6f83b5e5a8811feb17b484c6b11fa3b8b Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sun, 3 Sep 2023 01:14:22 +0200 Subject: Fix adapter selection loop in `iced_wgpu` --- wgpu/src/window/compositor.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'wgpu') diff --git a/wgpu/src/window/compositor.rs b/wgpu/src/window/compositor.rs index cacfeef2..9e9c63db 100644 --- a/wgpu/src/window/compositor.rs +++ b/wgpu/src/window/compositor.rs @@ -98,8 +98,9 @@ impl Compositor { ..limits }); - let (device, queue) = loop { - if let Some(limits) = limits.next() { + let (device, queue) = + loop { + let limits = limits.next()?; let device = adapter.request_device( &wgpu::DeviceDescriptor { label: Some( @@ -114,10 +115,7 @@ impl Compositor { if let Some(device) = device { break Some(device); } - } - - break None; - }?; + }?; Some(Compositor { instance, -- cgit From 76cec1b1fd533dda37aa53c40ef7665ed3b406b6 Mon Sep 17 00:00:00 2001 From: David Huculak Date: Sun, 3 Sep 2023 19:32:38 -0400 Subject: use @interpolate(flat) attribute as per the WebGPU spec: User-defined vertex outputs and fragment inputs of scalar or vector integer type must always be specified as @interpolate(flat) https://www.w3.org/TR/WGSL/#interpolation --- wgpu/src/shader/quad.wgsl | 22 +++++++++++----------- wgpu/src/shader/triangle.wgsl | 20 ++++++++++---------- 2 files changed, 21 insertions(+), 21 deletions(-) (limited to 'wgpu') diff --git a/wgpu/src/shader/quad.wgsl b/wgpu/src/shader/quad.wgsl index fb402158..87055339 100644 --- a/wgpu/src/shader/quad.wgsl +++ b/wgpu/src/shader/quad.wgsl @@ -147,12 +147,12 @@ fn solid_fs_main( struct GradientVertexInput { @location(0) v_pos: vec2, - @location(1) colors_1: vec4, - @location(2) colors_2: vec4, - @location(3) colors_3: vec4, - @location(4) colors_4: vec4, - @location(5) offsets: vec4, - @location(6) direction: vec4, + @location(1) @interpolate(flat) colors_1: vec4, + @location(2) @interpolate(flat) colors_2: vec4, + @location(3) @interpolate(flat) colors_3: vec4, + @location(4) @interpolate(flat) colors_4: vec4, + @location(5) @interpolate(flat) offsets: vec4, + @location(6) @interpolate(flat) direction: vec4, @location(7) position_and_scale: vec4, @location(8) border_color: vec4, @location(9) border_radius: vec4, @@ -161,11 +161,11 @@ struct GradientVertexInput { struct GradientVertexOutput { @builtin(position) position: vec4, - @location(1) colors_1: vec4, - @location(2) colors_2: vec4, - @location(3) colors_3: vec4, - @location(4) colors_4: vec4, - @location(5) offsets: vec4, + @location(1) @interpolate(flat) colors_1: vec4, + @location(2) @interpolate(flat) colors_2: vec4, + @location(3) @interpolate(flat) colors_3: vec4, + @location(4) @interpolate(flat) colors_4: vec4, + @location(5) @interpolate(flat) offsets: vec4, @location(6) direction: vec4, @location(7) position_and_scale: vec4, @location(8) border_color: vec4, diff --git a/wgpu/src/shader/triangle.wgsl b/wgpu/src/shader/triangle.wgsl index 9f512d14..3a2b9845 100644 --- a/wgpu/src/shader/triangle.wgsl +++ b/wgpu/src/shader/triangle.wgsl @@ -38,22 +38,22 @@ fn solid_fs_main(input: SolidVertexOutput) -> @location(0) vec4 { struct GradientVertexInput { @location(0) v_pos: vec2, - @location(1) colors_1: vec4, - @location(2) colors_2: vec4, - @location(3) colors_3: vec4, - @location(4) colors_4: vec4, - @location(5) offsets: vec4, + @location(1) @interpolate(flat) colors_1: vec4, + @location(2) @interpolate(flat) colors_2: vec4, + @location(3) @interpolate(flat) colors_3: vec4, + @location(4) @interpolate(flat) colors_4: vec4, + @location(5) @interpolate(flat) offsets: vec4, @location(6) direction: vec4, } struct GradientVertexOutput { @builtin(position) position: vec4, @location(0) raw_position: vec2, - @location(1) colors_1: vec4, - @location(2) colors_2: vec4, - @location(3) colors_3: vec4, - @location(4) colors_4: vec4, - @location(5) offsets: vec4, + @location(1) @interpolate(flat) colors_1: vec4, + @location(2) @interpolate(flat) colors_2: vec4, + @location(3) @interpolate(flat) colors_3: vec4, + @location(4) @interpolate(flat) colors_4: vec4, + @location(5) @interpolate(flat) offsets: vec4, @location(6) direction: vec4, } -- cgit From bb49a22996f39e32c3ced0c2d80c2137aed7a0ea Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 4 Sep 2023 03:28:45 +0200 Subject: Enable WebGPU backend in `wgpu` by default instead of WebGL Instead, we expose a new `webgl` feature. --- wgpu/Cargo.toml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'wgpu') diff --git a/wgpu/Cargo.toml b/wgpu/Cargo.toml index b0f70220..49c62673 100644 --- a/wgpu/Cargo.toml +++ b/wgpu/Cargo.toml @@ -12,6 +12,7 @@ geometry = ["iced_graphics/geometry", "lyon"] image = ["iced_graphics/image"] svg = ["resvg"] web-colors = ["iced_graphics/web-colors"] +webgl = ["wgpu/webgl"] [dependencies] wgpu = "0.17" @@ -24,9 +25,6 @@ once_cell = "1.0" rustc-hash = "1.1" log = "0.4" -[target.'cfg(target_arch = "wasm32")'.dependencies] -wgpu = { version = "0.17", features = ["webgl"] } - [dependencies.twox-hash] version = "1.6" default-features = false -- cgit From ef429fbea6e39efcfdc58fdd8a2fe365fd5314d9 Mon Sep 17 00:00:00 2001 From: Josh Megnauth Date: Mon, 4 Sep 2023 02:58:54 -0400 Subject: Ensure LineHeight > 0.0 for the WGPU renderer --- wgpu/src/text.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'wgpu') diff --git a/wgpu/src/text.rs b/wgpu/src/text.rs index fb13545d..08a32b5e 100644 --- a/wgpu/src/text.rs +++ b/wgpu/src/text.rs @@ -96,7 +96,8 @@ impl Pipeline { section .line_height .to_absolute(Pixels(section.size)), - ), + ) + .max(f32::MIN_POSITIVE), font: section.font, bounds: Size { width: section.bounds.width, @@ -238,7 +239,8 @@ impl Pipeline { ) -> Size { let mut cache = self.cache.borrow_mut(); - let line_height = f32::from(line_height.to_absolute(Pixels(size))); + let line_height = f32::from(line_height.to_absolute(Pixels(size))) + .max(f32::MIN_POSITIVE); let (_, entry) = cache.allocate( &mut self.font_system.borrow_mut(), @@ -269,7 +271,8 @@ impl Pipeline { ) -> Option { let mut cache = self.cache.borrow_mut(); - let line_height = f32::from(line_height.to_absolute(Pixels(size))); + let line_height = f32::from(line_height.to_absolute(Pixels(size))) + .max(f32::MIN_POSITIVE); let (_, entry) = cache.allocate( &mut self.font_system.borrow_mut(), -- cgit From f468e25d0c67a01ee79d892f6e8ba9be019f06c7 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 4 Sep 2023 12:58:41 +0200 Subject: Use workspace dependencies and package inheritance We are also taking this as a chance to synchronize the versions of all the crates! Because of this, we will skip the `0.11` version. --- wgpu/Cargo.toml | 90 +++++++++++++++++++++++++-------------------------------- 1 file changed, 40 insertions(+), 50 deletions(-) (limited to 'wgpu') diff --git a/wgpu/Cargo.toml b/wgpu/Cargo.toml index 49c62673..97594f1a 100644 --- a/wgpu/Cargo.toml +++ b/wgpu/Cargo.toml @@ -1,11 +1,18 @@ [package] name = "iced_wgpu" -version = "0.11.1" -authors = ["Héctor Ramón Jiménez "] -edition = "2021" -description = "A wgpu renderer for Iced" -license = "MIT AND OFL-1.1" -repository = "https://github.com/iced-rs/iced" +description = "A renderer for iced on top of wgpu" +version.workspace = true +edition.workspace = true +authors.workspace = true +license.workspace = true +repository.workspace = true +homepage.workspace = true +categories.workspace = true +keywords.workspace = true + +[package.metadata.docs.rs] +rustdoc-args = ["--cfg", "docsrs"] +all-features = true [features] geometry = ["iced_graphics/geometry", "lyon"] @@ -15,47 +22,30 @@ web-colors = ["iced_graphics/web-colors"] webgl = ["wgpu/webgl"] [dependencies] -wgpu = "0.17" -glyphon = { git = "https://github.com/grovesNL/glyphon.git", rev = "20f0f8fa80e0d0df4c63634ce9176fa489546ca9" } -raw-window-handle = "0.5" -guillotiere = "0.6" -futures = "0.3" -bitflags = "1.2" -once_cell = "1.0" -rustc-hash = "1.1" -log = "0.4" - -[dependencies.twox-hash] -version = "1.6" -default-features = false - -[target.'cfg(not(target_arch = "wasm32"))'.dependencies.twox-hash] -version = "1.6.1" -features = ["std"] - -[dependencies.bytemuck] -version = "1.9" -features = ["derive"] - -[dependencies.iced_graphics] -version = "0.9" -path = "../graphics" - -[dependencies.glam] -version = "0.24" - -[dependencies.lyon] -version = "1.0" -optional = true - -[dependencies.resvg] -version = "0.35" -optional = true - -[dependencies.tracing] -version = "0.1.6" -optional = true - -[package.metadata.docs.rs] -rustdoc-args = ["--cfg", "docsrs"] -all-features = true +iced_graphics.workspace = true + +bitflags.workspace = true +bytemuck.workspace = true +futures.workspace = true +glam.workspace = true +glyphon.workspace = true +guillotiere.workspace = true +log.workspace = true +once_cell.workspace = true +raw-window-handle.workspace = true +rustc-hash.workspace = true +twox-hash.workspace = true +wgpu.workspace = true + +lyon.workspace = true +lyon.optional = true + +resvg.workspace = true +resvg.optional = true + +tracing.workspace = true +tracing.optional = true + +[target.'cfg(not(target_arch = "wasm32"))'.dependencies] +twox-hash.workspace = true +twox-hash.features = ["std"] -- cgit From bdf18554feadb631fdae5b427ac7a92a5546ade1 Mon Sep 17 00:00:00 2001 From: Josh Megnauth Date: Mon, 4 Sep 2023 23:47:44 -0400 Subject: Check LineHeight > 0.0 before allocating text --- wgpu/src/text.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'wgpu') diff --git a/wgpu/src/text.rs b/wgpu/src/text.rs index 08a32b5e..9c42be0e 100644 --- a/wgpu/src/text.rs +++ b/wgpu/src/text.rs @@ -96,8 +96,7 @@ impl Pipeline { section .line_height .to_absolute(Pixels(section.size)), - ) - .max(f32::MIN_POSITIVE), + ), font: section.font, bounds: Size { width: section.bounds.width, @@ -239,8 +238,7 @@ impl Pipeline { ) -> Size { let mut cache = self.cache.borrow_mut(); - let line_height = f32::from(line_height.to_absolute(Pixels(size))) - .max(f32::MIN_POSITIVE); + let line_height = f32::from(line_height.to_absolute(Pixels(size))); let (_, entry) = cache.allocate( &mut self.font_system.borrow_mut(), @@ -271,8 +269,7 @@ impl Pipeline { ) -> Option { let mut cache = self.cache.borrow_mut(); - let line_height = f32::from(line_height.to_absolute(Pixels(size))) - .max(f32::MIN_POSITIVE); + let line_height = f32::from(line_height.to_absolute(Pixels(size))); let (_, entry) = cache.allocate( &mut self.font_system.borrow_mut(), @@ -417,7 +414,10 @@ impl Cache { } if let hash_map::Entry::Vacant(entry) = self.entries.entry(hash) { - let metrics = glyphon::Metrics::new(key.size, key.line_height); + let metrics = glyphon::Metrics::new( + key.size, + key.line_height.max(f32::MIN_POSITIVE), + ); let mut buffer = glyphon::Buffer::new(font_system, metrics); buffer.set_size( -- cgit From 5371fae21a4c1110a37e7183e794cba234598d9c Mon Sep 17 00:00:00 2001 From: ripytide Date: Tue, 5 Sep 2023 10:49:50 +0100 Subject: added a Frame::scale_nonuniform method --- wgpu/src/geometry.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'wgpu') diff --git a/wgpu/src/geometry.rs b/wgpu/src/geometry.rs index e421e0b0..2cd07a27 100644 --- a/wgpu/src/geometry.rs +++ b/wgpu/src/geometry.rs @@ -444,7 +444,7 @@ impl Frame { self.transforms.current.is_identity = false; } - /// Applies a scaling to the current transform of the [`Frame`]. + /// Applies a uniform scaling to the current transform of the [`Frame`]. #[inline] pub fn scale(&mut self, scale: f32) { self.transforms.current.raw = @@ -452,6 +452,14 @@ impl Frame { self.transforms.current.is_identity = false; } + /// Applies a non-uniform scaling to the current transform of the [`Frame`]. + #[inline] + pub fn scale_nonuniform(&mut self, scale: Vector) { + self.transforms.current.raw = + self.transforms.current.raw.pre_scale(scale.x, scale.y); + self.transforms.current.is_identity = false; + } + /// Produces the [`Primitive`] representing everything drawn on the [`Frame`]. pub fn into_primitive(self) -> Primitive { Primitive::Group { -- cgit From 87800095e27353557adb39ef42ee6f82a0075bc1 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 7 Sep 2023 05:43:03 +0200 Subject: Remove unnecessary `interpolate(flat)` in `quad.wgsl` --- wgpu/src/shader/quad.wgsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'wgpu') diff --git a/wgpu/src/shader/quad.wgsl b/wgpu/src/shader/quad.wgsl index 87055339..023b5a6d 100644 --- a/wgpu/src/shader/quad.wgsl +++ b/wgpu/src/shader/quad.wgsl @@ -152,7 +152,7 @@ struct GradientVertexInput { @location(3) @interpolate(flat) colors_3: vec4, @location(4) @interpolate(flat) colors_4: vec4, @location(5) @interpolate(flat) offsets: vec4, - @location(6) @interpolate(flat) direction: vec4, + @location(6) direction: vec4, @location(7) position_and_scale: vec4, @location(8) border_color: vec4, @location(9) border_radius: vec4, -- cgit From 1f263051b6c2d2f2a02633d8a6277c772ae8e7f9 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 7 Sep 2023 05:45:51 +0200 Subject: Implement `scale` in terms of `scale_nonuniform` --- wgpu/src/geometry.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'wgpu') diff --git a/wgpu/src/geometry.rs b/wgpu/src/geometry.rs index 2cd07a27..64b98469 100644 --- a/wgpu/src/geometry.rs +++ b/wgpu/src/geometry.rs @@ -447,9 +447,7 @@ impl Frame { /// Applies a uniform scaling to the current transform of the [`Frame`]. #[inline] pub fn scale(&mut self, scale: f32) { - self.transforms.current.raw = - self.transforms.current.raw.pre_scale(scale, scale); - self.transforms.current.is_identity = false; + self.scale_nonuniform(Vector { x: scale, y: scale }); } /// Applies a non-uniform scaling to the current transform of the [`Frame`]. -- cgit From 09965b686ea6bf82e6c13ed5331bbeb059848e4f Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 7 Sep 2023 05:51:39 +0200 Subject: Make `scale` methods in `Frame` generic over `f32` and `Vector` --- wgpu/src/geometry.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'wgpu') diff --git a/wgpu/src/geometry.rs b/wgpu/src/geometry.rs index 64b98469..c3e16f8c 100644 --- a/wgpu/src/geometry.rs +++ b/wgpu/src/geometry.rs @@ -446,13 +446,17 @@ impl Frame { /// Applies a uniform scaling to the current transform of the [`Frame`]. #[inline] - pub fn scale(&mut self, scale: f32) { + pub fn scale(&mut self, scale: impl Into) { + let scale = scale.into(); + self.scale_nonuniform(Vector { x: scale, y: scale }); } /// Applies a non-uniform scaling to the current transform of the [`Frame`]. #[inline] - pub fn scale_nonuniform(&mut self, scale: Vector) { + pub fn scale_nonuniform(&mut self, scale: impl Into) { + let scale = scale.into(); + self.transforms.current.raw = self.transforms.current.raw.pre_scale(scale.x, scale.y); self.transforms.current.is_identity = false; -- cgit From 181708a1c0f4920f7491df4516b0de3f61993391 Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Mon, 28 Aug 2023 22:56:47 +0200 Subject: Compute gradients in Oklab color space --- wgpu/src/shader/quad.wgsl | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) (limited to 'wgpu') diff --git a/wgpu/src/shader/quad.wgsl b/wgpu/src/shader/quad.wgsl index 023b5a6d..cba7e5a4 100644 --- a/wgpu/src/shader/quad.wgsl +++ b/wgpu/src/shader/quad.wgsl @@ -230,6 +230,18 @@ fn gradient( let unit = normalize(v1); let coord_offset = dot(unit, v2) / length(v1); + let to_lms: mat3x4 = mat3x4( + vec4(0.4121656120, 0.2118591070, 0.0883097947, 0.0), + vec4(0.5362752080, 0.6807189584, 0.2818474174, 0.0), + vec4(0.0514575653, 0.1074065790, 0.6302613616, 0.0), + ); + + let to_rgb: mat3x4 = mat3x4( + vec4( 4.0767245293, -3.3072168827, 0.2307590544, 0.0), + vec4(-1.2681437731, 2.6093323231, -0.3411344290, 0.0), + vec4(-0.0041119885, -0.7034763098, 1.7068625689, 0.0), + ); + //need to store these as a var to use dynamic indexing in a loop //this is already added to wgsl spec but not in wgpu yet var colors_arr = colors; @@ -248,11 +260,15 @@ fn gradient( } if (curr_offset <= coord_offset && coord_offset <= next_offset) { - color = mix(colors_arr[i], colors_arr[i+1], smoothstep( - curr_offset, - next_offset, - coord_offset, - )); + // blend in OKLab + let factor = smoothstep(curr_offset, next_offset, coord_offset); + let lms_a = pow(colors_arr[i] * to_lms, vec3(1.0 / 3.0, 1.0 / 3.0, 1.0 / 3.0)); + let lms_b = pow(colors_arr[i+1] * to_lms, vec3(1.0 / 3.0, 1.0 / 3.0, 1.0 / 3.0)); + let mixed = mix(lms_a, lms_b, factor); + + // back to sRGB + color = to_rgb * (mixed * mixed * mixed); + color.a = mix(colors_arr[i].a, colors_arr[i+1].a, factor); } if (coord_offset >= offsets_arr[last_index]) { -- cgit From 10d0b257f929296b1991a440f62c87487c0076dc Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 7 Sep 2023 07:24:32 +0200 Subject: Use Oklab color interpolation only with `color::GAMMA_CORRECTION` --- wgpu/src/quad/gradient.rs | 19 +- wgpu/src/quad/solid.rs | 6 +- wgpu/src/shader/color/linear_rgb.wgsl | 3 + wgpu/src/shader/color/oklab.wgsl | 26 +++ wgpu/src/shader/quad.wgsl | 322 --------------------------------- wgpu/src/shader/quad/gradient.wgsl | 205 +++++++++++++++++++++ wgpu/src/shader/quad/solid.wgsl | 99 ++++++++++ wgpu/src/shader/triangle.wgsl | 160 ---------------- wgpu/src/shader/triangle/gradient.wgsl | 134 ++++++++++++++ wgpu/src/shader/triangle/solid.wgsl | 24 +++ wgpu/src/triangle.rs | 35 +++- 11 files changed, 544 insertions(+), 489 deletions(-) create mode 100644 wgpu/src/shader/color/linear_rgb.wgsl create mode 100644 wgpu/src/shader/color/oklab.wgsl create mode 100644 wgpu/src/shader/quad/gradient.wgsl create mode 100644 wgpu/src/shader/quad/solid.wgsl create mode 100644 wgpu/src/shader/triangle/gradient.wgsl create mode 100644 wgpu/src/shader/triangle/solid.wgsl (limited to 'wgpu') diff --git a/wgpu/src/quad/gradient.rs b/wgpu/src/quad/gradient.rs index 6db37252..a8e83d01 100644 --- a/wgpu/src/quad/gradient.rs +++ b/wgpu/src/quad/gradient.rs @@ -1,3 +1,4 @@ +use crate::graphics::color; use crate::graphics::gradient; use crate::quad::{self, Quad}; use crate::Buffer; @@ -78,7 +79,23 @@ impl Pipeline { device.create_shader_module(wgpu::ShaderModuleDescriptor { label: Some("iced_wgpu.quad.gradient.shader"), source: wgpu::ShaderSource::Wgsl(std::borrow::Cow::Borrowed( - include_str!("../shader/quad.wgsl"), + if color::GAMMA_CORRECTION { + concat!( + include_str!("../shader/quad.wgsl"), + "\n", + include_str!("../shader/quad/gradient.wgsl"), + "\n", + include_str!("../shader/color/oklab.wgsl") + ) + } else { + concat!( + include_str!("../shader/quad.wgsl"), + "\n", + include_str!("../shader/quad/gradient.wgsl"), + "\n", + include_str!("../shader/color/linear_rgb.wgsl") + ) + }, )), }); diff --git a/wgpu/src/quad/solid.rs b/wgpu/src/quad/solid.rs index f8f1e3a5..9bc6b466 100644 --- a/wgpu/src/quad/solid.rs +++ b/wgpu/src/quad/solid.rs @@ -72,7 +72,11 @@ impl Pipeline { device.create_shader_module(wgpu::ShaderModuleDescriptor { label: Some("iced_wgpu.quad.solid.shader"), source: wgpu::ShaderSource::Wgsl(std::borrow::Cow::Borrowed( - include_str!("../shader/quad.wgsl"), + concat!( + include_str!("../shader/quad.wgsl"), + "\n", + include_str!("../shader/quad/solid.wgsl"), + ), )), }); diff --git a/wgpu/src/shader/color/linear_rgb.wgsl b/wgpu/src/shader/color/linear_rgb.wgsl new file mode 100644 index 00000000..a5cf45d4 --- /dev/null +++ b/wgpu/src/shader/color/linear_rgb.wgsl @@ -0,0 +1,3 @@ +fn interpolate_color(from_: vec4, to_: vec4, factor: f32) -> vec4 { + return mix(from_, to_, factor); +} diff --git a/wgpu/src/shader/color/oklab.wgsl b/wgpu/src/shader/color/oklab.wgsl new file mode 100644 index 00000000..0dc37ba6 --- /dev/null +++ b/wgpu/src/shader/color/oklab.wgsl @@ -0,0 +1,26 @@ +const to_lms = mat3x4( + vec4(0.4121656120, 0.2118591070, 0.0883097947, 0.0), + vec4(0.5362752080, 0.6807189584, 0.2818474174, 0.0), + vec4(0.0514575653, 0.1074065790, 0.6302613616, 0.0), +); + +const to_rgb = mat3x4( + vec4( 4.0767245293, -3.3072168827, 0.2307590544, 0.0), + vec4(-1.2681437731, 2.6093323231, -0.3411344290, 0.0), + vec4(-0.0041119885, -0.7034763098, 1.7068625689, 0.0), +); + +fn interpolate_color(from_: vec4, to_: vec4, factor: f32) -> vec4 { + // To Oklab + let lms_a = pow(from_ * to_lms, vec3(1.0 / 3.0, 1.0 / 3.0, 1.0 / 3.0)); + let lms_b = pow(to_ * to_lms, vec3(1.0 / 3.0, 1.0 / 3.0, 1.0 / 3.0)); + let mixed = mix(lms_a, lms_b, factor); + + // Back to linear RGB + var color = to_rgb * (mixed * mixed * mixed); + + // Alpha interpolation + color.a = mix(from_.a, to_.a, factor); + + return color; +} diff --git a/wgpu/src/shader/quad.wgsl b/wgpu/src/shader/quad.wgsl index cba7e5a4..f919cfe2 100644 --- a/wgpu/src/shader/quad.wgsl +++ b/wgpu/src/shader/quad.wgsl @@ -37,325 +37,3 @@ fn select_border_radius(radi: vec4, position: vec2, center: vec2) rx = select(rx, ry, position.y > center.y); return rx; } - -fn unpack_u32(color: vec2) -> vec4 { - let rg: vec2 = unpack2x16float(color.x); - let ba: vec2 = unpack2x16float(color.y); - - return vec4(rg.y, rg.x, ba.y, ba.x); -} - -struct SolidVertexInput { - @location(0) v_pos: vec2, - @location(1) color: vec4, - @location(2) pos: vec2, - @location(3) scale: vec2, - @location(4) border_color: vec4, - @location(5) border_radius: vec4, - @location(6) border_width: f32, -} - -struct SolidVertexOutput { - @builtin(position) position: vec4, - @location(0) color: vec4, - @location(1) border_color: vec4, - @location(2) pos: vec2, - @location(3) scale: vec2, - @location(4) border_radius: vec4, - @location(5) border_width: f32, -} - -@vertex -fn solid_vs_main(input: SolidVertexInput) -> SolidVertexOutput { - var out: SolidVertexOutput; - - var pos: vec2 = input.pos * globals.scale; - var scale: vec2 = input.scale * globals.scale; - - var min_border_radius = min(input.scale.x, input.scale.y) * 0.5; - var border_radius: vec4 = vec4( - min(input.border_radius.x, min_border_radius), - min(input.border_radius.y, min_border_radius), - min(input.border_radius.z, min_border_radius), - min(input.border_radius.w, min_border_radius) - ); - - var transform: mat4x4 = mat4x4( - vec4(scale.x + 1.0, 0.0, 0.0, 0.0), - vec4(0.0, scale.y + 1.0, 0.0, 0.0), - vec4(0.0, 0.0, 1.0, 0.0), - vec4(pos - vec2(0.5, 0.5), 0.0, 1.0) - ); - - out.position = globals.transform * transform * vec4(input.v_pos, 0.0, 1.0); - out.color = input.color; - out.border_color = input.border_color; - out.pos = pos; - out.scale = scale; - out.border_radius = border_radius * globals.scale; - out.border_width = input.border_width * globals.scale; - - return out; -} - -@fragment -fn solid_fs_main( - input: SolidVertexOutput -) -> @location(0) vec4 { - var mixed_color: vec4 = input.color; - - var border_radius = select_border_radius( - input.border_radius, - input.position.xy, - (input.pos + input.scale * 0.5).xy - ); - - if (input.border_width > 0.0) { - var internal_border: f32 = max(border_radius - input.border_width, 0.0); - - var internal_distance: f32 = distance_alg( - input.position.xy, - input.pos + vec2(input.border_width, input.border_width), - input.scale - vec2(input.border_width * 2.0, input.border_width * 2.0), - internal_border - ); - - var border_mix: f32 = smoothstep( - max(internal_border - 0.5, 0.0), - internal_border + 0.5, - internal_distance - ); - - mixed_color = mix(input.color, input.border_color, vec4(border_mix, border_mix, border_mix, border_mix)); - } - - var dist: f32 = distance_alg( - vec2(input.position.x, input.position.y), - input.pos, - input.scale, - border_radius - ); - - var radius_alpha: f32 = 1.0 - smoothstep( - max(border_radius - 0.5, 0.0), - border_radius + 0.5, - dist - ); - - return vec4(mixed_color.x, mixed_color.y, mixed_color.z, mixed_color.w * radius_alpha); -} - -struct GradientVertexInput { - @location(0) v_pos: vec2, - @location(1) @interpolate(flat) colors_1: vec4, - @location(2) @interpolate(flat) colors_2: vec4, - @location(3) @interpolate(flat) colors_3: vec4, - @location(4) @interpolate(flat) colors_4: vec4, - @location(5) @interpolate(flat) offsets: vec4, - @location(6) direction: vec4, - @location(7) position_and_scale: vec4, - @location(8) border_color: vec4, - @location(9) border_radius: vec4, - @location(10) border_width: f32, -} - -struct GradientVertexOutput { - @builtin(position) position: vec4, - @location(1) @interpolate(flat) colors_1: vec4, - @location(2) @interpolate(flat) colors_2: vec4, - @location(3) @interpolate(flat) colors_3: vec4, - @location(4) @interpolate(flat) colors_4: vec4, - @location(5) @interpolate(flat) offsets: vec4, - @location(6) direction: vec4, - @location(7) position_and_scale: vec4, - @location(8) border_color: vec4, - @location(9) border_radius: vec4, - @location(10) border_width: f32, -} - -@vertex -fn gradient_vs_main(input: GradientVertexInput) -> GradientVertexOutput { - var out: GradientVertexOutput; - - var pos: vec2 = input.position_and_scale.xy * globals.scale; - var scale: vec2 = input.position_and_scale.zw * globals.scale; - - var min_border_radius = min(input.position_and_scale.z, input.position_and_scale.w) * 0.5; - var border_radius: vec4 = vec4( - min(input.border_radius.x, min_border_radius), - min(input.border_radius.y, min_border_radius), - min(input.border_radius.z, min_border_radius), - min(input.border_radius.w, min_border_radius) - ); - - var transform: mat4x4 = mat4x4( - vec4(scale.x + 1.0, 0.0, 0.0, 0.0), - vec4(0.0, scale.y + 1.0, 0.0, 0.0), - vec4(0.0, 0.0, 1.0, 0.0), - vec4(pos - vec2(0.5, 0.5), 0.0, 1.0) - ); - - out.position = globals.transform * transform * vec4(input.v_pos, 0.0, 1.0); - out.colors_1 = input.colors_1; - out.colors_2 = input.colors_2; - out.colors_3 = input.colors_3; - out.colors_4 = input.colors_4; - out.offsets = input.offsets; - out.direction = input.direction * globals.scale; - out.position_and_scale = vec4(pos, scale); - out.border_color = input.border_color; - out.border_radius = border_radius * globals.scale; - out.border_width = input.border_width * globals.scale; - - return out; -} - -fn random(coords: vec2) -> f32 { - return fract(sin(dot(coords, vec2(12.9898,78.233))) * 43758.5453); -} - -/// Returns the current interpolated color with a max 8-stop gradient -fn gradient( - raw_position: vec2, - direction: vec4, - colors: array, 8>, - offsets: array, - last_index: i32 -) -> vec4 { - let start = direction.xy; - let end = direction.zw; - - let v1 = end - start; - let v2 = raw_position - start; - let unit = normalize(v1); - let coord_offset = dot(unit, v2) / length(v1); - - let to_lms: mat3x4 = mat3x4( - vec4(0.4121656120, 0.2118591070, 0.0883097947, 0.0), - vec4(0.5362752080, 0.6807189584, 0.2818474174, 0.0), - vec4(0.0514575653, 0.1074065790, 0.6302613616, 0.0), - ); - - let to_rgb: mat3x4 = mat3x4( - vec4( 4.0767245293, -3.3072168827, 0.2307590544, 0.0), - vec4(-1.2681437731, 2.6093323231, -0.3411344290, 0.0), - vec4(-0.0041119885, -0.7034763098, 1.7068625689, 0.0), - ); - - //need to store these as a var to use dynamic indexing in a loop - //this is already added to wgsl spec but not in wgpu yet - var colors_arr = colors; - var offsets_arr = offsets; - - var color: vec4; - - let noise_granularity: f32 = 0.3/255.0; - - for (var i: i32 = 0; i < last_index; i++) { - let curr_offset = offsets_arr[i]; - let next_offset = offsets_arr[i+1]; - - if (coord_offset <= offsets_arr[0]) { - color = colors_arr[0]; - } - - if (curr_offset <= coord_offset && coord_offset <= next_offset) { - // blend in OKLab - let factor = smoothstep(curr_offset, next_offset, coord_offset); - let lms_a = pow(colors_arr[i] * to_lms, vec3(1.0 / 3.0, 1.0 / 3.0, 1.0 / 3.0)); - let lms_b = pow(colors_arr[i+1] * to_lms, vec3(1.0 / 3.0, 1.0 / 3.0, 1.0 / 3.0)); - let mixed = mix(lms_a, lms_b, factor); - - // back to sRGB - color = to_rgb * (mixed * mixed * mixed); - color.a = mix(colors_arr[i].a, colors_arr[i+1].a, factor); - } - - if (coord_offset >= offsets_arr[last_index]) { - color = colors_arr[last_index]; - } - } - - return color + mix(-noise_granularity, noise_granularity, random(raw_position)); -} - -@fragment -fn gradient_fs_main(input: GradientVertexOutput) -> @location(0) vec4 { - let colors = array, 8>( - unpack_u32(input.colors_1.xy), - unpack_u32(input.colors_1.zw), - unpack_u32(input.colors_2.xy), - unpack_u32(input.colors_2.zw), - unpack_u32(input.colors_3.xy), - unpack_u32(input.colors_3.zw), - unpack_u32(input.colors_4.xy), - unpack_u32(input.colors_4.zw), - ); - - let offsets_1: vec4 = unpack_u32(input.offsets.xy); - let offsets_2: vec4 = unpack_u32(input.offsets.zw); - - var offsets = array( - offsets_1.x, - offsets_1.y, - offsets_1.z, - offsets_1.w, - offsets_2.x, - offsets_2.y, - offsets_2.z, - offsets_2.w, - ); - - //TODO could just pass this in to the shader but is probably more performant to just check it here - var last_index = 7; - for (var i: i32 = 0; i <= 7; i++) { - if (offsets[i] > 1.0) { - last_index = i - 1; - break; - } - } - - var mixed_color: vec4 = gradient(input.position.xy, input.direction, colors, offsets, last_index); - - let pos = input.position_and_scale.xy; - let scale = input.position_and_scale.zw; - - var border_radius = select_border_radius( - input.border_radius, - input.position.xy, - (pos + scale * 0.5).xy - ); - - if (input.border_width > 0.0) { - var internal_border: f32 = max(border_radius - input.border_width, 0.0); - - var internal_distance: f32 = distance_alg( - input.position.xy, - pos + vec2(input.border_width, input.border_width), - scale - vec2(input.border_width * 2.0, input.border_width * 2.0), - internal_border - ); - - var border_mix: f32 = smoothstep( - max(internal_border - 0.5, 0.0), - internal_border + 0.5, - internal_distance - ); - - mixed_color = mix(mixed_color, input.border_color, vec4(border_mix, border_mix, border_mix, border_mix)); - } - - var dist: f32 = distance_alg( - input.position.xy, - pos, - scale, - border_radius - ); - - var radius_alpha: f32 = 1.0 - smoothstep( - max(border_radius - 0.5, 0.0), - border_radius + 0.5, - dist); - - return vec4(mixed_color.x, mixed_color.y, mixed_color.z, mixed_color.w * radius_alpha); -} diff --git a/wgpu/src/shader/quad/gradient.wgsl b/wgpu/src/shader/quad/gradient.wgsl new file mode 100644 index 00000000..0754e97f --- /dev/null +++ b/wgpu/src/shader/quad/gradient.wgsl @@ -0,0 +1,205 @@ +struct GradientVertexInput { + @location(0) v_pos: vec2, + @location(1) @interpolate(flat) colors_1: vec4, + @location(2) @interpolate(flat) colors_2: vec4, + @location(3) @interpolate(flat) colors_3: vec4, + @location(4) @interpolate(flat) colors_4: vec4, + @location(5) @interpolate(flat) offsets: vec4, + @location(6) direction: vec4, + @location(7) position_and_scale: vec4, + @location(8) border_color: vec4, + @location(9) border_radius: vec4, + @location(10) border_width: f32, +} + +struct GradientVertexOutput { + @builtin(position) position: vec4, + @location(1) @interpolate(flat) colors_1: vec4, + @location(2) @interpolate(flat) colors_2: vec4, + @location(3) @interpolate(flat) colors_3: vec4, + @location(4) @interpolate(flat) colors_4: vec4, + @location(5) @interpolate(flat) offsets: vec4, + @location(6) direction: vec4, + @location(7) position_and_scale: vec4, + @location(8) border_color: vec4, + @location(9) border_radius: vec4, + @location(10) border_width: f32, +} + +@vertex +fn gradient_vs_main(input: GradientVertexInput) -> GradientVertexOutput { + var out: GradientVertexOutput; + + var pos: vec2 = input.position_and_scale.xy * globals.scale; + var scale: vec2 = input.position_and_scale.zw * globals.scale; + + var min_border_radius = min(input.position_and_scale.z, input.position_and_scale.w) * 0.5; + var border_radius: vec4 = vec4( + min(input.border_radius.x, min_border_radius), + min(input.border_radius.y, min_border_radius), + min(input.border_radius.z, min_border_radius), + min(input.border_radius.w, min_border_radius) + ); + + var transform: mat4x4 = mat4x4( + vec4(scale.x + 1.0, 0.0, 0.0, 0.0), + vec4(0.0, scale.y + 1.0, 0.0, 0.0), + vec4(0.0, 0.0, 1.0, 0.0), + vec4(pos - vec2(0.5, 0.5), 0.0, 1.0) + ); + + out.position = globals.transform * transform * vec4(input.v_pos, 0.0, 1.0); + out.colors_1 = input.colors_1; + out.colors_2 = input.colors_2; + out.colors_3 = input.colors_3; + out.colors_4 = input.colors_4; + out.offsets = input.offsets; + out.direction = input.direction * globals.scale; + out.position_and_scale = vec4(pos, scale); + out.border_color = input.border_color; + out.border_radius = border_radius * globals.scale; + out.border_width = input.border_width * globals.scale; + + return out; +} + +fn random(coords: vec2) -> f32 { + return fract(sin(dot(coords, vec2(12.9898,78.233))) * 43758.5453); +} + +/// Returns the current interpolated color with a max 8-stop gradient +fn gradient( + raw_position: vec2, + direction: vec4, + colors: array, 8>, + offsets: array, + last_index: i32 +) -> vec4 { + let start = direction.xy; + let end = direction.zw; + + let v1 = end - start; + let v2 = raw_position - start; + let unit = normalize(v1); + let coord_offset = dot(unit, v2) / length(v1); + + //need to store these as a var to use dynamic indexing in a loop + //this is already added to wgsl spec but not in wgpu yet + var colors_arr = colors; + var offsets_arr = offsets; + + var color: vec4; + + let noise_granularity: f32 = 0.3/255.0; + + for (var i: i32 = 0; i < last_index; i++) { + let curr_offset = offsets_arr[i]; + let next_offset = offsets_arr[i+1]; + + if (coord_offset <= offsets_arr[0]) { + color = colors_arr[0]; + } + + if (curr_offset <= coord_offset && coord_offset <= next_offset) { + let from_ = colors_arr[i]; + let to_ = colors_arr[i+1]; + let factor = smoothstep(curr_offset, next_offset, coord_offset); + + color = interpolate_color(from_, to_, factor); + } + + if (coord_offset >= offsets_arr[last_index]) { + color = colors_arr[last_index]; + } + } + + return color + mix(-noise_granularity, noise_granularity, random(raw_position)); +} + +@fragment +fn gradient_fs_main(input: GradientVertexOutput) -> @location(0) vec4 { + let colors = array, 8>( + unpack_u32(input.colors_1.xy), + unpack_u32(input.colors_1.zw), + unpack_u32(input.colors_2.xy), + unpack_u32(input.colors_2.zw), + unpack_u32(input.colors_3.xy), + unpack_u32(input.colors_3.zw), + unpack_u32(input.colors_4.xy), + unpack_u32(input.colors_4.zw), + ); + + let offsets_1: vec4 = unpack_u32(input.offsets.xy); + let offsets_2: vec4 = unpack_u32(input.offsets.zw); + + var offsets = array( + offsets_1.x, + offsets_1.y, + offsets_1.z, + offsets_1.w, + offsets_2.x, + offsets_2.y, + offsets_2.z, + offsets_2.w, + ); + + //TODO could just pass this in to the shader but is probably more performant to just check it here + var last_index = 7; + for (var i: i32 = 0; i <= 7; i++) { + if (offsets[i] > 1.0) { + last_index = i - 1; + break; + } + } + + var mixed_color: vec4 = gradient(input.position.xy, input.direction, colors, offsets, last_index); + + let pos = input.position_and_scale.xy; + let scale = input.position_and_scale.zw; + + var border_radius = select_border_radius( + input.border_radius, + input.position.xy, + (pos + scale * 0.5).xy + ); + + if (input.border_width > 0.0) { + var internal_border: f32 = max(border_radius - input.border_width, 0.0); + + var internal_distance: f32 = distance_alg( + input.position.xy, + pos + vec2(input.border_width, input.border_width), + scale - vec2(input.border_width * 2.0, input.border_width * 2.0), + internal_border + ); + + var border_mix: f32 = smoothstep( + max(internal_border - 0.5, 0.0), + internal_border + 0.5, + internal_distance + ); + + mixed_color = mix(mixed_color, input.border_color, vec4(border_mix, border_mix, border_mix, border_mix)); + } + + var dist: f32 = distance_alg( + input.position.xy, + pos, + scale, + border_radius + ); + + var radius_alpha: f32 = 1.0 - smoothstep( + max(border_radius - 0.5, 0.0), + border_radius + 0.5, + dist); + + return vec4(mixed_color.x, mixed_color.y, mixed_color.z, mixed_color.w * radius_alpha); +} + +fn unpack_u32(color: vec2) -> vec4 { + let rg: vec2 = unpack2x16float(color.x); + let ba: vec2 = unpack2x16float(color.y); + + return vec4(rg.y, rg.x, ba.y, ba.x); +} diff --git a/wgpu/src/shader/quad/solid.wgsl b/wgpu/src/shader/quad/solid.wgsl new file mode 100644 index 00000000..ebd6d877 --- /dev/null +++ b/wgpu/src/shader/quad/solid.wgsl @@ -0,0 +1,99 @@ +struct SolidVertexInput { + @location(0) v_pos: vec2, + @location(1) color: vec4, + @location(2) pos: vec2, + @location(3) scale: vec2, + @location(4) border_color: vec4, + @location(5) border_radius: vec4, + @location(6) border_width: f32, +} + +struct SolidVertexOutput { + @builtin(position) position: vec4, + @location(0) color: vec4, + @location(1) border_color: vec4, + @location(2) pos: vec2, + @location(3) scale: vec2, + @location(4) border_radius: vec4, + @location(5) border_width: f32, +} + +@vertex +fn solid_vs_main(input: SolidVertexInput) -> SolidVertexOutput { + var out: SolidVertexOutput; + + var pos: vec2 = input.pos * globals.scale; + var scale: vec2 = input.scale * globals.scale; + + var min_border_radius = min(input.scale.x, input.scale.y) * 0.5; + var border_radius: vec4 = vec4( + min(input.border_radius.x, min_border_radius), + min(input.border_radius.y, min_border_radius), + min(input.border_radius.z, min_border_radius), + min(input.border_radius.w, min_border_radius) + ); + + var transform: mat4x4 = mat4x4( + vec4(scale.x + 1.0, 0.0, 0.0, 0.0), + vec4(0.0, scale.y + 1.0, 0.0, 0.0), + vec4(0.0, 0.0, 1.0, 0.0), + vec4(pos - vec2(0.5, 0.5), 0.0, 1.0) + ); + + out.position = globals.transform * transform * vec4(input.v_pos, 0.0, 1.0); + out.color = input.color; + out.border_color = input.border_color; + out.pos = pos; + out.scale = scale; + out.border_radius = border_radius * globals.scale; + out.border_width = input.border_width * globals.scale; + + return out; +} + +@fragment +fn solid_fs_main( + input: SolidVertexOutput +) -> @location(0) vec4 { + var mixed_color: vec4 = input.color; + + var border_radius = select_border_radius( + input.border_radius, + input.position.xy, + (input.pos + input.scale * 0.5).xy + ); + + if (input.border_width > 0.0) { + var internal_border: f32 = max(border_radius - input.border_width, 0.0); + + var internal_distance: f32 = distance_alg( + input.position.xy, + input.pos + vec2(input.border_width, input.border_width), + input.scale - vec2(input.border_width * 2.0, input.border_width * 2.0), + internal_border + ); + + var border_mix: f32 = smoothstep( + max(internal_border - 0.5, 0.0), + internal_border + 0.5, + internal_distance + ); + + mixed_color = mix(input.color, input.border_color, vec4(border_mix, border_mix, border_mix, border_mix)); + } + + var dist: f32 = distance_alg( + vec2(input.position.x, input.position.y), + input.pos, + input.scale, + border_radius + ); + + var radius_alpha: f32 = 1.0 - smoothstep( + max(border_radius - 0.5, 0.0), + border_radius + 0.5, + dist + ); + + return vec4(mixed_color.x, mixed_color.y, mixed_color.z, mixed_color.w * radius_alpha); +} diff --git a/wgpu/src/shader/triangle.wgsl b/wgpu/src/shader/triangle.wgsl index 3a2b9845..e4c19344 100644 --- a/wgpu/src/shader/triangle.wgsl +++ b/wgpu/src/shader/triangle.wgsl @@ -3,163 +3,3 @@ struct Globals { } @group(0) @binding(0) var globals: Globals; - -fn unpack_u32(color: vec2) -> vec4 { - let rg: vec2 = unpack2x16float(color.x); - let ba: vec2 = unpack2x16float(color.y); - - return vec4(rg.y, rg.x, ba.y, ba.x); -} - -struct SolidVertexInput { - @location(0) position: vec2, - @location(1) color: vec4, -} - -struct SolidVertexOutput { - @builtin(position) position: vec4, - @location(0) color: vec4, -} - -@vertex -fn solid_vs_main(input: SolidVertexInput) -> SolidVertexOutput { - var out: SolidVertexOutput; - - out.color = input.color; - out.position = globals.transform * vec4(input.position, 0.0, 1.0); - - return out; -} - -@fragment -fn solid_fs_main(input: SolidVertexOutput) -> @location(0) vec4 { - return input.color; -} - -struct GradientVertexInput { - @location(0) v_pos: vec2, - @location(1) @interpolate(flat) colors_1: vec4, - @location(2) @interpolate(flat) colors_2: vec4, - @location(3) @interpolate(flat) colors_3: vec4, - @location(4) @interpolate(flat) colors_4: vec4, - @location(5) @interpolate(flat) offsets: vec4, - @location(6) direction: vec4, -} - -struct GradientVertexOutput { - @builtin(position) position: vec4, - @location(0) raw_position: vec2, - @location(1) @interpolate(flat) colors_1: vec4, - @location(2) @interpolate(flat) colors_2: vec4, - @location(3) @interpolate(flat) colors_3: vec4, - @location(4) @interpolate(flat) colors_4: vec4, - @location(5) @interpolate(flat) offsets: vec4, - @location(6) direction: vec4, -} - -@vertex -fn gradient_vs_main(input: GradientVertexInput) -> GradientVertexOutput { - var output: GradientVertexOutput; - - output.position = globals.transform * vec4(input.v_pos, 0.0, 1.0); - output.raw_position = input.v_pos; - output.colors_1 = input.colors_1; - output.colors_2 = input.colors_2; - output.colors_3 = input.colors_3; - output.colors_4 = input.colors_4; - output.offsets = input.offsets; - output.direction = input.direction; - - return output; -} - -fn random(coords: vec2) -> f32 { - return fract(sin(dot(coords, vec2(12.9898,78.233))) * 43758.5453); -} - -/// Returns the current interpolated color with a max 8-stop gradient -fn gradient( - raw_position: vec2, - direction: vec4, - colors: array, 8>, - offsets: array, - last_index: i32 -) -> vec4 { - let start = direction.xy; - let end = direction.zw; - - let v1 = end - start; - let v2 = raw_position - start; - let unit = normalize(v1); - let coord_offset = dot(unit, v2) / length(v1); - - //need to store these as a var to use dynamic indexing in a loop - //this is already added to wgsl spec but not in wgpu yet - var colors_arr = colors; - var offsets_arr = offsets; - - var color: vec4; - - let noise_granularity: f32 = 0.3/255.0; - - for (var i: i32 = 0; i < last_index; i++) { - let curr_offset = offsets_arr[i]; - let next_offset = offsets_arr[i+1]; - - if (coord_offset <= offsets_arr[0]) { - color = colors_arr[0]; - } - - if (curr_offset <= coord_offset && coord_offset <= next_offset) { - color = mix(colors_arr[i], colors_arr[i+1], smoothstep( - curr_offset, - next_offset, - coord_offset, - )); - } - - if (coord_offset >= offsets_arr[last_index]) { - color = colors_arr[last_index]; - } - } - - return color + mix(-noise_granularity, noise_granularity, random(raw_position)); -} - -@fragment -fn gradient_fs_main(input: GradientVertexOutput) -> @location(0) vec4 { - let colors = array, 8>( - unpack_u32(input.colors_1.xy), - unpack_u32(input.colors_1.zw), - unpack_u32(input.colors_2.xy), - unpack_u32(input.colors_2.zw), - unpack_u32(input.colors_3.xy), - unpack_u32(input.colors_3.zw), - unpack_u32(input.colors_4.xy), - unpack_u32(input.colors_4.zw), - ); - - let offsets_1: vec4 = unpack_u32(input.offsets.xy); - let offsets_2: vec4 = unpack_u32(input.offsets.zw); - - var offsets = array( - offsets_1.x, - offsets_1.y, - offsets_1.z, - offsets_1.w, - offsets_2.x, - offsets_2.y, - offsets_2.z, - offsets_2.w, - ); - - var last_index = 7; - for (var i: i32 = 0; i <= 7; i++) { - if (offsets[i] >= 1.0) { - last_index = i; - break; - } - } - - return gradient(input.raw_position, input.direction, colors, offsets, last_index); -} diff --git a/wgpu/src/shader/triangle/gradient.wgsl b/wgpu/src/shader/triangle/gradient.wgsl new file mode 100644 index 00000000..1a8ae3b5 --- /dev/null +++ b/wgpu/src/shader/triangle/gradient.wgsl @@ -0,0 +1,134 @@ +struct GradientVertexInput { + @location(0) v_pos: vec2, + @location(1) @interpolate(flat) colors_1: vec4, + @location(2) @interpolate(flat) colors_2: vec4, + @location(3) @interpolate(flat) colors_3: vec4, + @location(4) @interpolate(flat) colors_4: vec4, + @location(5) @interpolate(flat) offsets: vec4, + @location(6) direction: vec4, +} + +struct GradientVertexOutput { + @builtin(position) position: vec4, + @location(0) raw_position: vec2, + @location(1) @interpolate(flat) colors_1: vec4, + @location(2) @interpolate(flat) colors_2: vec4, + @location(3) @interpolate(flat) colors_3: vec4, + @location(4) @interpolate(flat) colors_4: vec4, + @location(5) @interpolate(flat) offsets: vec4, + @location(6) direction: vec4, +} + +@vertex +fn gradient_vs_main(input: GradientVertexInput) -> GradientVertexOutput { + var output: GradientVertexOutput; + + output.position = globals.transform * vec4(input.v_pos, 0.0, 1.0); + output.raw_position = input.v_pos; + output.colors_1 = input.colors_1; + output.colors_2 = input.colors_2; + output.colors_3 = input.colors_3; + output.colors_4 = input.colors_4; + output.offsets = input.offsets; + output.direction = input.direction; + + return output; +} + +/// Returns the current interpolated color with a max 8-stop gradient +fn gradient( + raw_position: vec2, + direction: vec4, + colors: array, 8>, + offsets: array, + last_index: i32 +) -> vec4 { + let start = direction.xy; + let end = direction.zw; + + let v1 = end - start; + let v2 = raw_position - start; + let unit = normalize(v1); + let coord_offset = dot(unit, v2) / length(v1); + + //need to store these as a var to use dynamic indexing in a loop + //this is already added to wgsl spec but not in wgpu yet + var colors_arr = colors; + var offsets_arr = offsets; + + var color: vec4; + + let noise_granularity: f32 = 0.3/255.0; + + for (var i: i32 = 0; i < last_index; i++) { + let curr_offset = offsets_arr[i]; + let next_offset = offsets_arr[i+1]; + + if (coord_offset <= offsets_arr[0]) { + color = colors_arr[0]; + } + + if (curr_offset <= coord_offset && coord_offset <= next_offset) { + let from_ = colors_arr[i]; + let to_ = colors_arr[i+1]; + let factor = smoothstep(curr_offset, next_offset, coord_offset); + + color = interpolate_color(from_, to_, factor); + } + + if (coord_offset >= offsets_arr[last_index]) { + color = colors_arr[last_index]; + } + } + + return color + mix(-noise_granularity, noise_granularity, random(raw_position)); +} + +@fragment +fn gradient_fs_main(input: GradientVertexOutput) -> @location(0) vec4 { + let colors = array, 8>( + unpack_u32(input.colors_1.xy), + unpack_u32(input.colors_1.zw), + unpack_u32(input.colors_2.xy), + unpack_u32(input.colors_2.zw), + unpack_u32(input.colors_3.xy), + unpack_u32(input.colors_3.zw), + unpack_u32(input.colors_4.xy), + unpack_u32(input.colors_4.zw), + ); + + let offsets_1: vec4 = unpack_u32(input.offsets.xy); + let offsets_2: vec4 = unpack_u32(input.offsets.zw); + + var offsets = array( + offsets_1.x, + offsets_1.y, + offsets_1.z, + offsets_1.w, + offsets_2.x, + offsets_2.y, + offsets_2.z, + offsets_2.w, + ); + + var last_index = 7; + for (var i: i32 = 0; i <= 7; i++) { + if (offsets[i] >= 1.0) { + last_index = i; + break; + } + } + + return gradient(input.raw_position, input.direction, colors, offsets, last_index); +} + +fn unpack_u32(color: vec2) -> vec4 { + let rg: vec2 = unpack2x16float(color.x); + let ba: vec2 = unpack2x16float(color.y); + + return vec4(rg.y, rg.x, ba.y, ba.x); +} + +fn random(coords: vec2) -> f32 { + return fract(sin(dot(coords, vec2(12.9898,78.233))) * 43758.5453); +} diff --git a/wgpu/src/shader/triangle/solid.wgsl b/wgpu/src/shader/triangle/solid.wgsl new file mode 100644 index 00000000..9ef81982 --- /dev/null +++ b/wgpu/src/shader/triangle/solid.wgsl @@ -0,0 +1,24 @@ +struct SolidVertexInput { + @location(0) position: vec2, + @location(1) color: vec4, +} + +struct SolidVertexOutput { + @builtin(position) position: vec4, + @location(0) color: vec4, +} + +@vertex +fn solid_vs_main(input: SolidVertexInput) -> SolidVertexOutput { + var out: SolidVertexOutput; + + out.color = input.color; + out.position = globals.transform * vec4(input.position, 0.0, 1.0); + + return out; +} + +@fragment +fn solid_fs_main(input: SolidVertexOutput) -> @location(0) vec4 { + return input.color; +} diff --git a/wgpu/src/triangle.rs b/wgpu/src/triangle.rs index d8b23dfe..d430e607 100644 --- a/wgpu/src/triangle.rs +++ b/wgpu/src/triangle.rs @@ -487,8 +487,10 @@ mod solid { device.create_shader_module(wgpu::ShaderModuleDescriptor { label: Some("iced_wgpu.triangle.solid.shader"), source: wgpu::ShaderSource::Wgsl( - std::borrow::Cow::Borrowed(include_str!( - "shader/triangle.wgsl" + std::borrow::Cow::Borrowed(concat!( + include_str!("shader/triangle.wgsl"), + "\n", + include_str!("shader/triangle/solid.wgsl"), )), ), }); @@ -537,6 +539,7 @@ mod solid { } mod gradient { + use crate::graphics::color; use crate::graphics::mesh; use crate::graphics::Antialiasing; use crate::triangle; @@ -633,9 +636,31 @@ mod gradient { device.create_shader_module(wgpu::ShaderModuleDescriptor { label: Some("iced_wgpu.triangle.gradient.shader"), source: wgpu::ShaderSource::Wgsl( - std::borrow::Cow::Borrowed(include_str!( - "shader/triangle.wgsl" - )), + std::borrow::Cow::Borrowed( + if color::GAMMA_CORRECTION { + concat!( + include_str!("shader/triangle.wgsl"), + "\n", + include_str!( + "shader/triangle/gradient.wgsl" + ), + "\n", + include_str!("shader/color/oklab.wgsl") + ) + } else { + concat!( + include_str!("shader/triangle.wgsl"), + "\n", + include_str!( + "shader/triangle/gradient.wgsl" + ), + "\n", + include_str!( + "shader/color/linear_rgb.wgsl" + ) + ) + }, + ), ), }); -- cgit From 89d9f1d7d2202029028a487df1dd11b0665a7517 Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Sat, 9 Sep 2023 12:24:47 +0200 Subject: Fix majority of unresolved documentation links --- wgpu/src/geometry.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'wgpu') diff --git a/wgpu/src/geometry.rs b/wgpu/src/geometry.rs index c3e16f8c..63a59c05 100644 --- a/wgpu/src/geometry.rs +++ b/wgpu/src/geometry.rs @@ -310,13 +310,11 @@ impl Frame { /// resulting glyphs will not be rotated or scaled properly. /// /// Additionally, all text will be rendered on top of all the layers of - /// a [`Canvas`]. Therefore, it is currently only meant to be used for + /// a `Canvas`. Therefore, it is currently only meant to be used for /// overlays, which is the most common use case. /// /// Support for vectorial text is planned, and should address all these /// limitations. - /// - /// [`Canvas`]: crate::widget::Canvas pub fn fill_text(&mut self, text: impl Into) { let text = text.into(); -- cgit From f60884f6f8639f75258c264bf4a15591351ef05b Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 9 Sep 2023 20:58:45 +0200 Subject: Deny `broken_intradoc_links` and verify documentation in CI --- wgpu/src/lib.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'wgpu') diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index d1e4b7af..b9f54560 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -20,6 +20,7 @@ #![doc( html_logo_url = "https://raw.githubusercontent.com/iced-rs/iced/9ab6923e943f784985e9ef9ca28b10278297225d/docs/logo.svg" )] +#![forbid(rust_2018_idioms)] #![deny( missing_debug_implementations, missing_docs, @@ -29,9 +30,9 @@ clippy::from_over_into, clippy::needless_borrow, clippy::new_without_default, - clippy::useless_conversion + clippy::useless_conversion, + rustdoc::broken_intra_doc_links )] -#![forbid(rust_2018_idioms)] #![allow(clippy::inherent_to_string, clippy::type_complexity)] #![cfg_attr(docsrs, feature(doc_auto_cfg))] pub mod layer; -- cgit