summaryrefslogtreecommitdiffstats
path: root/wgpu/src/layer
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--wgpu/src/layer.rs94
-rw-r--r--wgpu/src/layer/mesh.rs15
-rw-r--r--wgpu/src/layer/quad.rs41
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 {}