diff options
Diffstat (limited to '')
-rw-r--r-- | wgpu/src/layer.rs | 94 | ||||
-rw-r--r-- | wgpu/src/layer/mesh.rs | 15 | ||||
-rw-r--r-- | wgpu/src/layer/quad.rs | 41 |
3 files changed, 118 insertions, 32 deletions
diff --git a/wgpu/src/layer.rs b/wgpu/src/layer.rs index 8af72b9d..b3ee4739 100644 --- a/wgpu/src/layer.rs +++ b/wgpu/src/layer.rs @@ -1,13 +1,13 @@ //! 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; -pub use quad::Quad; +use quad::Quad; pub use text::Text; use crate::core; @@ -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.color_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 {} |