Skip to content

Atmosphere as entity with transforms#23651

Open
mate-h wants to merge 7 commits intobevyengine:mainfrom
mate-h:m/atmosphere-transform
Open

Atmosphere as entity with transforms#23651
mate-h wants to merge 7 commits intobevyengine:mainfrom
mate-h:m/atmosphere-transform

Conversation

@mate-h
Copy link
Copy Markdown
Contributor

@mate-h mate-h commented Apr 3, 2026

Objective

Anecdotal feedback:

Solution

  • Atmosphere component can be spawned stand-alone
  • AtmosphereSettings remains on camera
  • A closest-to-camera heuristic is used to pick the primary atmosphere to render. Deliberately no multi-atmosphere support to keep the scope of this PR small and self contained. See WIP: Multiple atmospheres in one scene mate-h/bevy#19 at an attempt.
  • scene_units_to_m removed in favor of using Transform
  • Z up now possible by offsetting the viewer position to the equator
  • Floating origin systems now possible
  • Simplify the AtmosphereBuffer / AtmosphereData structs to just use the plain extracted GpuAtmosphere struct. this reduces the complexity of the struct in the mesh view bindings. Since atmosphere settings is coupled with the rendering pipeline of the atmosphere this makes sense architecturally.
  • We no longer hard code the offset to the north pole from the planet center in places.

Why not multi atmosphere:
The atmosphere uses multiple LUTs (lookup textures) to accelerate the rendering performance. Some of them are not view dependent:

  • Transmittance LUT
  • Multiple scattering LUT
  • Scattering / density LUTs

These can be coupled and rendered for each atmosphere individually. However the remainder of the pipeline is view dependent:

  • Aerial View LUT
  • Sky View LUT
  • Render Sky pass

In raymarched rendering mode, these LUTs can be skipped and only the render sky pass runs sampling on all of the atmospheres with a raymarch in screen space.

Further, the Sky View LUT uses a local reference frame to concentrate texel density along the horizon's local up axis. This in turn means it's coupled with both a specific atmosphere's local coordinates as well as the view's transform matrix. We cannot consider rendering both atmospheres into a single LUT for this reason. So it has to be unique for each pair of (view, atmosphere). Given two views and two atmospheres we would need 4 of these Sky View LUTs and at some point, raymarched rendering will become the less expensive option.

Lastly the Render Sky pass needs to happen once per view, we cannot realistically composite them in sequence with simple dual-source blending as we do with the scene, this would result in incorrect scattering integration. This in turn means we need to bind ALL of the luts calculated previously so a single render sky pass and render aerial view lut - perhaps making use of array textures. Rely on unified volumetric ingegration in the raymarching loop: for each light,for each atmosphere, attenuate inscattering and transmittance along the path integral. It is suffice to say this change is overall too complex for the time being and is likely the reason Unreal Engine also do not support multiple atmospheres. For context: our research is based heavily on Sebastian Hillarie's work, one of the Unreal graphics engineers.

That being said about multiple atmospheres - I am thinking of this PR as a segway into unified volumetrics in Bevy. that is: Render the FogVolume and Atmosphere in a single pass! Making use of the frustum aligned voxel grid "froxel" approach to accelerate the rendering. This would drastically increase the performance for scenes wanting to make use of both the atmosphere and local fog volumes.

Testing

  • Ran the examples/3d/atmosphere.rs example.

Showcase

(example screenshot unchanged compared to main.)

// Spawn earth atmosphere
commands.spawn(Atmosphere::earth(earth_medium));

commands.spawn((
    Camera3d::default(),
    // Can be adjusted to change the rendering quality
    AtmosphereSettings::default(),
));

@mate-h mate-h added A-Rendering Drawing game state to the screen M-Migration-Guide A breaking change to Bevy's public API that needs to be noted in a migration guide D-Straightforward Simple bug fixes and API improvements, docs, test and examples S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Apr 3, 2026
@github-project-automation github-project-automation bot moved this to Needs SME Triage in Rendering Apr 3, 2026
@mate-h mate-h requested a review from ecoskey April 3, 2026 20:20
@carrapaz
Copy link
Copy Markdown

carrapaz commented Apr 3, 2026

Thanks! Eagerly waiting for this 😄

Copy link
Copy Markdown
Contributor

@ecoskey ecoskey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooh nice! Mostly just have some nitpicks and some comments for future work.

/// when your scene uses other units, like kilometer-sized scenes.
#[derive(Clone, Component)]
#[require(Hdr)]
#[require(Transform::default())]
Copy link
Copy Markdown
Member

@aevyrie aevyrie Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does the north pole of a sphere matter? Why does up direction matter at all? Isn't scattering entirely view, medium, and light dependent?

Copy link
Copy Markdown
Contributor

@ecoskey ecoskey Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean regarding the default Vec3::NEG_Y * radius offset? I think it's just that most people will want the planet normal to be Vec3::Y around where their scene is located. But yeah the docs should probably say that instead of making the north pole special.

Copy link
Copy Markdown
Contributor Author

@mate-h mate-h Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes the north pole is not special in any sense, there is no global up direction. the locally apparent up direction from the planets surface (i.e. the way the horizon faces) arises from the spheres outward pointing normal direction. Since bevy's convention is Y up by default that's why I also defaulted the scene to align the horizon with this up direction. If the user were to tilt there camera to be Z up for instance they would need to move the atmosphere offset to the equator instead so the apparent horizon's tilt also matches the new up direction. Hope this clears things up a bit. This is in contrast to the linked repo above that encodes the local up direction into the atmosphere space during the inner raymarch. Code ref: https://github.com/philpax/veldera/blob/main/crates/bevy_pbr_atmosphere_planet/src/shaders/functions.wgsl#L230
this effectively rotates the horizon in view space relative to the camera which works differently than a simple transform on the atmosphere component. so I deliberately excluded this type of approach from this PR.

Co-authored-by: Emerson Coskey <emerson@coskey.dev>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 3, 2026

The generated examples/README.md is out of sync with the example metadata in Cargo.toml or the example readme template. Please run cargo run -p build-templated-pages -- update examples to update it, and commit the file change.

Copy link
Copy Markdown
Contributor

@ecoskey ecoskey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Agree that we shouldn't hold this up too long on renaming or other refactors. Approving 🙂

  • I do still think we can save three matmuls in ndc_to_camera_dist if the planet's scale is uniform (which it should always be imo) and we keep track of the scale separate from the matrix.
  • I'm fine with keeping AtmosphereSettings as the "driver" component for now, but will note that we moved away from this style in several other effects. i.e. BloomSettings was renamed to Bloom iirc

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-Rendering Drawing game state to the screen D-Straightforward Simple bug fixes and API improvements, docs, test and examples M-Migration-Guide A breaking change to Bevy's public API that needs to be noted in a migration guide S-Needs-Review Needs reviewer attention (from anyone!) to move forward

Projects

Status: Needs SME Triage

Development

Successfully merging this pull request may close these issues.

4 participants