diff --git a/Apps/Sandcastle/gallery/Atmosphere.html b/Apps/Sandcastle/gallery/Atmosphere.html index 1f2741655f2..301fc9119c1 100644 --- a/Apps/Sandcastle/gallery/Atmosphere.html +++ b/Apps/Sandcastle/gallery/Atmosphere.html @@ -25,6 +25,8 @@ background: rgba(42, 42, 42, 0.8); padding: 4px; border-radius: 4px; + max-height: 80%; + overflow-y: auto; } #toolbar input { vertical-align: middle; diff --git a/Apps/Sandcastle/gallery/Fog.html b/Apps/Sandcastle/gallery/Fog.html new file mode 100644 index 00000000000..f22f8c8cc4b --- /dev/null +++ b/Apps/Sandcastle/gallery/Fog.html @@ -0,0 +1,259 @@ + + + + + + + + + Cesium Demo + + + + + + +
+

Loading...

+
+ + + + + + + + + + + + + + + + + + + + + + + +
enabled
density + + +
visual density scalar + + +
Fog min brightness + + +
sse increase factor
+
+
+ + + diff --git a/Apps/Sandcastle/gallery/development/Fog.jpg b/Apps/Sandcastle/gallery/Fog.jpg similarity index 100% rename from Apps/Sandcastle/gallery/development/Fog.jpg rename to Apps/Sandcastle/gallery/Fog.jpg diff --git a/Apps/Sandcastle/gallery/development/Fog.html b/Apps/Sandcastle/gallery/development/Fog.html deleted file mode 100644 index dbd30f10b64..00000000000 --- a/Apps/Sandcastle/gallery/development/Fog.html +++ /dev/null @@ -1,147 +0,0 @@ - - - - - - - - - Cesium Demo - - - - - - -
-

Loading...

