CesiumGS / cesium

An open-source JavaScript library for world-class 3D globes and maps :earth_americas:
https://cesium.com/cesiumjs/
Apache License 2.0
12.93k stars 3.49k forks source link

Proposal: Consolidate SkyAtmosphere and Globe atmosphere settings? #11681

Open ptrgags opened 11 months ago

ptrgags commented 11 months ago

As I'm looking into #4196, one thing I notice is that the following settings exist on both viewer.scene.skyAtmosphere (for the sky) and viewer.scene.globe (for ground and fog for terrain):

Ultimately these impact the shader uniforms in AtmosphereCommon.glsl:

uniform vec3 u_radiiAndDynamicAtmosphereColor;
uniform float u_atmosphereLightIntensity;
uniform float u_atmosphereRayleighScaleHeight;
uniform float u_atmosphereMieScaleHeight;
uniform float u_atmosphereMieAnisotropy;
uniform vec3 u_atmosphereRayleighCoefficient;
uniform vec3 u_atmosphereMieCoefficient;

Since the ground and sky atmosphere both represent the Earth's atmosphere, conceptually they should always use the same settings.

There's also two other benefits of combining them:

  1. This streamlines the interface. Instead of changing settings in two places (skyAtmosphere and globe), you only need to change one (I'm thinking Globe, but open to suggestions).
  2. It also would streamline things deeper in the implementation details. In #4196 I'm already considering changing the Globe's implementation to use AutomaticUniforms, this way it's easier to implement fog for 3D Tiles.

I'm curious if the community would find this to be a reasonable breaking change, or if there are use cases where configuring SkyAtmosphere and GroundAtmosphere differently is helpful. I'll ask about this on the forum as well.

lilleyse commented 11 months ago

I'm thinking Globe, but open to suggestions

I think the atmosphere options should be in its own object under Scene in case you don't have a globe

ptrgags commented 11 months ago

@lilleyse That's a good point, I like that for 2 more reasons:

  1. It puts the parameters in their own dedicated struct to make
  2. The implementation would have more symmetry with how scene.fog is implemented
ptrgags commented 11 months ago

I made a forum post to see if the community has any further thoughts on this.

ptrgags commented 10 months ago

A couple more thoughts:

  1. For non-photorealistic rendering, it's kinda neat to be able to adjust the color of sky atmosphere and ground atmosphere/fog separately. So maybe the HSB shift parameters could be duplicated for each system, but keep the other atmosphere parameters in sync. image
  2. The flags that enable lighting for the sky/ground/fog are rather tangled. Here's a table to keep track of what affects what.
Setting Purpose (Globe) ground atmosphere SkyAtmosphere (Globe) Terrain fog Fog culling
Viewer constructor: options.globe If false, the globe is not created/rendered If false, does not render. If false, cannot use lighting from sun, but otherwise not affected If false, not rendered If false, no terrain so no fog culling.
globe.enableLighting turns on lighting from the sun or other light source Toggles lighting toggles lighting (flag synced via Scene) Toggles lighting regardless of globe.showGroundAtmosphere No effect
globe.dynamicAtmosphereLighting Use the sun or other light source. If false, use a light directly overhead of the vertex/fragment Toggles dynamic lighting Toggles dynamic lighting (flag synced via Scene) Toggles dynamic lighting (regardless of globe.showGroundAtmosphere No effect
globe.dynamicAtmosphereLightingFromSun forces using the sun rather than the scene's current light source (sun or directional light) Toggles forced sunlight Toggles forced sunlight (flag synced via Scene) Toggles forced sunlight regardless of globe.showGroundAtmosphere No effect
globe.showGroundAtmosphere Turns off rendering of the ground atmosphere Not rendered No effect No effect No effect
skyAtmosphere.show Turns off rendering the sky atmosphere No effect Not rendered No effect No effect
fog.enabled Turn off anything to do with fog. No effect no effect Not rendered No fog culling
fog.renderable Toggle showing fog, but still allow fog culling No effect No effect Not rendered No effect

Some of these settings might be better off stored in the new scene.atmosphere so all the systems always are synced to it via FrameState and/or AutomaticUniforms

ptrgags commented 10 months ago

After thinking about the above parameters, here's a proposal for how this might be structured to make the UX for adjusting lighting better, and make it easier for atmosphere and fog settings to be applied to 3D Tiles (and any future system that needs them)

The tricky thing is this does involve quite a few breaking changes to the API, and deprecating things would be a bit tricky. Though at least for some of the settings, #11655 might be a good reference for determining how to deprecate settings.

scene.atmosphere: Atmosphere (new)

Purpose: Store common settings that affect all atmosphere rendering affects. This object does not do any rendering, but updates the FrameState so other systems can access the parameters.

Parameters:

scene.groundAtmosphere: GroundAtmosphere (new)

Purpose: Store common settings that affect ground atmosphere (impacts the globe and 3D Tiles) This will update the FrameState so other systems can access the parameters.

Parameters:

scene.skyAtmosphere: SkyAtmosphere (modified)

Purpose: Renderable sky atmosphere. It manages any settings specific to the sky rendering

Parameters: (unchanged) skyAtmosphere.show: bool - Turn on sky atmosphere rendering (unchanged) skyAtmosphere.hueShift/saturationShift/brightnessShift/: number - Adjust the HSB color of the sky atmosphere independent from other atmosphere rendering. (remove) skyAtmosphere.atmosphere* -- move scattering settings to the common Atmosphere

Other details:

scene.globe: Globe (modified)

Purpose: Renderable globe that handles terrain, imagery and other rendering details. It also renders the ground atmosphere and fog for terrain. The main change is to unload some of the rendering settings to Atmosphere and GroundAtmosphere so other systems can access them even when the globe is turned off.

Parameters: (unchanged) globe.atmosphereHueShift/atmosphereSaturationShift/atmosphereBrightnessShift/: number -- Adjust the HSB color of the ground atmosphere and terrain fog only. (remove) globe.atmosphere* -- move scattering settings to the common Atmosphere (remove) globe.enableLighting, globe.dynamicAtmosphere* -- These flags were confusing and weirdly coupled to SkyAtmosphere and fog. Replace this with Atmosphere.dynamicLighting (now an enum) (remove) globe.showGroundAtmosphere - Move to groundAtmosphere.show so this setting can be used for 3D Tiles as well.

scene.fog: Fog (unchanged)

I think the settings for Fog are sufficient for now. The main change is that this will now impact 3D Tiles as well.

The fog color is still dependent on the ground atmosphere, but now the dedicated GroundAtmosphere will put the relevant settings in the FrameState so both terrain and 3D Tiles can access it.

ptrgags commented 10 months ago

After talking with @ggetz the other day, we think that the above is a bit of overkill. A couple changes to streamline the above:

  1. a separate GroundAtmosphere class isn't really needed, just add the settings to scene.atmosphere (except for show which should be scoped to the primitive responsible for rendering, whether that's the globe or the tileset)
  2. For consistency and ease of use, just have a single place for hue/saturation/brightness shift (also in scene.atmosphere). This means the colors for sky and ground atmosphere will always be in sync (before they were independent.

So to summarize the overall architecture

ptrgags commented 10 months ago

Some implementation details from #11744 that will need changes after we change the API:

(I'll update this as I find more)

ptrgags commented 9 months ago

Some thoughts about how to make the Globe and SkyAtmosphere settings work during the deprecation period:

  1. Whenever Scene.globe's setter is called, also set globe._atmosphere = this.atmosphere so the globe now has a reference to the atmosphere struct.
  2. Change Scene.skyAtmosphere to a setter, and do a similar skyAtmosphere._atmosphere = this.atmosphere
  3. Make a Scene.atmosphere setter that updates globe._atmosphere and skyAtmosphere._atmosphere to the new atmosphere object (if the globe/sky exist)
  4. For Globe/SkyAtmosphere, turn all of the atmosphere-related members into properties, and the setters should: A. log a deprecation warning, and B. Don't update the globe/sky, update _atmosphere.<propertyNameHere> instead (checking first if _atmosphere is defined). If it's not defined... maybe another warning is needed (not the most elegant, but this is temporary for the deprecation period)
  5. In the shaders, use the czm_atmosphere* builtins and functions
  6. Also remove all old atmosphere uniforms manually set by the globe/sky atmosphere (u_atmosphere*) and the code used to configure them, as these will become dead code (note, make sure to check through GlobeSurfaceTileProvider.js and GlobeSurfaceShaderSet.js carefully.)