bevy_feronia 0.8.2

Foliage/grass scattering tools and wind simulation shaders/materials that prioritize visual fidelity/artistic freedom, a declarative api and modularity.
Documentation
//! # bevy_feronia
//! [![License](https://img.shields.io/badge/license-MIT%2FApache-blue.svg)](https://github.com/NicoZweifel/bevy_feronia?tab=readme-ov-file#licensecreditsinspirationsreferences)
//! [![Crates.io](https://img.shields.io/crates/v/bevy_feronia.svg)](https://crates.io/crates/bevy_feronia)
//! [![Downloads](https://img.shields.io/crates/d/bevy_feronia.svg)](https://crates.io/crates/bevy_feronia)
//! [![Docs](https://docs.rs/bevy_feronia/badge.svg)](https://docs.rs/bevy_feronia/)
//! [![CI](https://github.com/bevyengine/bevy/workflows/CI/badge.svg)](https://github.com/NicoZweifel/bevy_feronia/actions)
//!
//! Environment scattering tools and shaders/materials that prioritize visual
//! fidelity/artistic freedom, a declarative API, and modularity.
//!
//! ## Who is this for?
//!
//! In the current stage, this is mostly for tinkerers and learners within the
//! [bevy](https://github.com/bevyengine/bevy) ecosystem, but the plan is to use this
//! for actual game dev eventually.
//!
//! **Warning: Early Development**
//! > This package is in early development and in an experimentation stage.
//! > I wouldn't personally use this in production quite yet, but it's getting closer
//! > to that state incrementally.
//!
//! ![Screenshot](https://github.com/user-attachments/assets/bf0ac5b4-affc-4360-8b3e-7492b5c07257)
//!
//! ## Getting started
//!
//! The possible use-cases are demonstrated in the `examples` directory.
//!
//! ### Setup
//!
//! The setup depends on the use-case, but a typical setup would look like this:
//!
//! ```rust,no_run
//! # use bevy::prelude::*;
//! # // Mocking plugins for documentation purposes
//! # struct MeshMaterialAssetBackendPlugin; impl Plugin for MeshMaterialAssetBackendPlugin { fn build(&self, app: &mut App) {} }
//! # struct SceneAssetBackendPlugin; impl Plugin for SceneAssetBackendPlugin { fn build(&self, app: &mut App) {} }
//! # struct ExtendedWindAffectedScatterPlugin; impl Plugin for ExtendedWindAffectedScatterPlugin { fn build(&self, app: &mut App) {} }
//! # let mut app = App::new();
//! app.add_plugins((
//!     MeshMaterialAssetBackendPlugin,
//!     // Or
//!     SceneAssetBackendPlugin,
//!     // ...
//!     ExtendedWindAffectedScatterPlugin
//! ));
//! ```
//!
//! The Scatter system needs to know when it can set up since it can depend on height mapping.
//! You need to insert the setup state at some point.
//!
//! **Note:** In complex setups that load assets and bake a height map, this can be
//! done after `Startup`.
//!
//! ```rust,ignore
//! app.insert_state(ScatterState::Setup)
//! ```
//!
//! Or:
//!
//! ```rust,ignore
//! ns_height_map.set(HeightMapState::Setup);
//! ns_scatter.set(ScatterState::Setup);
//! ```
//!
//! For chunking or GPU driven culling to work, `Center` and `CullComputeCamera` need to be inserted on the Camera:
//! ```rust
//! cmd.spawn((
//!     (Camera::default(), Camera3d::default()),
//!     (Center, CullComputeCamera),
//! // etc...
//! ```
//!
//! ### Defining layers
//!
//! A `ScatterItem`'s `LOD`s are grouped by `Name`. If the names end in `LOD_1` or `lod1` etc.,
//! the LOD suffix will be stripped from the name to match it to the other LODs of the asset.
//!
//! **Caution:** When defining multiple `ScatterItems` per `ScatterLayer` without names,
//! a different asset will render when `LODs` are changing, leading to visual bugs.
//!
//! ```rust,ignore
//! // Landscape
//! cmd.spawn((
//!     MeshMaterial3d(materials.add(StandardMaterial {
//!         base_color: GRAY_500.into(),
//!         ..default()
//!     })),
//!     Mesh3d(meshes.add(PlaneMeshBuilder::from_length(80.).build())),
//!     ScatterRoot::default(),
//!     // Scatter layers
//!     children![(
//!         // Make sure you use the correct `ScatterLayer` with the desired `ScatterLayerType`, e.g.,
//!         // Standard, Extended or Instanced Material/Layer.
//!         extension::scatter_layer("Wind Affected Layer"),
//!         // Scatter Options
//!         DistributionDensity(50.),
//!         InstanceJitter::default(),
//!         // You can define material options on the full layer here
//!         WindAffected,
//!         children![
//!             (
//!                 // Or overwrite on the item, e.g.,
//!                 // WindAffected,
//!                 //
//!                 // CAUTION: If you have multiple assets, all lods that belong to each other need to have the same name!
//!                 //
//!                 // You can have multiple assets in each layer; as long as all LODs have the same name, they will be matched correctly.
//!                 Name::new("Wind Affected Example Item"),
//!                 MeshMaterial3d(materials.add(StandardMaterial::default())),
//!                 Mesh3d(mesh.clone()),
//!             ),
//!             (
//!                 Name::new("Wind Affected Example Item"),
//!                 // We need to specify the LOD Level if it is not 0 (Highest level)
//!                 LevelOfDetail(1),
//!                 MeshMaterial3d(materials.add(StandardMaterial {
//!                     base_color: RED_500.into(),
//!                     ..default()
//!                 })),
//!                 Mesh3d(mesh.clone()),
//!             ),
//!         ]
//!     )]
//! ));
//! ```
//!
//! ### Scattering
//!
//! Now you can start scattering! 🌱 πŸƒ 🌿 πŸ€ 🌳 🌲 🌴 🌺
//!
//! ```rust,ignore
//! cmd.trigger(Scatter::<ExtendedWindAffectedMaterial>::new(*root));
//! ```
//!
//! **Note:** `ScatterLayers` and their `ScatterItems` of the same `ScatterType` are always
//! scattered in order, but layers of different `ScatterTypes` can be scattered at the same time.
//!
//! #### Ordered Scattering
//!
//! In complex scenes it is often required to scatter a complete hierarchy in order
//! (rocks β†’ trees/foliage β†’ grass).
//!
//! **Tip:** If an ordered scatter is still required, and you can't or don't want to scatter
//! in parallel, observers need to be used to chain the scattering of `ScatterTypes` in order.
//!
//! ```rust,ignore
//! fn scatter_on_keypress(
//!     mut cmd: Commands,
//!     keyboard_input: Res<ButtonInput<KeyCode>>,
//!     root: Single<Entity, With<ScatterRoot>>
//! ) {
//!     if !keyboard_input.just_pressed(KeyCode::Space) {
//!         return;
//!     };
//!
//!     // Scatter the rocks.
//!     cmd.trigger(Scatter::<StandardMaterial>::new(*root));
//! }
//!
//! fn scatter_extended(
//!     _: On<ScatterFinished<StandardMaterial>>,
//!     mut cmd: Commands,
//!     root: Single<Entity, With<ScatterRoot>>,
//! ) {
//!     // Scatter the foliage after the rocks.
//!     cmd.trigger(Scatter::<ExtendedWindAffectedMaterial>::new(*root));
//! }
//!
//! fn scatter_instanced(
//!     _: On<ScatterFinished<ExtendedWindAffectedMaterial>>,
//!     mut cmd: Commands,
//!     root: Single<Entity, With<ScatterRoot>>,
//! ) {
//!     // Scatter the grass last so it doesn't grow on occupied areas.
//!     cmd.trigger(Scatter::<InstancedWindAffectedMaterial>::new(*root));
//! }
//! ```
//!
//! ## Compatibility
//!
//! There are very experimental releases before 0.5.0, but I wouldn't use them.
//!
//! | bevy | bevy_feronia |
//! |------|--------------|
//! | 0.18 | 0.8+ |
//! | 0.17 | 0.7 |
//!
//! ## License/Credits/Inspirations/References
//!
//! The code is dual-licensed:
//!
//! - MIT License ([LICENSE-MIT](LICENSE-MIT) or [http://opensource.org/licenses/MIT](http://opensource.org/licenses/MIT))
//! - Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0))
//!
//! Feel free to copy the grass assets. All the other assets used in the examples are licensed assets.
//!
//! **Important:** If you intend to use them, make sure you comply with the license.
//!
//! - [Graswald](https://gscatter.com/gallery) for their amazing assets and [`GScatter`](https://gscatter.com/gscatter), which served as inspiration for the scatter tools.
//! - Sucker Punch Productions for their Procedural Grass and Wind simulation in 'Ghost of Tsushima' and [GDC Talks](https://www.youtube.com/watch?v=Ibe1JBF5i5Y).
//! - [bevy_procedural_grass](https://github.com/jadedbay/bevy_procedural_grass) by jadedbay
//! - [warbler_grass](https://github.com/EmiOnGit/warbler_grass) by EmiOnGit
//! - [GDC 2011 "Approximating Translucency"](https://www.gdcvault.com/play/1014538/Approximating-Translucency-for-a-Fast)
//! - [Blinn–Phong reflection model](https://en.wikipedia.org/wiki/Blinn%E2%80%93Phong_reflection_model)
//! - [All the other assets](https://github.com/villor/bevy_feronia/blob/main/assets/LICENSE)
//!
//! ## Alternatives
//!
//! - If you want a lower level scattering API, just for scattering and sampling there is also [`bevy_map_scatter`](https://github.com/morgenthum/map_scatter),
//!   which I might use eventually as well but for now I want this crate to achieve a vision.
//!
//! ## Roadmap
//!
//! A bunch of issues are already open, but some of the larger milestones could be:
//!
//! - Allow physics-based and other entities to impact the displacement/wind.
//! - Make use of compute shaders (Allow scattering on CPU and GPU, improve culling).
//! - Allow for multiple `ScatterRoots` when baking height maps.
pub mod asset;
pub mod backend;
pub mod chunking;
pub mod core;
pub mod density_map;
pub mod extension;
pub mod height_map;
pub mod instancing;
pub mod scatter;
pub mod utils;
pub mod wind;

pub mod prelude {
    pub use crate::asset::prelude::*;
    pub use crate::chunking::prelude::*;
    pub use crate::core::*;
    pub use crate::density_map::*;
    pub use crate::extension::prelude::*;
    pub use crate::height_map::prelude::*;
    pub use crate::instancing::prelude::*;
    pub use crate::scatter::prelude::*;
    pub use crate::utils::*;
    pub use crate::wind::prelude::*;
}