Atmosphere as entity with transforms#23651
Conversation
|
Thanks! Eagerly waiting for this 😄 |
ecoskey
left a comment
There was a problem hiding this comment.
Ooh nice! Mostly just have some nitpicks and some comments for future work.
Co-authored-by: Emerson Coskey <emerson@coskey.dev>
|
The generated |
There was a problem hiding this comment.
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_distif 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
AtmosphereSettingsas the "driver" component for now, but will note that we moved away from this style in several other effects. i.e.BloomSettingswas renamed toBloomiirc
| #[derive(Clone, Component)] | ||
| #[require(Hdr)] | ||
| #[require(GlobalTransform::default())] | ||
| #[component(on_add = set_default_transform)] |
There was a problem hiding this comment.
It would be nice if there was some way to opt out of setting the Transform for users of non-default transform systems. I don't know if there is a nice solution that doesn't add more complexity.
The only thing I can think of is making the Transform and GlobalTransform optional (not required components), and placing the atmosphere at -6000km in Y if they are not present. That way you have to opt in to manual atmosphere positioning and can use your own components?
There was a problem hiding this comment.
I need to better understand the use case, maybe I should test this change with big_space. is that a good example of a non-default transform system? also, would just changing the lines in set_default_transform to GlobalTransform work for decoupling it?
There was a problem hiding this comment.
I need to better understand the use case, maybe I should test this change with big_space. is that a good example of a non-default transform system?
Not really, it integrates with Transform. It's more about only depending on GlobalTransform instead of Transform everywhere.
would just changing the lines in set_default_transform to GlobalTransform work for decoupling it?
No, because it would just get overwritten by whatever transform system is present, including bevy's. That's why I was suggesting making the atmosphere positioning entirely opt-in: you get good default behavior for bevy out of the box, and don't have any dependency on Transform for arbitrary downstream use cases - the code only reads GlobalTransform.
EmbersArc
left a comment
There was a problem hiding this comment.
Neat! Just some nits from me.
| /// The scale on [`GlobalTransform`] rescales the planet in world space. Tune it with the radius offset | ||
| /// when your scene uses other units, like kilometer-sized scenes. |
There was a problem hiding this comment.
The Atmosphere fields say units: m. But according to this comment this is only accurate for scale = Vec3::ONE.
Maybe there should also be a note about transforms that are not x==y==z.
There was a problem hiding this comment.
Good point I never tested non-uniform scale, hopefully it doesn't break too badly 😬 However, regarding the units: m that should stay the same since these units are still expressed in atmosphere-space and not world-space. So scaling the atmosphere doesn't change the meaning of those units, those are still meters. For actually scaling the atmosphere in a physically based way you'd set a smaller inner_radius and outer_radius. Now I realize this might be confusing so maybe it deserves more docs.
| + Vec3::new(0.0, atmosphere.bottom_radius, 0.0), | ||
| gpu_atmosphere | ||
| .world_to_atmosphere | ||
| .transform_point3(cam_world), |
There was a problem hiding this comment.
Recent versions of glam have to_vec3a()
| ground_albedo: Vec3::ZERO, | ||
| inner_radius: 0.0, | ||
| outer_radius: 0.0, | ||
| world_to_atmosphere: Mat4::IDENTITY, |
There was a problem hiding this comment.
I prefer e.g. atmosphere_from_world for those transforms, but bevy seems to use both.
There was a problem hiding this comment.
The reason I kept the inverse here is so that I can pass it to the GPU uniform and it becomes a simple multiplication by the world space position. The public facing component API i.e. the struct Atmosphere doesn't expose this world_to_atmosphere matrix to the userspace, they are tuning the regular, non-inverted Transform component. This field is only used on the GpuAtmosphere so that the shader doesn't have to compute the inverse (expensive).
There was a problem hiding this comment.
I fully agree with the inverse if it makes more sense in this case. My comment was just about the naming convention.
# Objective - Once PR #23651 is merged we need a migration guide for breaking changes to Bevy's atmosphere. - Post the release note changes as a new PR to review grammar/writing separately ## Solution - Write a migration guide detailing the breaking changes - Adhere to a friendly non-technical tone - Explain the new way of scaling the atmosphere with `Transform` ## Out of scope - Explain how to customize the apparent up axis (i.e. horizon's orientation) -> this should follow intuitively but maybe I should add this too? or maybe this belongs in a release note instead?
# Objective **Anecdotal feedback:** - no floating origin support for implementing large-scale worlds, forked Bevy's atmosphere at https://github.com/philpax/veldera/blob/main/crates/bevy_pbr_atmosphere_planet/NOTICE.md - no custom up axis support, resorted to using a custom sky shader for flight simulator with Z up coordinate system. Bevy's atmosphere appears tilted at a 90 degree angle with no way of changing it. ## 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 #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.) ```rs // Spawn earth atmosphere commands.spawn(Atmosphere::earth(earth_medium)); commands.spawn(( Camera3d::default(), // Can be adjusted to change the rendering quality AtmosphereSettings::default(), )); ``` --------- Co-authored-by: Emerson Coskey <emerson@coskey.dev>
# Objective - Once PR bevyengine#23651 is merged we need a migration guide for breaking changes to Bevy's atmosphere. - Post the release note changes as a new PR to review grammar/writing separately ## Solution - Write a migration guide detailing the breaking changes - Adhere to a friendly non-technical tone - Explain the new way of scaling the atmosphere with `Transform` ## Out of scope - Explain how to customize the apparent up axis (i.e. horizon's orientation) -> this should follow intuitively but maybe I should add this too? or maybe this belongs in a release note instead?
Objective
Anecdotal feedback:
Solution
scene_units_to_mremoved in favor of usingTransformAtmosphereBuffer/AtmosphereDatastructs to just use the plain extractedGpuAtmospherestruct. 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.Why not multi atmosphere:
The atmosphere uses multiple LUTs (lookup textures) to accelerate the rendering performance. Some of them are not view dependent:
These can be coupled and rendered for each atmosphere individually. However the remainder of the pipeline is view dependent:
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
examples/3d/atmosphere.rsexample.Showcase
(example screenshot unchanged compared to main.)