diff options
| author | 2020-04-28 04:41:09 +0200 | |
|---|---|---|
| committer | 2020-04-28 04:41:09 +0200 | |
| commit | e65585ae17bf2fae1bbad1cde839d6f767a29b82 (patch) | |
| tree | 49d36c227011d6aed771fa73bd66b26ac31a4142 /wgpu/src | |
| 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-- | 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 | 
4 files changed, 44 insertions, 25 deletions
| 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, | 