-
- - - - - - - - - - - - - - - -
enabled
density
sse increase factor
-
-
- - - diff --git a/CHANGES.md b/CHANGES.md index 5b2c3ee8576..dbe294fbe21 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,9 +4,14 @@ #### @cesium/engine +##### Breaking Changes :mega: + +- Changed the default Fog density scalar from `0.15` to `0.4` to make fog appear more dense. Set `viewer.scene.fog.visualDensityScalar = 0.15` to get the previous behavior. [#12248](https://github.com/CesiumGS/cesium/pull/12248) + ##### Additions :tada: - Added `ScreenSpaceCameraController.maximumTiltAngle` to limit how much the camera can tilt. [#12169](https://github.com/CesiumGS/cesium/pull/12169) +- Exposed `Fog.visualDensityScalar` to allow modifying the visual density of fog without affecting the culling aspects. This defaults to `0.4` but previously had an internal default value of `0.15`. Set `viewer.scene.fog.visualDensityScalar = 0.15` to get the previous behavior. [#12248](https://github.com/CesiumGS/cesium/pull/12248) ##### Fixes :wrench: diff --git a/packages/engine/Source/Core/Math.js b/packages/engine/Source/Core/Math.js index 150cd9aa30a..91579c5f6a8 100644 --- a/packages/engine/Source/Core/Math.js +++ b/packages/engine/Source/Core/Math.js @@ -1048,6 +1048,8 @@ CesiumMath.log2 = defaultValue(Math.log2, function log2(number) { }); /** + * Calculate the fog impact at a given distance. Useful for culling. + * Matches the equation in `fog.glsl` * @private */ CesiumMath.fog = function (distanceToCamera, density) { diff --git a/packages/engine/Source/Renderer/AutomaticUniforms.js b/packages/engine/Source/Renderer/AutomaticUniforms.js index 53e028aca28..73382e649f7 100644 --- a/packages/engine/Source/Renderer/AutomaticUniforms.js +++ b/packages/engine/Source/Renderer/AutomaticUniforms.js @@ -1577,6 +1577,19 @@ const AutomaticUniforms = { }, }), + /** + * An automatic GLSL uniform scalar used to mix a color with the fog color based on the distance to the camera. + * + * @see czm_fog + */ + czm_fogVisualDensityScalar: new AutomaticUniform({ + size: 1, + datatype: WebGLConstants.FLOAT, + getValue: function (uniformState) { + return uniformState.fogVisualDensityScalar; + }, + }), + /** * An automatic GLSL uniform scalar used to set a minimum brightness when dynamic lighting is applied to fog. * diff --git a/packages/engine/Source/Renderer/UniformState.js b/packages/engine/Source/Renderer/UniformState.js index 3c3fa7c4275..a1573dbd722 100644 --- a/packages/engine/Source/Renderer/UniformState.js +++ b/packages/engine/Source/Renderer/UniformState.js @@ -160,6 +160,7 @@ function UniformState() { this._specularEnvironmentMapsMaximumLOD = undefined; this._fogDensity = undefined; + this._fogVisualDensityScalar = undefined; this._fogMinimumBrightness = undefined; this._atmosphereHsbShift = undefined; @@ -924,6 +925,17 @@ Object.defineProperties(UniformState.prototype, { }, }, + /** + * A scalar used to mix a color with the fog color based on the distance to the camera. + * @memberof UniformState.prototype + * @type {number} + */ + fogVisualDensityScalar: { + get: function () { + return this._fogVisualDensityScalar; + }, + }, + /** * A scalar used as a minimum value when brightening fog * @memberof UniformState.prototype @@ -1495,6 +1507,7 @@ UniformState.prototype.update = function (frameState) { frameState.specularEnvironmentMapsMaximumLOD; this._fogDensity = frameState.fog.density; + this._fogVisualDensityScalar = frameState.fog.visualDensityScalar; this._fogMinimumBrightness = frameState.fog.minimumBrightness; const atmosphere = frameState.atmosphere; diff --git a/packages/engine/Source/Scene/Fog.js b/packages/engine/Source/Scene/Fog.js index 9dd4e4e6899..79dd3e9656b 100644 --- a/packages/engine/Source/Scene/Fog.js +++ b/packages/engine/Source/Scene/Fog.js @@ -7,6 +7,8 @@ import SceneMode from "./SceneMode.js"; * Blends the atmosphere to geometry far from the camera for horizon views. Allows for additional * performance improvements by rendering less geometry and dispatching less terrain requests. * + * @demo {@link https://sandcastle.cesium.com/index.html?src=Fog.html|Cesium Sandcastle Fog Demo} + * * @alias Fog * @constructor */ @@ -15,6 +17,9 @@ function Fog() { * true if fog is enabled, false otherwise. * @type {boolean} * @default true + * @example + * // Disable fog in the scene + * viewer.scene.fog.enabled = false; */ this.enabled = true; /** @@ -22,6 +27,10 @@ function Fog() { * This allows to benefits from optimized tile loading strategy based on fog density without the actual visual rendering. * @type {boolean} * @default true + * @example + * // Use fog culling but don't render it + * viewer.scene.fog.enabled = true; + * viewer.scene.fog.renderable = false; */ this.renderable = true; /** @@ -32,8 +41,22 @@ function Fog() { * Decreasing the value will push the fog further from the viewer, but decrease performance as more of the terrain is rendered. * @type {number} * @default 2.0e-4 + * @example + * // Double the default fog density + * viewer.scene.fog.density = 0.0004; */ this.density = 2.0e-4; + /** + * A scalar that impacts the visual density of fog. This value does not impact the culling of terrain. + * Use in combination with the {@link Fog.density} to make fog appear more or less dense. Values above ~3-4 will + * have very diminishing effects. + * @type {number} + * @default 0.4 + * @example + * // Increase fog appearance effect + * viewer.scene.fog.visualDensityScalar = 0.6; + */ + this.visualDensityScalar = 0.4; /** * A factor used to increase the screen space error of terrain tiles when they are partially in fog. The effect is to reduce * the number of terrain tiles requested for rendering. If set to zero, the feature will be disabled. If the value is increased @@ -122,6 +145,10 @@ function findInterval(height) { const scratchPositionNormal = new Cartesian3(); +/** + * @param {FrameState} frameState + * @private + */ Fog.prototype.update = function (frameState) { const enabled = (frameState.fog.enabled = this.enabled); if (!enabled) { @@ -167,6 +194,7 @@ Fog.prototype.update = function (frameState) { density *= 1.0 - dot; frameState.fog.density = density; + frameState.fog.visualDensityScalar = this.visualDensityScalar; frameState.fog.sse = this.screenSpaceErrorFactor; frameState.fog.minimumBrightness = this.minimumBrightness; }; diff --git a/packages/engine/Source/Scene/FrameState.js b/packages/engine/Source/Scene/FrameState.js index f2b45b73c44..36313c10269 100644 --- a/packages/engine/Source/Scene/FrameState.js +++ b/packages/engine/Source/Scene/FrameState.js @@ -261,9 +261,10 @@ function FrameState(context, creditDisplay, jobScheduler) { * @type {object} * @property {boolean} enabled true if fog is enabled, false otherwise. This affects both fog culling and rendering. * @property {boolean} renderable true if fog should be rendered, false if not. This flag should be checked in combination with fog.enabled. - * @property {number} density A positive number used to mix the color and fog color based on camera distance. - * @property {number} sse A scalar used to modify the screen space error of geometry partially in fog. - * @property {number} minimumBrightness The minimum brightness of terrain with fog applied. + * @property {number | undefined} density A positive number used to mix the color and fog color based on camera distance. + * @property {number | undefined} visualDensityScalar A positive number to modify how impactful the fog is based off the density + * @property {number | undefined} sse A scalar used to modify the screen space error of geometry partially in fog. + * @property {number | undefined} minimumBrightness The minimum brightness of terrain with fog applied. */ /** @@ -277,6 +278,7 @@ function FrameState(context, creditDisplay, jobScheduler) { enabled: false, renderable: false, density: undefined, + visualDensityScalar: undefined, sse: undefined, minimumBrightness: undefined, }; diff --git a/packages/engine/Source/Scene/Model/AtmospherePipelineStage.js b/packages/engine/Source/Scene/Model/AtmospherePipelineStage.js index 11128da39bd..c16aceb98b7 100644 --- a/packages/engine/Source/Scene/Model/AtmospherePipelineStage.js +++ b/packages/engine/Source/Scene/Model/AtmospherePipelineStage.js @@ -16,12 +16,17 @@ const AtmospherePipelineStage = { name: "AtmospherePipelineStage", // Helps with debugging }; +/** + * @param {ModelRenderResources} modelRenderResources + * @param {Model} model + * @param {FrameState} frameState + */ AtmospherePipelineStage.process = function ( - renderResources, + modelRenderResources, model, frameState, ) { - const shaderBuilder = renderResources.shaderBuilder; + const shaderBuilder = modelRenderResources.shaderBuilder; shaderBuilder.addDefine("HAS_ATMOSPHERE", undefined, ShaderDestination.BOTH); shaderBuilder.addDefine( @@ -37,12 +42,12 @@ AtmospherePipelineStage.process = function ( shaderBuilder.addVertexLines([AtmosphereStageVS]); shaderBuilder.addFragmentLines([AtmosphereStageFS]); - // Add a uniform so fog is only calculated when the efcfect would - // be non-negligible For example when the camera is in space, fog density decreases + // Add a uniform so fog is only calculated when the effect would + // be non-negligible. For example when the camera is in space, fog density decreases // to 0 so fog shouldn't be rendered. Since this state may change rapidly if // the camera is moving, this is implemented as a uniform, not a define. shaderBuilder.addUniform("bool", "u_isInFog", ShaderDestination.FRAGMENT); - renderResources.uniformMap.u_isInFog = function () { + modelRenderResources.uniformMap.u_isInFog = function () { // We only need a rough measure of distance to the model, so measure // from the camera to the bounding sphere center. const distance = Cartesian3.distance( diff --git a/packages/engine/Source/Scene/Model/ModelSceneGraph.js b/packages/engine/Source/Scene/Model/ModelSceneGraph.js index 11e3918c058..248ee80f340 100644 --- a/packages/engine/Source/Scene/Model/ModelSceneGraph.js +++ b/packages/engine/Source/Scene/Model/ModelSceneGraph.js @@ -601,6 +601,7 @@ ModelSceneGraph.prototype.buildDrawCommands = function (frameState) { * this method again to ensure the correct sequence of pipeline stages are * used. * + * @param {FrameState} frameState * @private */ ModelSceneGraph.prototype.configurePipeline = function (frameState) { diff --git a/packages/engine/Source/Shaders/GlobeFS.glsl b/packages/engine/Source/Shaders/GlobeFS.glsl index 2c9df10caf0..be303326adb 100644 --- a/packages/engine/Source/Shaders/GlobeFS.glsl +++ b/packages/engine/Source/Shaders/GlobeFS.glsl @@ -499,8 +499,7 @@ void main() fogColor.rgb = czm_inverseGamma(fogColor.rgb); #endif - const float modifier = 0.15; - finalColor = vec4(czm_fog(v_distance, finalColor.rgb, fogColor.rgb, modifier), finalColor.a); + finalColor = vec4(czm_fog(v_distance, finalColor.rgb, fogColor.rgb, czm_fogVisualDensityScalar), finalColor.a); #else // Apply ground atmosphere. This happens when the camera is far away from the earth. diff --git a/packages/engine/Source/Shaders/Model/AtmosphereStageFS.glsl b/packages/engine/Source/Shaders/Model/AtmosphereStageFS.glsl index e46dc6e6878..4c586ab096f 100644 --- a/packages/engine/Source/Shaders/Model/AtmosphereStageFS.glsl +++ b/packages/engine/Source/Shaders/Model/AtmosphereStageFS.glsl @@ -56,10 +56,7 @@ void applyFog(inout vec4 color, vec4 groundAtmosphereColor, vec3 lightDirection, fogColor.rgb = czm_inverseGamma(fogColor.rgb); #endif - // Matches the constant in GlobeFS.glsl. This makes the fog falloff - // more gradual. - const float fogModifier = 0.15; - vec3 withFog = czm_fog(distanceToCamera, color.rgb, fogColor, fogModifier); + vec3 withFog = czm_fog(distanceToCamera, color.rgb, fogColor, czm_fogVisualDensityScalar); color = vec4(withFog, color.a); }