diff options
author | 2020-04-28 04:41:09 +0200 | |
---|---|---|
committer | 2020-04-28 04:41:09 +0200 | |
commit | e65585ae17bf2fae1bbad1cde839d6f767a29b82 (patch) | |
tree | 49d36c227011d6aed771fa73bd66b26ac31a4142 | |
parent | 69c60d372c18c20856f733efd337ac302b7de926 (diff) | |
download | iced-e65585ae17bf2fae1bbad1cde839d6f767a29b82.tar.gz iced-e65585ae17bf2fae1bbad1cde839d6f767a29b82.tar.bz2 iced-e65585ae17bf2fae1bbad1cde839d6f767a29b82.zip |
Clip and cull `Mesh2D` primitives in `iced_wgpu`
Diffstat (limited to '')
-rw-r--r-- | examples/geometry/src/main.rs | 1 | ||||
-rw-r--r-- | wgpu/src/primitive.rs | 9 | ||||
-rw-r--r-- | wgpu/src/renderer.rs | 36 | ||||
-rw-r--r-- | wgpu/src/triangle.rs | 23 | ||||
-rw-r--r-- | wgpu/src/widget/canvas/frame.rs | 1 |
5 files changed, 45 insertions, 25 deletions
diff --git a/examples/geometry/src/main.rs b/examples/geometry/src/main.rs index 63e1bacd..795cac27 100644 --- a/examples/geometry/src/main.rs +++ b/examples/geometry/src/main.rs @@ -88,6 +88,7 @@ mod rainbow { Primitive::Translate { translation: Vector::new(b.x, b.y), content: Box::new(Primitive::Mesh2D { + size: b.size(), buffers: Mesh2D { vertices: vec![ Vertex2D { diff --git a/wgpu/src/primitive.rs b/wgpu/src/primitive.rs index e9c0bf46..e73227ef 100644 --- a/wgpu/src/primitive.rs +++ b/wgpu/src/primitive.rs @@ -1,5 +1,5 @@ use iced_native::{ - image, svg, Background, Color, Font, HorizontalAlignment, Rectangle, + image, svg, Background, Color, Font, HorizontalAlignment, Rectangle, Size, Vector, VerticalAlignment, }; @@ -72,7 +72,7 @@ pub enum Primitive { }, /// A primitive that applies a translation Translate { - /// The top-left coordinate of the mesh + /// The translation vector translation: Vector, /// The primitive to translate @@ -82,6 +82,11 @@ pub enum Primitive { /// /// It can be used to render many kinds of geometry freely. Mesh2D { + /// The size of the drawable region of the mesh. + /// + /// Any geometry that falls out of this region will be clipped. + size: Size, + /// The vertex and index buffers of the mesh buffers: triangle::Mesh2D, }, diff --git a/wgpu/src/renderer.rs b/wgpu/src/renderer.rs index e93532bc..5c38ce61 100644 --- a/wgpu/src/renderer.rs +++ b/wgpu/src/renderer.rs @@ -29,7 +29,7 @@ pub struct Renderer { struct Layer<'a> { bounds: Rectangle<u32>, quads: Vec<Quad>, - meshes: Vec<(Vector, &'a triangle::Mesh2D)>, + meshes: Vec<(Vector, Rectangle<u32>, &'a triangle::Mesh2D)>, text: Vec<wgpu_glyph::Section<'a>>, #[cfg(any(feature = "image", feature = "svg"))] @@ -48,6 +48,12 @@ impl<'a> Layer<'a> { images: Vec::new(), } } + + pub fn intersection(&self, rectangle: Rectangle) -> Option<Rectangle<u32>> { + let layer_bounds: Rectangle<f32> = self.bounds.into(); + + layer_bounds.intersection(&rectangle).map(Into::into) + } } impl Renderer { @@ -214,10 +220,20 @@ impl Renderer { border_color: border_color.into_linear(), }); } - Primitive::Mesh2D { buffers } => { + Primitive::Mesh2D { size, buffers } => { let layer = layers.last_mut().unwrap(); - layer.meshes.push((translation, buffers)); + // Only draw visible content + if let Some(clip_bounds) = layer.intersection(Rectangle::new( + Point::new(translation.x, translation.y), + *size, + )) { + layer.meshes.push(( + translation, + clip_bounds.into(), + buffers, + )); + } } Primitive::Clip { bounds, @@ -226,16 +242,10 @@ impl Renderer { } => { let layer = layers.last_mut().unwrap(); - let layer_bounds: Rectangle<f32> = layer.bounds.into(); - - let clip = Rectangle { - x: bounds.x + translation.x, - y: bounds.y + translation.y, - ..*bounds - }; - // Only draw visible content - if let Some(clip_bounds) = layer_bounds.intersection(&clip) { + if let Some(clip_bounds) = + layer.intersection(*bounds + translation) + { let clip_layer = Layer::new(clip_bounds.into()); let new_layer = Layer::new(layer.bounds); @@ -356,8 +366,8 @@ impl Renderer { target_width, target_height, scaled, + scale_factor, &layer.meshes, - bounds, ); } diff --git a/wgpu/src/triangle.rs b/wgpu/src/triangle.rs index b58cc03c..246dc7ce 100644 --- a/wgpu/src/triangle.rs +++ b/wgpu/src/triangle.rs @@ -201,15 +201,15 @@ impl Pipeline { target_width: u32, target_height: u32, transformation: Transformation, - meshes: &[(Vector, &Mesh2D)], - bounds: Rectangle<u32>, + scale_factor: f32, + meshes: &[(Vector, Rectangle<u32>, &Mesh2D)], ) { // This looks a bit crazy, but we are just counting how many vertices // and indices we will need to handle. // TODO: Improve readability let (total_vertices, total_indices) = meshes .iter() - .map(|(_, mesh)| (mesh.vertices.len(), mesh.indices.len())) + .map(|(_, _, mesh)| (mesh.vertices.len(), mesh.indices.len())) .fold((0, 0), |(total_v, total_i), (v, i)| { (total_v + v, total_i + i) }); @@ -230,7 +230,7 @@ impl Pipeline { let mut last_index = 0; // We upload everything upfront - for (origin, mesh) in meshes { + for (origin, _, mesh) in meshes { let transform = (transformation * Transformation::translate(origin.x, origin.y)) .into(); @@ -316,16 +316,19 @@ impl Pipeline { }); render_pass.set_pipeline(&self.pipeline); - render_pass.set_scissor_rect( - bounds.x, - bounds.y, - bounds.width, - bounds.height, - ); for (i, (vertex_offset, index_offset, indices)) in offsets.into_iter().enumerate() { + let bounds = meshes[i].1 * scale_factor; + + render_pass.set_scissor_rect( + bounds.x, + bounds.y, + bounds.width, + bounds.height, + ); + render_pass.set_bind_group( 0, &self.constants, diff --git a/wgpu/src/widget/canvas/frame.rs b/wgpu/src/widget/canvas/frame.rs index 8623ce4d..1c4a038a 100644 --- a/wgpu/src/widget/canvas/frame.rs +++ b/wgpu/src/widget/canvas/frame.rs @@ -267,6 +267,7 @@ impl Frame { pub fn into_geometry(mut self) -> Geometry { if !self.buffers.indices.is_empty() { self.primitives.push(Primitive::Mesh2D { + size: self.size, buffers: triangle::Mesh2D { vertices: self.buffers.vertices, indices: self.buffers.indices, |