diff options
Diffstat (limited to '')
| -rw-r--r-- | wgpu/src/layer.rs | 92 | ||||
| -rw-r--r-- | wgpu/src/layer/mesh.rs | 15 | ||||
| -rw-r--r-- | wgpu/src/layer/quad.rs | 41 | 
3 files changed, 117 insertions, 31 deletions
| diff --git a/wgpu/src/layer.rs b/wgpu/src/layer.rs index 8af72b9d..980d807b 100644 --- a/wgpu/src/layer.rs +++ b/wgpu/src/layer.rs @@ -1,9 +1,9 @@  //! Organize rendering primitives into a flattened list of layers.  mod image; -mod quad;  mod text;  pub mod mesh; +pub mod quad;  pub use image::Image;  pub use mesh::Mesh; @@ -22,7 +22,7 @@ pub struct Layer<'a> {      pub bounds: Rectangle,      /// The quads of the [`Layer`]. -    pub quads: Vec<Quad>, +    pub quads: Quads,      /// The triangle meshes of the [`Layer`].      pub meshes: Vec<Mesh<'a>>, @@ -34,12 +34,29 @@ pub struct Layer<'a> {      pub images: Vec<Image>,  } +/// The quads of the [`Layer`]. +#[derive(Default, Debug)] +pub struct Quads { +    /// The solid quads of the [`Layer`]. +    pub solids: Vec<quad::Solid>, + +    /// The gradient quads of the [`Layer`]. +    pub gradients: Vec<quad::Gradient>, +} + +impl Quads { +    /// Returns true if there are no quads of any type in [`Quads`]. +    pub fn is_empty(&self) -> bool { +        self.solids.is_empty() && self.gradients.is_empty() +    } +} +  impl<'a> Layer<'a> {      /// Creates a new [`Layer`] with the given clipping bounds.      pub fn new(bounds: Rectangle) -> Self {          Self {              bounds, -            quads: Vec::new(), +            quads: Quads::default(),              meshes: Vec::new(),              text: Vec::new(),              images: Vec::new(), @@ -145,20 +162,39 @@ impl<'a> Layer<'a> {              } => {                  let layer = &mut layers[current_layer]; -                // TODO: Move some of these computations to the GPU (?) -                layer.quads.push(Quad { +                let quad = Quad {                      position: [                          bounds.x + translation.x,                          bounds.y + translation.y,                      ],                      size: [bounds.width, bounds.height], -                    color: match background { -                        Background::Color(color) => color.into_linear(), -                    }, +                    border_color: border_color.into_linear(),                      border_radius: *border_radius,                      border_width: *border_width, -                    border_color: border_color.into_linear(), -                }); +                }; + +                match background { +                    Background::Color(color) => { +                        layer.quads.solids.push(quad::Solid { +                            color: color.into_linear(), +                            quad, +                        }); +                    } +                    Background::Gradient(gradient) => { +                        let quad = quad::Gradient { +                            gradient: pack_gradient( +                                gradient, +                                Rectangle::new( +                                    quad.position.into(), +                                    quad.size.into(), +                                ), +                            ), +                            quad, +                        }; + +                        layer.quads.gradients.push(quad); +                    } +                };              }              Primitive::Image { handle, bounds } => {                  let layer = &mut layers[current_layer]; @@ -198,11 +234,7 @@ impl<'a> Layer<'a> {                      });                  }              } -            Primitive::GradientMesh { -                buffers, -                size, -                gradient, -            } => { +            Primitive::GradientMesh { buffers, size } => {                  let layer = &mut layers[current_layer];                  let bounds = Rectangle::new( @@ -216,7 +248,6 @@ impl<'a> Layer<'a> {                          origin: Point::new(translation.x, translation.y),                          buffers,                          clip_bounds, -                        gradient,                      });                  }              } @@ -279,3 +310,32 @@ impl<'a> Layer<'a> {          }      }  } + +/// Packs the [`Gradient`] for use in shader code. +fn pack_gradient(gradient: &core::Gradient, bounds: Rectangle) -> [f32; 44] { +    match gradient { +        core::Gradient::Linear(linear) => { +            let mut pack: [f32; 44] = [0.0; 44]; + +            for (index, stop) in linear.stops.iter().enumerate() { +                let [r, g, b, a] = +                    stop.map_or(Color::default(), |s| s.color).into_linear(); + +                pack[index * 4] = r; +                pack[(index * 4) + 1] = g; +                pack[(index * 4) + 2] = b; +                pack[(index * 4) + 3] = a; +                pack[32 + index] = stop.map_or(2.0, |s| s.offset); +            } + +            let (start, end) = linear.angle.to_distance(&bounds); + +            pack[40] = start.x; +            pack[41] = start.y; +            pack[42] = end.x; +            pack[43] = end.y; + +            pack +        } +    } +} diff --git a/wgpu/src/layer/mesh.rs b/wgpu/src/layer/mesh.rs index 9dd14391..b7dd9a0b 100644 --- a/wgpu/src/layer/mesh.rs +++ b/wgpu/src/layer/mesh.rs @@ -1,5 +1,5 @@  //! A collection of triangle primitives. -use crate::core::{Gradient, Point, Rectangle}; +use crate::core::{Point, Rectangle};  use crate::graphics::primitive;  /// A mesh of triangles. @@ -22,13 +22,10 @@ pub enum Mesh<'a> {          origin: Point,          /// The vertex and index buffers of the [`Mesh`]. -        buffers: &'a primitive::Mesh2D<primitive::Vertex2D>, +        buffers: &'a primitive::Mesh2D<primitive::GradientVertex2D>,          /// The clipping bounds of the [`Mesh`].          clip_bounds: Rectangle<f32>, - -        /// The gradient to apply to the [`Mesh`]. -        gradient: &'a Gradient,      },  } @@ -65,9 +62,15 @@ pub struct AttributeCount {      /// The total amount of solid vertices.      pub solid_vertices: usize, +    /// The total amount of solid meshes. +    pub solids: usize, +      /// The total amount of gradient vertices.      pub gradient_vertices: usize, +    /// The total amount of gradient meshes. +    pub gradients: usize, +      /// The total amount of indices.      pub indices: usize,  } @@ -79,10 +82,12 @@ pub fn attribute_count_of<'a>(meshes: &'a [Mesh<'a>]) -> AttributeCount {          .fold(AttributeCount::default(), |mut count, mesh| {              match mesh {                  Mesh::Solid { buffers, .. } => { +                    count.solids += 1;                      count.solid_vertices += buffers.vertices.len();                      count.indices += buffers.indices.len();                  }                  Mesh::Gradient { buffers, .. } => { +                    count.gradients += 1;                      count.gradient_vertices += buffers.vertices.len();                      count.indices += buffers.indices.len();                  } diff --git a/wgpu/src/layer/quad.rs b/wgpu/src/layer/quad.rs index 0d8bde9d..9913cfe0 100644 --- a/wgpu/src/layer/quad.rs +++ b/wgpu/src/layer/quad.rs @@ -1,7 +1,9 @@ -/// A colored rectangle with a border. -/// -/// This type can be directly uploaded to GPU memory. -#[derive(Debug, Clone, Copy)] +//! A rectangle with certain styled properties. + +use bytemuck::{Pod, Zeroable}; + +/// The properties of a quad. +#[derive(Clone, Copy, Debug, Pod, Zeroable)]  #[repr(C)]  pub struct Quad {      /// The position of the [`Quad`]. @@ -10,21 +12,40 @@ pub struct Quad {      /// The size of the [`Quad`].      pub size: [f32; 2], -    /// The color of the [`Quad`], in __linear RGB__. -    pub color: [f32; 4], -      /// The border color of the [`Quad`], in __linear RGB__.      pub border_color: [f32; 4], -    /// The border radius of the [`Quad`]. +    /// The border radii of the [`Quad`].      pub border_radius: [f32; 4],      /// The border width of the [`Quad`].      pub border_width: f32,  } +/// A quad filled with a solid color. +#[derive(Clone, Copy, Debug, Pod, Zeroable)] +#[repr(C)] +pub struct Solid { +    /// The background color data of the quad. +    pub color: [f32; 4], + +    /// The [`Quad`] data of the [`Solid`]. +    pub quad: Quad, +} + +/// A quad filled with interpolated colors. +#[derive(Clone, Copy, Debug)] +#[repr(C)] +pub struct Gradient { +    /// The background gradient data of the quad. +    pub gradient: [f32; 44], + +    /// The [`Quad`] data of the [`Gradient`]. +    pub quad: Quad, +} +  #[allow(unsafe_code)] -unsafe impl bytemuck::Zeroable for Quad {} +unsafe impl Pod for Gradient {}  #[allow(unsafe_code)] -unsafe impl bytemuck::Pod for Quad {} +unsafe impl Zeroable for Gradient {} | 
