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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
//! Growing trees in the vertex shader.
//!
//! A tree with [`GpuGrowth`] is built once, at maturity, and uploaded once.
//! Every vertex carries which node it belongs to and where it sits relative to
//! that node's axis; each frame the CPU ages the skeleton ([`Skeleton::aged`])
//! and writes one small record per node into a storage buffer, and the vertex
//! shader (`growth.wesl`) moves every vertex to where the CPU path would have
//! put it. Nothing else is uploaded.
//!
//! [`Skeleton::aged`]: crate::Skeleton::aged
use App;
use ;
use *;
use ;
use ;
use Reflect;
use RenderApp;
use ShaderBuffer;
pub
pub use ;
/// Per-vertex: the node (`Node::id`) in the low word, the placement class
/// (low 8 bits) and a leaf's ordinal (the rest) in the high word.
pub const ATTRIBUTE_GROWTH_ID: MeshVertexAttribute =
new;
/// Per-vertex: the anchor on the node's axis in node lengths (`xyz`), and the
/// fraction along the piece or the trunk ring (`w`).
pub const ATTRIBUTE_GROWTH_AXIS: MeshVertexAttribute =
new;
/// Per-vertex: the offset from the anchor in units of the piece's scale (`xyz`),
/// and the trunk's unit root-ridge bulge (`w`).
pub const ATTRIBUTE_GROWTH_OFFSET: MeshVertexAttribute =
new;
/// Grow this tree in the vertex shader instead of rebuilding its meshes every
/// frame. Add it to an entity that has [`ProceduralTree`](crate::ProceduralTree)
/// and [`TreeAge`](crate::TreeAge) (and, to make the tree grow,
/// [`Growing`](crate::Growing)).
///
/// The mature tree is built once per change of [`ProceduralTree`](crate::ProceduralTree)
/// and uploaded once; each frame only a few kilobytes of per-node state are
/// written. A tree on this path costs the CPU microseconds per frame instead of
/// the 0.1-0.5 ms the CPU path takes, which makes growing a forest affordable.
///
/// Without this component a tree behaves exactly as before.
///
/// # What differs from the CPU path
///
/// The tree is the same at every age in its overall shape, but it is a
/// deformation of the mature mesh, not a rebuild:
///
/// - **Smoothing** ([`MeshParams::smooth_iterations`](crate::MeshParams::smooth_iterations))
/// is computed once, on the mature mesh, and deformed with the tree; the CPU
/// path smooths every age afresh.
/// - **Ring and side counts are the mature ones.** With
/// [`MeshParams::adaptive_resolution`](crate::MeshParams::adaptive_resolution)
/// a young thin branch keeps the sides of the mature branch.
/// - **Unborn parts have zero size**, instead of being absent; their triangles
/// collapse to a point and draw nothing.
/// - With [`FoliagePlacement::AllBranches`](crate::FoliagePlacement::AllBranches),
/// leaves keep their mature positions along a branch and the first ones appear
/// as it lengthens; the CPU path respaces them.
/// - Tip-cluster leaves that are mirrored away from the trunk
/// ([`FoliagePlacement::TipClusters`](crate::FoliagePlacement::TipClusters))
/// keep the mirroring the mature tree chose.
/// - Leaf normals and the shape of primary bases follow the mature tree.
/// - A growing pointed trunk ends in a flat cap; with smoothing on, the CPU
/// path softens that cap into a point while the tree is young.
/// - The [`Mesh`](bevy::mesh::Mesh) assets on the tree's children, and the
/// bounding box derived from them, are the **mature** tree at every age:
/// picking, physics and frustum culling see the grown size, not the current one.
/// - Growth does not feed motion vectors (temporal anti-aliasing sees a growing
/// branch as still).
///
/// # Platform support
///
/// The per-node state lives in a storage buffer, which WebGL2 does not have. On
/// such a device (and until the renderer is ready) the tree falls back to the
/// CPU path and a warning is logged once. The same happens if
/// [`FloraPlugin`](crate::FloraPlugin) was added before the renderer's plugins
/// (`DefaultPlugins`): it works in any order, but only registers
/// [`GrowthMaterial`] with a renderer that is already there, so add it after.
;
/// Whether this device can grow trees in the vertex shader. [`FloraPlugin`](crate::FloraPlugin)
/// sets it once the renderer is ready, from the device's limits: `true` where
/// the vertex stage can read a storage buffer, `false` on WebGL2. While it is
/// `false`, trees with [`GpuGrowth`] grow on the CPU. Insert it yourself only
/// where there is no renderer (a headless test).
;
/// Set when [`GrowthMaterial`] was registered with the renderer, which only
/// happens if the plugin was added after the renderer's plugins.
pub ;
/// Register what GPU growth needs: the support flag, and, when the renderer's
/// plugins have already been added, the material and its shaders.
///
/// Plugins may be added in any order. Added ahead of the renderer's (or of the
/// asset plugin), this registers nothing that needs them; [`finish`] covers the
/// asset types, and `GpuGrowthSupport` stays `false`, so trees grow on the CPU.
pub
/// Once every plugin is built, make sure the asset types the systems take exist
/// even if the plugin was added too early to register them.
pub
/// Register [`GrowthMaterial`] and [`ShaderBuffer`] as assets where the asset
/// plugin is present and nobody has yet (the renderer's plugins do it when they
/// are).