1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
//! Drawing rectangles; by far the most commonly used `Draw*` struct.
use crate::*;
/// [`QuadIns`] is the basis for most draw structs.This renders a rectangle.
/// There are some default shaders available at [`QuadIns::SHADER`].
///
/// Example usage with your own struct:
///
/// ```
/// struct MyStruct {
/// pub base: QuadIns,
/// pub field1: f32,
/// pub field2: f32,
/// }
/// ```
///
/// And render using:
///
/// ```
/// let s = MyStruct {
/// base: QuadIns::from_rect(rect),
/// field1: 0.0,
/// field2: 0.0,
/// };
/// cx.add_instances(&SHADER, &[s]);
/// ```
#[derive(Clone, Copy, Default)]
#[repr(C)]
pub struct QuadIns {
/// The top-left corner position of the quad, in absolute coordinates.
pub rect_pos: Vec2,
/// The size of the quad.
pub rect_size: Vec2,
/// Z-index.
pub draw_depth: f32,
}
impl QuadIns {
#[must_use]
pub fn from_rect(rect: Rect) -> Self {
debug_assert!(!rect.size.x.is_nan());
debug_assert!(!rect.size.y.is_nan());
Self { rect_pos: rect.pos, rect_size: rect.size, ..Default::default() }
}
#[must_use]
pub fn with_draw_depth(mut self, draw_depth: f32) -> Self {
self.draw_depth = draw_depth;
self
}
#[must_use]
pub fn rect(&self) -> Rect {
Rect { pos: self.rect_pos, size: self.rect_size }
}
//ANCHOR: build_geom
pub fn build_geom() -> Geometry {
// First, represent each corner of the quad as a vertex,
// with each side having a length of 1.
let vertex_attributes = vec![
// top left vertex
vec2(0., 0.),
// top right vertex
vec2(1., 0.),
// bottom right vertex
vec2(1., 1.),
// bottom left vertex
vec2(0., 1.),
];
// Group the vertices into two triangles, right triangles
// on opposing corner coming together to share a hypotenuse.
let indices = vec![
// top-right triangle
[0, 1, 2],
// bottom-left triangle
[2, 3, 0],
];
Geometry::new(vertex_attributes, indices)
}
//ANCHOR_END: build_geom
/// Common [`Shader`] code for using [`QuadIns`].
pub const SHADER: CodeFragment = code_fragment!(
r#"
instance rect_pos: vec2;
instance rect_size: vec2;
instance draw_depth: float;
geometry geom: vec2;
varying pos: vec2;
fn scroll() -> vec2 {
return draw_scroll;
}
fn vertex() -> vec4 {
let scr = scroll();
let clipped: vec2 = clamp(
geom * rect_size + rect_pos - scr,
draw_clip.xy,
draw_clip.zw
);
pos = (clipped + scr - rect_pos) / rect_size;
// only pass the clipped position forward
return camera_projection * (camera_view * vec4(
clipped.x,
clipped.y,
draw_depth + draw_zbias,
1.
));
}
"#
);
}