From 781ef1f94c4859aeeb852f801b72be095b8ff82b Mon Sep 17 00:00:00 2001 From: Bingus Date: Thu, 14 Sep 2023 13:58:36 -0700 Subject: Added support for custom shader widget for iced_wgpu backend. --- examples/custom_shader/src/main.rs | 174 +++++++++++++++++++++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 examples/custom_shader/src/main.rs (limited to 'examples/custom_shader/src/main.rs') diff --git a/examples/custom_shader/src/main.rs b/examples/custom_shader/src/main.rs new file mode 100644 index 00000000..76fa1625 --- /dev/null +++ b/examples/custom_shader/src/main.rs @@ -0,0 +1,174 @@ +mod camera; +mod cubes; +mod pipeline; +mod primitive; + +use crate::cubes::Cubes; +use iced::widget::{ + checkbox, column, container, row, slider, text, vertical_space, Shader, +}; +use iced::{ + executor, window, Alignment, Application, Color, Command, Element, Length, + Renderer, Subscription, Theme, +}; +use std::time::Instant; + +fn main() -> iced::Result { + IcedCubes::run(iced::Settings::default()) +} + +struct IcedCubes { + start: Instant, + cubes: Cubes, + num_cubes_slider: u32, +} + +impl Default for IcedCubes { + fn default() -> Self { + Self { + start: Instant::now(), + cubes: Cubes::new(), + num_cubes_slider: cubes::MAX, + } + } +} + +#[derive(Debug, Clone)] +enum Message { + CubeAmountChanged(u32), + CubeSizeChanged(f32), + Tick(Instant), + ShowDepthBuffer(bool), + LightColorChanged(Color), +} + +impl Application for IcedCubes { + type Executor = executor::Default; + type Message = Message; + type Theme = Theme; + type Flags = (); + + fn new(_flags: Self::Flags) -> (Self, Command) { + (IcedCubes::default(), Command::none()) + } + + fn title(&self) -> String { + "Iced Cubes".to_string() + } + + fn update(&mut self, message: Self::Message) -> Command { + match message { + Message::CubeAmountChanged(num) => { + self.num_cubes_slider = num; + self.cubes.adjust_num_cubes(num); + } + Message::CubeSizeChanged(size) => { + self.cubes.size = size; + } + Message::Tick(time) => { + self.cubes.update(time - self.start); + } + Message::ShowDepthBuffer(show) => { + self.cubes.show_depth_buffer = show; + } + Message::LightColorChanged(color) => { + self.cubes.light_color = color; + } + } + + Command::none() + } + + fn view(&self) -> Element<'_, Self::Message, Renderer> { + let top_controls = row![ + control( + "Amount", + slider( + 1..=cubes::MAX, + self.num_cubes_slider, + Message::CubeAmountChanged + ) + .width(100) + ), + control( + "Size", + slider(0.1..=0.25, self.cubes.size, Message::CubeSizeChanged) + .step(0.01) + .width(100), + ), + checkbox( + "Show Depth Buffer", + self.cubes.show_depth_buffer, + Message::ShowDepthBuffer + ), + ] + .spacing(40); + + let bottom_controls = row![ + control( + "R", + slider(0.0..=1.0, self.cubes.light_color.r, move |r| { + Message::LightColorChanged(Color { + r, + ..self.cubes.light_color + }) + }) + .step(0.01) + .width(100) + ), + control( + "G", + slider(0.0..=1.0, self.cubes.light_color.g, move |g| { + Message::LightColorChanged(Color { + g, + ..self.cubes.light_color + }) + }) + .step(0.01) + .width(100) + ), + control( + "B", + slider(0.0..=1.0, self.cubes.light_color.b, move |b| { + Message::LightColorChanged(Color { + b, + ..self.cubes.light_color + }) + }) + .step(0.01) + .width(100) + ) + ] + .spacing(40); + + let controls = column![top_controls, bottom_controls,] + .spacing(10) + .align_items(Alignment::Center); + + let shader = Shader::new(&self.cubes) + .width(Length::Fill) + .height(Length::Fill); + + container( + column![shader, controls, vertical_space(20),] + .spacing(40) + .align_items(Alignment::Center), + ) + .width(Length::Fill) + .height(Length::Fill) + .center_x() + .center_y() + .into() + } + + fn subscription(&self) -> Subscription { + window::frames().map(Message::Tick) + } +} + +fn control<'a>( + label: &'static str, + control: impl Into>, +) -> Element<'a, Message> { + row![text(label), control.into()].spacing(10).into() +} -- cgit From 9489e29e6619b14ed9f41a8887c4b34158266f71 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 14 Nov 2023 12:49:49 +0100 Subject: Re-organize `custom` module as `pipeline` module ... and move `Shader` widget to `iced_widget` crate --- examples/custom_shader/src/main.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'examples/custom_shader/src/main.rs') diff --git a/examples/custom_shader/src/main.rs b/examples/custom_shader/src/main.rs index 76fa1625..f6370f46 100644 --- a/examples/custom_shader/src/main.rs +++ b/examples/custom_shader/src/main.rs @@ -3,15 +3,20 @@ mod cubes; mod pipeline; mod primitive; +use crate::camera::Camera; use crate::cubes::Cubes; +use crate::pipeline::Pipeline; + +use iced::executor; +use iced::time::Instant; use iced::widget::{ checkbox, column, container, row, slider, text, vertical_space, Shader, }; +use iced::window; use iced::{ - executor, window, Alignment, Application, Color, Command, Element, Length, - Renderer, Subscription, Theme, + Alignment, Application, Color, Command, Element, Length, Renderer, + Subscription, Theme, }; -use std::time::Instant; fn main() -> iced::Result { IcedCubes::run(iced::Settings::default()) -- cgit From 91d7df52cdedd1b5c431fdb51a6356e827765b60 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 14 Nov 2023 13:25:49 +0100 Subject: Create `shader` function helper in `iced_widget` --- examples/custom_shader/src/main.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'examples/custom_shader/src/main.rs') diff --git a/examples/custom_shader/src/main.rs b/examples/custom_shader/src/main.rs index f6370f46..e9b6776f 100644 --- a/examples/custom_shader/src/main.rs +++ b/examples/custom_shader/src/main.rs @@ -10,7 +10,7 @@ use crate::pipeline::Pipeline; use iced::executor; use iced::time::Instant; use iced::widget::{ - checkbox, column, container, row, slider, text, vertical_space, Shader, + checkbox, column, container, row, shader, slider, text, vertical_space, }; use iced::window; use iced::{ @@ -150,9 +150,8 @@ impl Application for IcedCubes { .spacing(10) .align_items(Alignment::Center); - let shader = Shader::new(&self.cubes) - .width(Length::Fill) - .height(Length::Fill); + let shader = + shader(&self.cubes).width(Length::Fill).height(Length::Fill); container( column![shader, controls, vertical_space(20),] -- cgit From 63f36b04638f14af3455ead8b82d581a438a28a3 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 14 Nov 2023 14:04:54 +0100 Subject: Export `wgpu` crate in `shader` module in `iced_widget` --- examples/custom_shader/src/main.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'examples/custom_shader/src/main.rs') diff --git a/examples/custom_shader/src/main.rs b/examples/custom_shader/src/main.rs index e9b6776f..e7b07d78 100644 --- a/examples/custom_shader/src/main.rs +++ b/examples/custom_shader/src/main.rs @@ -9,6 +9,7 @@ use crate::pipeline::Pipeline; use iced::executor; use iced::time::Instant; +use iced::widget::shader::wgpu; use iced::widget::{ checkbox, column, container, row, shader, slider, text, vertical_space, }; -- cgit From 78a06384b1e6fc5e0c472dc19169fcaf11fe27b2 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 14 Nov 2023 14:36:38 +0100 Subject: Use a single source for amount of cubes in `custom_shader` example --- examples/custom_shader/src/main.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'examples/custom_shader/src/main.rs') diff --git a/examples/custom_shader/src/main.rs b/examples/custom_shader/src/main.rs index e7b07d78..3336e7f5 100644 --- a/examples/custom_shader/src/main.rs +++ b/examples/custom_shader/src/main.rs @@ -26,7 +26,6 @@ fn main() -> iced::Result { struct IcedCubes { start: Instant, cubes: Cubes, - num_cubes_slider: u32, } impl Default for IcedCubes { @@ -34,7 +33,6 @@ impl Default for IcedCubes { Self { start: Instant::now(), cubes: Cubes::new(), - num_cubes_slider: cubes::MAX, } } } @@ -65,7 +63,6 @@ impl Application for IcedCubes { fn update(&mut self, message: Self::Message) -> Command { match message { Message::CubeAmountChanged(num) => { - self.num_cubes_slider = num; self.cubes.adjust_num_cubes(num); } Message::CubeSizeChanged(size) => { @@ -91,7 +88,7 @@ impl Application for IcedCubes { "Amount", slider( 1..=cubes::MAX, - self.num_cubes_slider, + self.cubes.cubes.len() as u32, Message::CubeAmountChanged ) .width(100) -- cgit From 9ddfaf3ee73cef3e7bd122f4d11893f77647c2c3 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 14 Nov 2023 14:41:48 +0100 Subject: Rename `cubes` to `scene` in `custom_shader` example --- examples/custom_shader/src/main.rs | 42 +++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 21 deletions(-) (limited to 'examples/custom_shader/src/main.rs') diff --git a/examples/custom_shader/src/main.rs b/examples/custom_shader/src/main.rs index 3336e7f5..f90061d7 100644 --- a/examples/custom_shader/src/main.rs +++ b/examples/custom_shader/src/main.rs @@ -1,11 +1,11 @@ mod camera; -mod cubes; mod pipeline; mod primitive; +mod scene; use crate::camera::Camera; -use crate::cubes::Cubes; use crate::pipeline::Pipeline; +use crate::scene::Scene; use iced::executor; use iced::time::Instant; @@ -25,14 +25,14 @@ fn main() -> iced::Result { struct IcedCubes { start: Instant, - cubes: Cubes, + scene: Scene, } impl Default for IcedCubes { fn default() -> Self { Self { start: Instant::now(), - cubes: Cubes::new(), + scene: Scene::new(), } } } @@ -62,20 +62,20 @@ impl Application for IcedCubes { fn update(&mut self, message: Self::Message) -> Command { match message { - Message::CubeAmountChanged(num) => { - self.cubes.adjust_num_cubes(num); + Message::CubeAmountChanged(amount) => { + self.scene.change_amount(amount); } Message::CubeSizeChanged(size) => { - self.cubes.size = size; + self.scene.size = size; } Message::Tick(time) => { - self.cubes.update(time - self.start); + self.scene.update(time - self.start); } Message::ShowDepthBuffer(show) => { - self.cubes.show_depth_buffer = show; + self.scene.show_depth_buffer = show; } Message::LightColorChanged(color) => { - self.cubes.light_color = color; + self.scene.light_color = color; } } @@ -87,21 +87,21 @@ impl Application for IcedCubes { control( "Amount", slider( - 1..=cubes::MAX, - self.cubes.cubes.len() as u32, + 1..=scene::MAX, + self.scene.cubes.len() as u32, Message::CubeAmountChanged ) .width(100) ), control( "Size", - slider(0.1..=0.25, self.cubes.size, Message::CubeSizeChanged) + slider(0.1..=0.25, self.scene.size, Message::CubeSizeChanged) .step(0.01) .width(100), ), checkbox( "Show Depth Buffer", - self.cubes.show_depth_buffer, + self.scene.show_depth_buffer, Message::ShowDepthBuffer ), ] @@ -110,10 +110,10 @@ impl Application for IcedCubes { let bottom_controls = row![ control( "R", - slider(0.0..=1.0, self.cubes.light_color.r, move |r| { + slider(0.0..=1.0, self.scene.light_color.r, move |r| { Message::LightColorChanged(Color { r, - ..self.cubes.light_color + ..self.scene.light_color }) }) .step(0.01) @@ -121,10 +121,10 @@ impl Application for IcedCubes { ), control( "G", - slider(0.0..=1.0, self.cubes.light_color.g, move |g| { + slider(0.0..=1.0, self.scene.light_color.g, move |g| { Message::LightColorChanged(Color { g, - ..self.cubes.light_color + ..self.scene.light_color }) }) .step(0.01) @@ -132,10 +132,10 @@ impl Application for IcedCubes { ), control( "B", - slider(0.0..=1.0, self.cubes.light_color.b, move |b| { + slider(0.0..=1.0, self.scene.light_color.b, move |b| { Message::LightColorChanged(Color { b, - ..self.cubes.light_color + ..self.scene.light_color }) }) .step(0.01) @@ -149,7 +149,7 @@ impl Application for IcedCubes { .align_items(Alignment::Center); let shader = - shader(&self.cubes).width(Length::Fill).height(Length::Fill); + shader(&self.scene).width(Length::Fill).height(Length::Fill); container( column![shader, controls, vertical_space(20),] -- cgit From 34b5cb75ef9f97076dd9e306d8afb68058176883 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 14 Nov 2023 14:43:02 +0100 Subject: Remove `Default` implementation in `custom_shader` example --- examples/custom_shader/src/main.rs | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'examples/custom_shader/src/main.rs') diff --git a/examples/custom_shader/src/main.rs b/examples/custom_shader/src/main.rs index f90061d7..f4853507 100644 --- a/examples/custom_shader/src/main.rs +++ b/examples/custom_shader/src/main.rs @@ -28,15 +28,6 @@ struct IcedCubes { scene: Scene, } -impl Default for IcedCubes { - fn default() -> Self { - Self { - start: Instant::now(), - scene: Scene::new(), - } - } -} - #[derive(Debug, Clone)] enum Message { CubeAmountChanged(u32), @@ -53,7 +44,13 @@ impl Application for IcedCubes { type Flags = (); fn new(_flags: Self::Flags) -> (Self, Command) { - (IcedCubes::default(), Command::none()) + ( + Self { + start: Instant::now(), + scene: Scene::new(), + }, + Command::none(), + ) } fn title(&self) -> String { -- cgit From 811aa673e9e832ebe38bf56a087f32fdc7aba59c Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 14 Nov 2023 15:48:01 +0100 Subject: Improve module hierarchy of `custom_shader` example --- examples/custom_shader/src/main.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'examples/custom_shader/src/main.rs') diff --git a/examples/custom_shader/src/main.rs b/examples/custom_shader/src/main.rs index f4853507..2eb1ac4a 100644 --- a/examples/custom_shader/src/main.rs +++ b/examples/custom_shader/src/main.rs @@ -1,11 +1,6 @@ -mod camera; -mod pipeline; -mod primitive; mod scene; -use crate::camera::Camera; -use crate::pipeline::Pipeline; -use crate::scene::Scene; +use scene::Scene; use iced::executor; use iced::time::Instant; -- cgit From ab7dae554cac801aeed5d9aa4d3850d50be86263 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 28 Nov 2023 23:13:38 +0100 Subject: Provide actual bounds to `Shader` primitives ... and allow for proper translation and scissoring. --- examples/custom_shader/src/main.rs | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) (limited to 'examples/custom_shader/src/main.rs') diff --git a/examples/custom_shader/src/main.rs b/examples/custom_shader/src/main.rs index 2eb1ac4a..3bfa3a43 100644 --- a/examples/custom_shader/src/main.rs +++ b/examples/custom_shader/src/main.rs @@ -5,9 +5,7 @@ use scene::Scene; use iced::executor; use iced::time::Instant; use iced::widget::shader::wgpu; -use iced::widget::{ - checkbox, column, container, row, shader, slider, text, vertical_space, -}; +use iced::widget::{checkbox, column, container, row, shader, slider, text}; use iced::window; use iced::{ Alignment, Application, Color, Command, Element, Length, Renderer, @@ -138,21 +136,18 @@ impl Application for IcedCubes { let controls = column![top_controls, bottom_controls,] .spacing(10) + .padding(20) .align_items(Alignment::Center); let shader = shader(&self.scene).width(Length::Fill).height(Length::Fill); - container( - column![shader, controls, vertical_space(20),] - .spacing(40) - .align_items(Alignment::Center), - ) - .width(Length::Fill) - .height(Length::Fill) - .center_x() - .center_y() - .into() + container(column![shader, controls].align_items(Alignment::Center)) + .width(Length::Fill) + .height(Length::Fill) + .center_x() + .center_y() + .into() } fn subscription(&self) -> Subscription { -- cgit