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 = DrawMyStruct {
/// base: QuadIns::from_rect(rect),
/// field1: 0.0,
/// field2: 0.0,
/// };
/// cx.add_instances(&SHADER, &[s]);
/// ```
#[derive(Clone, 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.
));
}
"#
);
}