Thanks to visit codestin.com
Credit goes to Github.com

Skip to content

Environment scattering tools and shaders/materials that prioritize visual fidelity/artistic freedom, a declarative API and modularity.

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-Apache-2.0
MIT
LICENSE-MIT
Notifications You must be signed in to change notification settings

NicoZweifel/bevy_feronia

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

bevy_feronia

License Crates.io Downloads Docs CI

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 ecosystem, but I am planning to use this for actual game dev myself eventually.

Caution

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 2025-11-28 144933

Getting started

cargo add bevy_feronia

The possible use-cases are demonstrated in the examples

Setup

The setup depends on the use-case, but a typical setup would look like something like this:

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 after the Startup.

app.insert_state(ScatterState::Setup)

Or

ns_height_map.set(HeightMapState::Setup);
ns_scatter.set(ScatterState::Setup);

Defining layers

A ScatterItem's LODs 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.

// 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! ๐ŸŒฑ ๐Ÿƒ ๐ŸŒฟ ๐Ÿ€ ๐ŸŒณ ๐ŸŒฒ ๐ŸŒด ๐ŸŒบ

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.

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.17 0.5

License/Credits/Inspirations/References

The code is dual-licensed:

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.

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 (otherwise it should work... probably but it isn't tested yet)

About

Environment scattering tools and shaders/materials that prioritize visual fidelity/artistic freedom, a declarative API and modularity.

Topics

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-Apache-2.0
MIT
LICENSE-MIT

Contributing

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •