diff --git a/content/news/2023-03-04-bevy-0.10/alpha_mask_shadows.png b/content/news/2023-03-04-bevy-0.10/alpha_mask_shadows.png new file mode 100644 index 0000000000..bff75c90ae Binary files /dev/null and b/content/news/2023-03-04-bevy-0.10/alpha_mask_shadows.png differ diff --git a/content/news/2023-03-04-bevy-0.10/android emulator.png b/content/news/2023-03-04-bevy-0.10/android emulator.png new file mode 100644 index 0000000000..f1557a3f0d Binary files /dev/null and b/content/news/2023-03-04-bevy-0.10/android emulator.png differ diff --git a/content/news/2023-03-04-bevy-0.10/animation_transition.mp4 b/content/news/2023-03-04-bevy-0.10/animation_transition.mp4 new file mode 100644 index 0000000000..cf78f7b9a2 Binary files /dev/null and b/content/news/2023-03-04-bevy-0.10/animation_transition.mp4 differ diff --git a/content/news/2023-03-04-bevy-0.10/atmospheric-fog.png b/content/news/2023-03-04-bevy-0.10/atmospheric-fog.png new file mode 100644 index 0000000000..ba9643d901 Binary files /dev/null and b/content/news/2023-03-04-bevy-0.10/atmospheric-fog.png differ diff --git a/content/news/2023-03-04-bevy-0.10/blend-modes.png b/content/news/2023-03-04-bevy-0.10/blend-modes.png new file mode 100644 index 0000000000..544cf22486 Binary files /dev/null and b/content/news/2023-03-04-bevy-0.10/blend-modes.png differ diff --git a/content/news/2023-03-04-bevy-0.10/bloom_example.png b/content/news/2023-03-04-bevy-0.10/bloom_example.png new file mode 100644 index 0000000000..3fbd236514 Binary files /dev/null and b/content/news/2023-03-04-bevy-0.10/bloom_example.png differ diff --git a/content/news/2023-03-04-bevy-0.10/cubic_curves.mp4 b/content/news/2023-03-04-bevy-0.10/cubic_curves.mp4 new file mode 100644 index 0000000000..4a6e8da8c4 Binary files /dev/null and b/content/news/2023-03-04-bevy-0.10/cubic_curves.mp4 differ diff --git a/content/news/2023-03-04-bevy-0.10/demo-ruins.mp4 b/content/news/2023-03-04-bevy-0.10/demo-ruins.mp4 new file mode 100644 index 0000000000..7ade5f5a0b Binary files /dev/null and b/content/news/2023-03-04-bevy-0.10/demo-ruins.mp4 differ diff --git a/content/news/2023-03-04-bevy-0.10/edge_detection.png b/content/news/2023-03-04-bevy-0.10/edge_detection.png new file mode 100644 index 0000000000..04aca55c8f Binary files /dev/null and b/content/news/2023-03-04-bevy-0.10/edge_detection.png differ diff --git a/content/news/2023-03-04-bevy-0.10/edge_detection_prepass.png b/content/news/2023-03-04-bevy-0.10/edge_detection_prepass.png new file mode 100644 index 0000000000..9051a992b1 Binary files /dev/null and b/content/news/2023-03-04-bevy-0.10/edge_detection_prepass.png differ diff --git a/content/news/2023-03-04-bevy-0.10/env_map_after.png b/content/news/2023-03-04-bevy-0.10/env_map_after.png new file mode 100644 index 0000000000..9c0904692b Binary files /dev/null and b/content/news/2023-03-04-bevy-0.10/env_map_after.png differ diff --git a/content/news/2023-03-04-bevy-0.10/env_map_before.png b/content/news/2023-03-04-bevy-0.10/env_map_before.png new file mode 100644 index 0000000000..b9a3dbda71 Binary files /dev/null and b/content/news/2023-03-04-bevy-0.10/env_map_before.png differ diff --git a/content/news/2023-03-04-bevy-0.10/exposure_005.png b/content/news/2023-03-04-bevy-0.10/exposure_005.png new file mode 100644 index 0000000000..af0aa2fbe0 Binary files /dev/null and b/content/news/2023-03-04-bevy-0.10/exposure_005.png differ diff --git a/content/news/2023-03-04-bevy-0.10/exposure_225.png b/content/news/2023-03-04-bevy-0.10/exposure_225.png new file mode 100644 index 0000000000..7568e77a1b Binary files /dev/null and b/content/news/2023-03-04-bevy-0.10/exposure_225.png differ diff --git a/content/news/2023-03-04-bevy-0.10/fog.png b/content/news/2023-03-04-bevy-0.10/fog.png new file mode 100644 index 0000000000..a6b8bfbebc Binary files /dev/null and b/content/news/2023-03-04-bevy-0.10/fog.png differ diff --git a/content/news/2023-03-04-bevy-0.10/force_field.mp4 b/content/news/2023-03-04-bevy-0.10/force_field.mp4 new file mode 100644 index 0000000000..7f4f662ad2 Binary files /dev/null and b/content/news/2023-03-04-bevy-0.10/force_field.mp4 differ diff --git a/content/news/2023-03-04-bevy-0.10/ime.mp4 b/content/news/2023-03-04-bevy-0.10/ime.mp4 new file mode 100644 index 0000000000..fe911b4a97 Binary files /dev/null and b/content/news/2023-03-04-bevy-0.10/ime.mp4 differ diff --git a/content/news/2023-03-04-bevy-0.10/index.md b/content/news/2023-03-04-bevy-0.10/index.md new file mode 100644 index 0000000000..5f1bdd4803 --- /dev/null +++ b/content/news/2023-03-04-bevy-0.10/index.md @@ -0,0 +1,2886 @@ ++++ +title = "Bevy 0.10" +date = 2023-03-04 +[extra] +author = "Bevy Contributors" +image = "ruins.png" +show_image = true +image_subtitle = "Ruins scene illustrating Bevy's new material blend modes and fog. Based on original scene by Casey Hardy (CC Attribution)" +image_subtitle_link = "https://github.com/coreh/bevy-demo-ruins" ++++ + +Thanks to **173** contributors, **689** pull requests, community reviewers, and our [**generous sponsors**](/community/donate), I'm happy to announce the **Bevy 0.10** release on [crates.io](https://crates.io/crates/bevy)! + +For those who don't know, Bevy is a refreshingly simple data-driven game engine built in Rust. You can check out our [Quick Start Guide](/learn/book/getting-started/) to try it today. It's free and open source forever! You can grab the full [source code](https://github.com/bevyengine/bevy) on GitHub. Check out [Bevy Assets](https://bevyengine.org/assets) for a collection of community-developed plugins, games, and learning resources. + +To update an existing Bevy App or Plugin to **Bevy 0.10**, check out our [0.9 to 0.10 Migration Guide](/learn/book/migration-guides/0.9-0.10/). + +Since our last release a few months ago we've added a _ton_ of new features, bug fixes, and quality of life tweaks, but here are some of the highlights: + + + +* **ECS Schedule v3**: Bevy now has much simpler, more flexible scheduling. Systems are now stored in a unified schedule, commands can be applied explicitly via `apply_system_buffers`, and a whole lot of quality of life and bug fixes. +* **Cascaded Shadow Maps**: Higher quality shadow maps that cover larger distances, where the quality follows the camera. +* **Environment Map Lighting**: 360 degree ambient image based lighting that can cheaply and drastically improve the visual quality of a scene. +* **Depth and Normal Prepass**: Render depth and normal textures for a scene prior to the main pass, enabling new effects and (in some cases) improved performance. Shadow mapping uses the prepass shaders, which enables transparent textures to cast shadows. +* **Smooth Skeletal Animation Transitions**: Smoothly transition between two skeletal animations playing at the same time! +* **Improved Android Support**: Bevy now works out of the box on more Android devices (with a couple of caveats) +* **Revamped Bloom**: Bloom now looks better, is easier to control, and has fewer visual artifacts. +* **Distance and Atmospheric Fog**: Add depth and ambiance to your scene with 3D distance and atmospheric fog effects! +* **StandardMaterial Blend Modes**: Achieve a variety of interesting effects with more PBR material blend modes. +* **More Tonemapping Choices**: Choose one of 7 popular tonemapping algorithms for your HDR scenes to achieve the visual style you are looking for. +* **Color Grading**: Control per-camera exposure, gamma, "pre-tonemapping saturation", and "post-tonemapping saturation". +* **Parallel Pipelined Rendering**: App logic and render logic now run in parallel automatically, yielding significant performance wins. +* **Windows as Entities**: Windows are now represented as entities instead of resources, improving the user experience and unlocking new scenarios. +* **Renderer Optimizations**: We spent a _ton_ of effort optimizing the renderer this cycle. Bevy's renderer is snappier than ever! +* **ECS Optimizations**: Likewise, we've turbocharged many common ECS operations. Bevy apps get a nice speed boost! + +## ECS Schedule v3 + +
authors: @alice-i-cecile, @maniwani, @WrongShoe, @cart, @jakobhellermann, @JoJoJet, @geieredgar and a whole lot more
+ +Thanks to the fantastic work of our ECS team, the hotly awaited ["stageless" scheduling RFC](https://github.com/bevyengine/rfcs/blob/main/rfcs/45-stageless.md) has been implemented! + +**Schedule v3** is the culmination of significant design and implementation work. Scheduling APIs are a central and defining part of the Bevy developer experience, so we had to be very thoughtful and meticulous about this next evolution of the API. In addition to the [RFC PR](https://github.com/bevyengine/rfcs/pull/45), the [initial implementation PR](https://github.com/bevyengine/bevy/pull/6587) by `@maniwani` and the [Bevy Engine internals port PR](https://github.com/bevyengine/bevy/pull/7267) by `@alice-i-cecile` are great places to start if you would like a view into our process and rationale. As we all know, plans and implementations are two different things. Our final implementation is a bit different from the initial RFC (in a good way). + +There are a ton of changes, but we've put a lot of care into ensuring the [migration path](/learn/book/migration-guides/0.9-0.10/#migrate-engine-to-schedule-v3-stageless) for existing applications is relatively straightforward. Don't sweat it! + +Let's take a look at what shipped in 0.10! + +### A Single Unified Schedule + +Have you ever wanted to specify that `system_a` runs before `system_b`, only to be met with confusing warnings that `system_b` isn't found because it's in a different stage? + +No more! All systems within a single [`Schedule`] are now stored in a single data structure with a global awareness of what's going on. + +This simplifies our internal logic, makes your code more robust to refactoring, and allows plugin authors to specify high-level invariants (e.g. "movement must occur before collision checking") without locking themselves into an exact schedule location. + +[![main_schedule_diagram](main_schedule_diagram.svg)](main_schedule_diagram.svg) + +This diagram made with [@jakobhellermann's `bevy_mod_debugdump` crate](https://github.com/jakobhellermann/bevy_mod_debugdump) shows a simplified version of Bevy's default schedule. + +[`Schedule`]: https://docs.rs/bevy/0.10.0/bevy/ecs/schedule/struct.Schedule.html + +### Adding Systems + +[`Systems`] (which are just [normal Rust functions!](https://github.com/bevyengine/bevy/tree/v0.10.0/crates/bevy_ecs#systems)) are how you define game logic in Bevy ECS. With **Schedule v3**, you can add systems to your [`App`] just like you did in previous versions: + +```rust +app.add_system(gravity) +``` + +However **Schedule v3** has some new tricks up its sleeve! You can now add multiple systems at once: + +```rust +app.add_systems((apply_acceleration, apply_velocity)) +``` + +By default, Bevy runs systems in parallel to each other. In previous versions of Bevy, you ordered systems like this: + +```rust +app + .add_system(walk.before(jump)) + .add_system(jump)) + .add_system(collide.after(jump)) +``` + +You can still do that! But you can now compress this using `add_systems`: + +```rust +// much cleaner! +app.add_systems(( + walk.before(jump), + jump, + collide.after(jump), +)) +``` + +`before()` and `after()` are definitely useful tools! However, thanks to the new `chain()` function, it is now _much easier_ to run systems in a specific order: + +```rust +// This is equivalent to the previous example +app.add_systems((walk, jump, collide).chain()) +``` + +`chain()` will run the systems in the order they were defined. Chaining also pairs with per-system configuration: + +```rust +app.add_systems((walk.after(input), jump, collide).chain()) +``` + +[`App`]: https://docs.rs/bevy/0.10.0/bevy/app/struct.App.html +[`Systems`]: https://docs.rs/bevy/0.10.0/bevy/ecs/system/trait.System.html + +### Configurable System Sets + +In **Schedule v3**, the idea of the "system set" has been redefined to support more natural and flexible control over how systems are run and scheduled. The old "system label" concept has been combined with the "set" concept, resulting in one straightforward but powerful abstraction. + +[`SystemSets`] are named collections of systems that share system configuration across all of their members. Ordering systems relative to a [`SystemSet`] applies that ordering to _all_ systems in that set, in addition to any configuration on each individual system. + +Let's jump right into what this would look like. You define [`SystemSets`] like this: + +```rust +#[derive(SystemSet, Debug, Hash, PartialEq, Eq, Clone)] +enum PhysicsSet { + Movement, + CollisionDetection, +} +``` + +You can add systems to sets by calling the [`in_set`] method: + +```rust +app.add_system(gravity.in_set(PhysicsSet::Movement)) +``` + +You can combine this with the new system features mentioned above: + +```rust +app.add_systems( + (apply_acceleration, apply_velocity) + .chain() + .in_set(PhysicsSet::Movement) +) +``` + +Systems can belong to any number of sets: + +```rust +app.add_system( + move_player + .in_set(MoveSet::Player) + .in_set(PhysicsSet::Movement) +) +``` + +Configuration is added to sets like this: + +```rust +app.configure_set( + // Run systems in the Movement set before systems in the CollisionDetection set + PhysicsSet::Movement.before(PhysicsSet::CollisionDetection) +) +``` + +Sets can be nested inside other sets, which will cause them to inherit the configuration of their parent set: + +```rust +app.configure_set(MoveSet::Enemy.in_set(PhysicsSet::Movement)) +``` + +Sets can be configured multiple times: + +```rust +// In PlayerPlugin: +app.configure_set(MoveSet::Player.before(MoveSet::Enemy)) + +// In PlayerTeleportPlugin +app.configure_set(MoveSet::Player.after(PortalSet::Teleport)) +``` + +Crucially system configuration is strictly additive: you cannot _remove_ rules added elsewhere. This is both an "anti-spaghetti" and "plugin privacy" consideration. When this rule is combined with Rust's robust type privacy rules, plugin authors can make careful decisions about which exact invariants need to be upheld, and reorganize code and systems internally without breaking consumers. + +Configuration rules _must be compatible with each other_: any paradoxes (like a system set inside of itself, a system that must run both before and after a set, order cycles, etc) will result in a runtime panic with a helpful error message. + +[`SystemSet`]: https://docs.rs/bevy/0.10.0/bevy/ecs/schedule/trait.SystemSet.html +[`SystemSets`]: https://docs.rs/bevy/0.10.0/bevy/ecs/schedule/trait.SystemSet.html +[`in_set`]: https://docs.rs/bevy/0.10.0/bevy/ecs/schedule/trait.IntoSystemConfig.html#method.in_set + +### Directly Schedule Exclusive Systems + +"Exclusive systems" are [`Systems`] that have mutable direct access to the entire ECS [`World`]. For this reason, they cannot be run in parallel with other [`Systems`]. + +Since Bevy's inception, Bevy devs have wanted to schedule exclusive systems (and flush commands) relative to normal systems. + +Now you can! Exclusive systems can now be scheduled and ordered like any other system. + +```rust +app + .add_system(ordinary_system) + // This works! + .add_system(exclusive_system.after(ordinary_system)) +``` + +This is particularly powerful, as **command flushes** (which apply queued-up [`Commands`] added in systems to do things like spawn and despawn entities) are now simply performed in the `apply_system_buffers` exclusive system. + +```rust +app.add_systems( + ( + // This system produces some commands + system_a, + // This will apply the queued commands from system_a + apply_system_buffers, + // This system will have access to the results of + // system_a's commands + system_b, + // This chain ensures the systems above run in the order + // they are defined + ).chain() +) +``` + +Do be careful with this pattern though: it's easy to quickly end up with many poorly ordered exclusive systems, creating bottlenecks and chaos. + +What will you do with this much power? We're keen to find out! + +### Managing Complex Control Flow with Schedules + +But what if you want to do something _weird_ with your [`Schedule`]? Something non-linear, branching, or looping. What should you reach for? + +It turns out, Bevy already _had_ a great tool for this: schedules that run inside of an exclusive system. The idea is pretty simple: + +1. Construct a schedule, that stores whatever complex logic you want to run. +2. Store that schedule inside of a resource. +3. In an exclusive system, perform any arbitrary Rust logic you want to decide if and how your schedule runs. +4. Temporarily take the schedule out of the [`World`], run it on the rest of the world to mutate both the schedule and the world, and then put it back in. + +With the addition of the new [`Schedules`] resource and the `world.run_schedule()` API it's more ✨ ergonomic ✨ than ever. + +```rust +// A Schedule! +let mut my_schedule = Schedule::new(); +schedule.add_system(my_system); + +// A label for our new Schedule! +#[derive(ScheduleLabel, Debug, Hash, PartialEq, Eq, Clone)] +struct MySchedule; + +// An exclusive system to run this schedule +fn run_my_schedule(world: &mut World) { + while very_complex_logic() { + world.run_schedule(MySchedule); + } +} + +// Behold the ergonomics! +app + .add_schedule(MySchedule, my_schedule) + .add_system(run_my_schedule); +``` + +Bevy uses this pattern for five rather different things in **Bevy 0.10**: + +1. **Startup systems:** these now live in their own schedule, which is run once at the start of the app. +2. **Fixed timestep systems:** another schedule?! The exclusive system that runs this schedule accumulates time, running a while loop that repeatedly runs `CoreSchedule::FixedUpdate` until all of the accumulated time has been spent. +3. **Entering and exiting states:** a bonanza of schedules. Each collection of systems that runs logic to enter and exit a state variant is stored in its own schedule, which is called based on the change in state in the `apply_state_transitions::` exclusive system. +4. **Rendering:** all rendering logic is stored in its own schedule to allow it to run asynchronously relative to gameplay logic. +5. **Controlling the outermost loop:** in order to handle the "startup schedule first, then main schedule" logic, we wrap it all up in a minimal overhead `CoreSchedule::Outer` and then run our schedules as the sole exclusive system there. + +Follow the breadcrumbs starting at [`CoreSchedule`](https://docs.rs/bevy/0.10.0/bevy/app/enum.CoreSchedule.html) for more info. + +[`Schedules`]: https://docs.rs/bevy/0.10.0/bevy/ecs/schedule/struct.Schedules.html + +### Run Conditions + +[`Systems`] can have any number of **run conditions**, which are "just" systems that return a `bool`. If the `bool`s returned by _all_ of a system's **run conditions** are `true`, the system will run. Otherwise the system will be skipped for the current run of the schedule: + +```rust +// Let's make our own run condition +fn game_win_condition(query: Query<&Player>, score: Res) -> bool { + let player = query.single(); + player.is_alive() && score.0 > 9000 +} + +app.add_system(win_game.run_if(game_win_condition)); +``` + +**Run conditions** also have a number of "combinator" operations, thanks to [@JoJoJet](https://github.com/bevyengine/bevy/pull/7547) and [@Shatur](https://github.com/bevyengine/bevy/pull/7559): + +They can be negated with `not()`: + +```rust +app.add_system(continue_game.run_if(not(game_win_condition))) +``` + +They can also be combined with `and_then` and `or_else`: + +```rust +app.add_system(move_player.run_if(is_alive.or_else(is_zombie))) +``` + +Bevy 0.10 is shipping with a lovely collection of built-in [common run conditions](https://docs.rs/bevy/0.10.0/bevy/ecs/schedule/common_conditions/index.html). You can easily run systems if there are events to process, timers that elapsed, resources that changed, input state changes, states that changed, and more (thanks to [`@maniwani`](https://github.com/bevyengine/bevy/pull/6587), [`@inodentry`](https://github.com/bevyengine/bevy/pull/7579), [`@jakobhellermann`](https://github.com/bevyengine/bevy/pull/7806), and [`@jabuwu`](https://github.com/bevyengine/bevy/pull/7866)). + +**Run conditions** can also serve as a lightweight optimization tool. Run conditions are evaluated on the main thread, and each run criteria is evaluated exactly once each schedule update, at the time of the first system in the set that relies on it. Systems disabled by run conditions don't spawn a task, which can add up across many systems. Like always though: benchmark! + +**Run conditions** have replaced the "run criteria" in previous versions of Bevy. We can finally get rid of the dreaded "looping run criteria"! [`ShouldRun::YesAndCheckAgain`](https://docs.rs/bevy/0.9.1/bevy/ecs/schedule/enum.ShouldRun.html) was not exactly straightforward to reason about, either for engine devs or users. It's always a bad sign when your bool-like enums have four possible values. If you crave more complex control flow: use the "schedules in exclusive systems" pattern in the [section above](#directly-schedule-exclusive-systems). For the other 99% of use cases, enjoy the simpler `bool`-based run conditions! + +### Simpler States + +**Schedule v3** adds a new, much simpler "state system". [`States`] allow you to easily configure different [`App`] logic to run based on the current "state" of the [`App`]. + +You define [`States`] like this: + +```rust +#[derive(States, PartialEq, Eq, Debug, Default)] +enum AppState { + #[default] + MainMenu, + InGame, +} +``` + +Each variant of the enum corresponds to a different state the [`App`] can be in. + +You add [`States`] to your [`App`] like this: + +```rust +app.add_state::() +``` + +This will setup your [`App`] to use the given state. It adds the [`State`] resource, which can be used to find the current state the [`App`] is in: + +```rust +fn check_state(state: Res>) { + info!("We are in the {} state", state.0); +} +``` + +Additionally, `add_state` will create an `OnUpdate` set for each possible value, which you can then add your systems to. These sets run as part of the normal app update, but only when the app is in a given state: + +```rust +app + .add_systems( + (main_menu, start_game) + .in_set(OnUpdate(AppState::MainMenu)) + ) + .add_system(fun_gameplay.in_set(OnUpdate(AppState::InGame))); +``` + +It will also create `OnEnter` and `OnExit` schedules for each state, which will only run when transitioning from one state to another: + +```rust +app + .add_system(load_main_menu.in_schedule(OnEnter(AppState::MainMenu))) + .add_system(cleanup_main_menu.in_schedule(OnExit(AppState::MainMenu))) +``` + +`add_state` also adds the [`NextState`] resource, which can be used to queue a state change: + +```rust +fn start_game( + button_query: Query<&Interaction, With>, + next_state: ResMut>, +){ + if button_query.single() == Interaction::Pressed { + *next_state = NextState(AppState::InGame); + } +} +``` + +This replaces Bevy's previous state system, which was very hard to deal with. It had state stacks, elaborate queued transitions, and error handling (that most people just unwrapped). The state stack was very complex to learn, very prone to exasperating bugs, and mostly ignored. + +As a result, in **Bevy 0.10** states are now "stackless": only one queued state of each type at a time. After lots of alpha testing, we're reasonably confident that this shouldn't be too bad to migrate away from. If you were relying on the state stack, you have plenty of options: + +* Build the "stack" logic on top of the core state system +* Split your state into multiple states, which capture orthogonal elements of your app's status +* Build your own state stack abstraction using the same patterns as Bevy's first-party version. None of the new state logic is hard coded! If you build something, [let the rest of the community know](/assets) so you can collaborate! + +[`States`]: https://docs.rs/bevy/0.10.0/bevy/ecs/schedule/trait.States.html +[`State`]: https://docs.rs/bevy/0.10.0/bevy/ecs/schedule/struct.State.html +[`NextState`]: https://docs.rs/bevy/0.10.0/bevy/ecs/schedule/struct.NextState.html + +### Base Sets: Getting Default Behavior Right + +An astute reader may point out that: + +1. Bevy automatically runs its systems in parallel. +2. [The order of systems is nondeterministic unless there is an explicit ordering relationship between them](https://github.com/bevyengine/bevy/blob/latest/examples/ecs/nondeterministic_system_order.rs) +3. All of the systems are now stored in a single `Schedule` object with no barriers between them +4. Systems can belong to any number of system sets, each of which can add their own behavior +5. Bevy is a powerful engine with many internal systems. + +Won't this lead to utter chaos and tedious spaghetti-flavored work to resolve every last ordering ambiguity? +Many users _liked_ stages, they were helpful for understanding the structure of an [`App`]! + +Well, I'm glad you asked, rhetorical skeptic. To reduce this chaos (and ease migration), **Bevy 0.10** comes with a brand new collection of system sets provided by [`DefaultPlugins`]: [`CoreSet`](https://docs.rs/bevy/0.10.0/bevy/app/enum.CoreSet.html), [`StartupSet`](https://docs.rs/bevy/0.10.0/bevy/app/enum.StartupSet.html), and [`RenderSet`](https://docs.rs/bevy/0.10.0/bevy/render/enum.RenderSet.html). The similarity of their names to the old [`CoreStage`](https://docs.rs/bevy/0.9.1/bevy/app/enum.CoreStage.html), [`StartupStage`](https://docs.rs/bevy/0.9.1/bevy/app/enum.StartupStage.html), and [`RenderStage`](https://docs.rs/bevy/0.9.1/bevy/render/enum.RenderStage.html) is not a coincidence. Much like stages, there are command flush points between each set, and existing systems have been migrated directly. + +Some parts of the stage-centric architecture were appealing: a clear high-level structure, coordination on flush points (to reduce excessive bottlenecks), and good default behavior. +To keep those bits (while excising the frustrating ones), we've introduced the concept of **Base Sets** ([added by @cart](https://github.com/bevyengine/bevy/pull/7466)). **Base Sets** are just normal [`SystemSets`], except: + +1. Every system can belong to at most one base set. +2. Systems that do not specify a base set will be added to the default base set for the schedule (if the schedule has one). + +```rust +// You define base sets exactly like normal sets, with the +// addition of the system_set(base) attribute +#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)] +#[system_set(base)] +enum MyBaseSet { + Early, + Late, +} + +app + // This ends up in CoreSet::Update by default + .add_system(no_explicit_base_set) + // You must use .in_base_set rather than .in_set for explicitness + // This is a high-impact decision! + .add_system(post_update.in_base_set(CoreSet::PostUpdate)) + // Look, it works! + .add_system(custom_base_set.in_base_set(MyBaseSet::Early)) + // Ordering your base sets relative to CoreSet is probably wise + .configure_set(MyBaseSet::Early.before(CoreSet::Update)) + .configure_set(MyBaseSet::Late.after(CoreSet::Update)); +``` + +Let me tell you a story, set in a world without **Base Sets**: + +1. A new user adds the `make_player_run` system to their app. +2. Sometimes this system runs before input handling, leading to randomly dropped inputs. Sometimes it runs after rendering, leading to strange flickers. +3. After much frustration, the user discovers that these are due to "system execution order ambiguities". +4. The user runs a specialized detection tool, digs into the source code of the engine, figures out what order their system should run in relative to the engine's system sets, and then continues on their merry way, doing this for each new system. +5. Bevy (or one of their third-party plugins) updates, breaking all of our poor users system ordering once again. + +The clear problem this illustrates is that _most_ gameplay systems should not need to know or care about "internal systems". + +We've found that in practice, there are three broad classes of systems: gameplay logic (the majority of all end user systems), stuff that needs to happen before gameplay logic (like event cleanup and input handling), and stuff that needs to happen after gameplay logic (like rendering and audio). + +By broadly ordering the schedule via **Base Sets**, Bevy apps can have good default behavior and clear high-level structure without compromising on the scheduling flexibility and explicitness that advanced users crave. +Let us know how it works out for you! + +### Improved System Ambiguity Detection + +When multiple systems interact with an ECS resource in conflicting ways, but don't have an ordering constraint between them, we call this an "ambiguity". If your [`App`] has ambiguities, this can cause bugs. We've significantly improved our ambiguity reporting, which can be configured in the new [`ScheduleBuildSettings`](https://docs.rs/bevy/0.10.0/bevy/ecs/schedule/struct.ScheduleBuildSettings.html). Check out the docs for more info. If you haven't tried this out on your app yet: you should take a look! + +### Single Threaded Execution + +You can now easily switch a [`Schedule`] to single-threaded evaluation via the [`SingleThreadedExecutor`](https://docs.rs/bevy/0.10.0/bevy/ecs/schedule/struct.SingleThreadedExecutor.html) for users who don't want or need parallelism. + +```rust +schedule.set_executor_kind(ExecutorKind::SingleThreaded); +``` + +## Cascaded Shadow Maps + +
authors: @danchia, Rob Swain (@superdump)
+ +Bevy uses "shadow maps" to cast shadows for lights / objects. Previous versions of Bevy used a simple but limited shadow map implementation for directional light sources. For a given light, you would define the resolution of the shadow map _and_ a manual "view projection" that would determine how the shadow is cast. This had a number of downsides: + +* The resolution of the shadow map was fixed. You had to choose something between "cover a large area, but have a lower resolution" and "cover a smaller area, but have a higher resolution". +* The resolution didn't adapt to camera positioning. Shadows might look great in one position, but terrible in another position. +* The "shadow projection" had to be manually defined. This made it hard and unapproachable to configure shadows to match a given scene. + +**Bevy 0.10** adds "cascaded shadow maps", which breaks up the camera's view frustum into a series of configurable "cascades", which each have their own shadow map. This enables shadows in the cascade "close to the camera" to be highly detailed, while allowing shadows "far from the camera" to cover a wider area with less detail. Because it uses the camera's view frustum to define the shadow projections, the shadow quality remains consistent as the camera moves through the scene. This also means that users don't need to manually configure shadow projections anymore. They are automatically calculated! + + + +Notice how the nearby shadows are highly detailed whereas the shadows in the distance become less detailed as they get farther away (which doesn't matter as much because they are far away). + +While shadow cascades solve important problems, they also introduce new ones. How many cascades should you use? What is the minimum and maximum distance from the camera where shadows should appear? How much overlap should there be between cascades? Be sure to dial in these parameters to fit your scenes. + +## Environment Map Lighting + +
authors: @JMS55
+ +Environment maps are a popular and computationally cheap way to significantly improve the quality of a scene's lighting. It uses a cube map texture to provide 360 degree lighting "from all directions". This is especially apparent for reflective surfaces, but it applies to all lit materials. + +This is what the PBR material looks like without environment map lighting: + +![env map before](env_map_before.png) + +And this is what the PBR material looks like with environment map lighting: + +![env map after](env_map_after.png) + +For scenes that need constant lighting (especially outdoor scenes), environment maps are a great solution. And because environment maps are arbitrary images, artists have a lot of control over the character of the scene's lighting. + +## Depth and Normal Prepass + +
authors: @icesentry, Rob Swain (@superdump), @robtfm, @JMS55
+ + +

This effect uses the depth from the prepass to find the intersection between the ground and the force field

+ +Bevy now has the ability to run a depth and/or normal prepass. This means the depth and normal textures will be generated in a render pass that runs before the main pass and can therefore be used during the main pass. This enables various special effects like Screen Space Ambient Occlusion, Temporal Anti Aliasing, and many more. These are currently being worked on and should be [available in the next release of Bevy](#what-s-next). + +![Edge detection](edge_detection.png) +

In the image on the right, green lines are edges detected in the normal texture and blue lines are edges detected in the depth texture

+ +![Edge detection prepass](edge_detection_prepass.png) +

The depth and normal textures generated by the prepass

+ +Using the prepass essentially means rendering everything twice. The prepass itself is much faster since it does a lot less work than the main pass. The result of the prepass can be used to reduce overdraw in the main pass, but if your scene didn't already suffer from overdraw then enabling the prepass will negatively affect performance. There are many things that can be done to improve this and we will keep working towards this goal. Like with anything performance related, make sure to measure it for your use case and see if it helps or not. + +The prepass is still very useful when working on special effects that require a depth or normal texture, so if you want to use it you can simply add the `DepthPrepass` or `NormalPrepass` components to your camera. + +## Shadow Mapping using Prepass Shaders + +
authors: @geieredgar
+ +Previously, the shader used for shadow mapping was hard-coded and had no knowledge of the material, only meshes. Now in **Bevy 0.10**, a `Material`'s depth prepass shaders are used for shadow mapping. This means that the shaders used to do the shadow mapping for a `Material` are customizable! + +As a bonus, the availability of `Material` information during shadow mapping means that we could instantly enable alpha mask shadows allowing foliage to cast shadows according to the alpha values in their texture rather than only based on their geometry. + +![Alpha mask shadows](alpha_mask_shadows.png) +
NVIDIA ORCA Emerald Square scene (CC BY-NC-SA 3.0) with alpha mask shadow support
+ +## Smooth Skeletal Animation Transitions + +
authors: @smessmer
+ +You can now smoothly transition between two (or more) skeletal animations! + + + +
Character model and animations are royalty free assets from Mixamo. +
+ +With the new [`play_with_transition`] method on the [`AnimationPlayer`] component, you can now specify a transition duration during which the new animation will be linearly blended with the currently playing animation, whose weight will decrease during that duration until it reaches `0.0`. + +```rust +#[derive(Component, Default)] +struct ActionTimer(Timer); + +#[derive(Component)] +struct Animations { + run: Handle, + attack: Handle, +} + +fn run_or_attack( + mut query: Query<(&mut AnimationPlayer, &mut ActionTimer, &Animations)>, + keyboard_input: Res>, + animation_clips: Res>, + time: Res