diff options
author | 2024-05-03 07:31:34 +0200 | |
---|---|---|
committer | 2024-05-03 07:31:34 +0200 | |
commit | 1cefe6be210cdae8c6769673e8d23c6781a988f1 (patch) | |
tree | 7d4a383412e6bd69d0cc1b32f996ba7cf6ef892e /wgpu | |
parent | fe240a93aacd15bd3fa75876054753a53bda9054 (diff) | |
parent | 4010e3983d40e24a5d7b590d8fec9801651199ce (diff) | |
download | iced-1cefe6be210cdae8c6769673e8d23c6781a988f1.tar.gz iced-1cefe6be210cdae8c6769673e8d23c6781a988f1.tar.bz2 iced-1cefe6be210cdae8c6769673e8d23c6781a988f1.zip |
Merge pull request #2334 from DKolter/image-rotation
Adding feature: Image rotation
Diffstat (limited to 'wgpu')
-rw-r--r-- | wgpu/src/image/mod.rs | 41 | ||||
-rw-r--r-- | wgpu/src/layer.rs | 9 | ||||
-rw-r--r-- | wgpu/src/lib.rs | 16 | ||||
-rw-r--r-- | wgpu/src/shader/image.wgsl | 32 |
4 files changed, 76 insertions, 22 deletions
diff --git a/wgpu/src/image/mod.rs b/wgpu/src/image/mod.rs index 8b831a3c..285eb2f6 100644 --- a/wgpu/src/image/mod.rs +++ b/wgpu/src/image/mod.rs @@ -135,14 +135,18 @@ impl Pipeline { attributes: &wgpu::vertex_attr_array!( // Position 0 => Float32x2, - // Scale + // Center 1 => Float32x2, - // Atlas position + // Image size 2 => Float32x2, + // Rotation + 3 => Float32, + // Atlas position + 4 => Float32x2, // Atlas scale - 3 => Float32x2, + 5 => Float32x2, // Layer - 4 => Sint32, + 6 => Sint32, ), }], }, @@ -224,6 +228,7 @@ impl Pipeline { handle, filter_method, bounds, + rotation, } => { if let Some(atlas_entry) = cache.upload_raster(device, encoder, handle) @@ -231,6 +236,7 @@ impl Pipeline { add_instances( [bounds.x, bounds.y], [bounds.width, bounds.height], + f32::from(*rotation), atlas_entry, match filter_method { crate::core::image::FilterMethod::Nearest => { @@ -251,6 +257,7 @@ impl Pipeline { handle, color, bounds, + rotation, } => { let size = [bounds.width, bounds.height]; @@ -260,6 +267,7 @@ impl Pipeline { add_instances( [bounds.x, bounds.y], size, + f32::from(*rotation), atlas_entry, nearest_instances, ); @@ -487,7 +495,9 @@ impl Data { #[derive(Debug, Clone, Copy, Zeroable, Pod)] struct Instance { _position: [f32; 2], + _center: [f32; 2], _size: [f32; 2], + _rotation: f32, _position_in_atlas: [f32; 2], _size_in_atlas: [f32; 2], _layer: u32, @@ -506,12 +516,25 @@ struct Uniforms { fn add_instances( image_position: [f32; 2], image_size: [f32; 2], + rotation: f32, entry: &atlas::Entry, instances: &mut Vec<Instance>, ) { + let center = [ + image_position[0] + image_size[0] / 2.0, + image_position[1] + image_size[1] / 2.0, + ]; + match entry { atlas::Entry::Contiguous(allocation) => { - add_instance(image_position, image_size, allocation, instances); + add_instance( + image_position, + center, + image_size, + rotation, + allocation, + instances, + ); } atlas::Entry::Fragmented { fragments, size } => { let scaling_x = image_size[0] / size.width as f32; @@ -537,7 +560,9 @@ fn add_instances( fragment_height as f32 * scaling_y, ]; - add_instance(position, size, allocation, instances); + add_instance( + position, center, size, rotation, allocation, instances, + ); } } } @@ -546,7 +571,9 @@ fn add_instances( #[inline] fn add_instance( position: [f32; 2], + center: [f32; 2], size: [f32; 2], + rotation: f32, allocation: &atlas::Allocation, instances: &mut Vec<Instance>, ) { @@ -556,7 +583,9 @@ fn add_instance( let instance = Instance { _position: position, + _center: center, _size: size, + _rotation: rotation, _position_in_atlas: [ (x as f32 + 0.5) / atlas::SIZE as f32, (y as f32 + 0.5) / atlas::SIZE as f32, diff --git a/wgpu/src/layer.rs b/wgpu/src/layer.rs index 9526c5a8..e0242c59 100644 --- a/wgpu/src/layer.rs +++ b/wgpu/src/layer.rs @@ -1,5 +1,6 @@ -use crate::core::renderer; -use crate::core::{Background, Color, Point, Rectangle, Transformation}; +use crate::core::{ + renderer, Background, Color, Point, Radians, Rectangle, Transformation, +}; use crate::graphics; use crate::graphics::color; use crate::graphics::layer; @@ -117,11 +118,13 @@ impl Layer { filter_method: crate::core::image::FilterMethod, bounds: Rectangle, transformation: Transformation, + rotation: Radians, ) { let image = Image::Raster { handle, filter_method, bounds: bounds * transformation, + rotation, }; self.images.push(image); @@ -133,11 +136,13 @@ impl Layer { color: Option<Color>, bounds: Rectangle, transformation: Transformation, + rotation: Radians, ) { let svg = Image::Vector { handle, color, bounds: bounds * transformation, + rotation, }; self.images.push(svg); diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index 178522de..6920067b 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -61,7 +61,8 @@ pub use settings::Settings; pub use geometry::Geometry; use crate::core::{ - Background, Color, Font, Pixels, Point, Rectangle, Size, Transformation, + Background, Color, Font, Pixels, Point, Radians, Rectangle, Size, + Transformation, Vector, }; use crate::graphics::text::{Editor, Paragraph}; use crate::graphics::Viewport; @@ -378,7 +379,6 @@ impl Renderer { use crate::core::alignment; use crate::core::text::Renderer as _; use crate::core::Renderer as _; - use crate::core::Vector; self.with_layer( Rectangle::with_size(viewport.logical_size()), @@ -517,9 +517,16 @@ impl core::image::Renderer for Renderer { handle: Self::Handle, filter_method: core::image::FilterMethod, bounds: Rectangle, + rotation: Radians, ) { let (layer, transformation) = self.layers.current_mut(); - layer.draw_image(handle, filter_method, bounds, transformation); + layer.draw_image( + handle, + filter_method, + bounds, + transformation, + rotation, + ); } } @@ -534,9 +541,10 @@ impl core::svg::Renderer for Renderer { handle: core::svg::Handle, color_filter: Option<Color>, bounds: Rectangle, + rotation: Radians, ) { let (layer, transformation) = self.layers.current_mut(); - layer.draw_svg(handle, color_filter, bounds, transformation); + layer.draw_svg(handle, color_filter, bounds, transformation, rotation); } } diff --git a/wgpu/src/shader/image.wgsl b/wgpu/src/shader/image.wgsl index 7b2e5238..71bf939c 100644 --- a/wgpu/src/shader/image.wgsl +++ b/wgpu/src/shader/image.wgsl @@ -9,10 +9,12 @@ struct Globals { struct VertexInput { @builtin(vertex_index) vertex_index: u32, @location(0) pos: vec2<f32>, - @location(1) scale: vec2<f32>, - @location(2) atlas_pos: vec2<f32>, - @location(3) atlas_scale: vec2<f32>, - @location(4) layer: i32, + @location(1) center: vec2<f32>, + @location(2) scale: vec2<f32>, + @location(3) rotation: f32, + @location(4) atlas_pos: vec2<f32>, + @location(5) atlas_scale: vec2<f32>, + @location(6) layer: i32, } struct VertexOutput { @@ -25,24 +27,34 @@ struct VertexOutput { fn vs_main(input: VertexInput) -> VertexOutput { var out: VertexOutput; - let v_pos = vertex_position(input.vertex_index); + // Generate a vertex position in the range [0, 1] from the vertex index. + var v_pos = vertex_position(input.vertex_index); + // Map the vertex position to the atlas texture. out.uv = vec2<f32>(v_pos * input.atlas_scale + input.atlas_pos); out.layer = f32(input.layer); - var transform: mat4x4<f32> = mat4x4<f32>( - vec4<f32>(input.scale.x, 0.0, 0.0, 0.0), - vec4<f32>(0.0, input.scale.y, 0.0, 0.0), + // Calculate the vertex position and move the center to the origin + v_pos = input.pos + v_pos * input.scale - input.center; + + // Apply the rotation around the center of the image + let cos_rot = cos(input.rotation); + let sin_rot = sin(input.rotation); + let rotate = mat4x4<f32>( + vec4<f32>(cos_rot, sin_rot, 0.0, 0.0), + vec4<f32>(-sin_rot, cos_rot, 0.0, 0.0), vec4<f32>(0.0, 0.0, 1.0, 0.0), - vec4<f32>(input.pos, 0.0, 1.0) + vec4<f32>(0.0, 0.0, 0.0, 1.0) ); - out.position = globals.transform * transform * vec4<f32>(v_pos, 0.0, 1.0); + // Calculate the final position of the vertex + out.position = globals.transform * (vec4<f32>(input.center, 0.0, 0.0) + rotate * vec4<f32>(v_pos, 0.0, 1.0)); return out; } @fragment fn fs_main(input: VertexOutput) -> @location(0) vec4<f32> { + // Sample the texture at the given UV coordinate and layer. return textureSample(u_texture, u_sampler, input.uv, i32(input.layer)); } |