From 5ec99b2d6e5aa3b126c7b1b8511a5e0e2cd4eb9d Mon Sep 17 00:00:00 2001 From: jjspace <8007967+jjspace@users.noreply.github.com> Date: Thu, 10 Oct 2024 12:01:00 -0400 Subject: [PATCH 01/11] expose new scalar to change the visual density of fog --- Apps/Sandcastle/gallery/Atmosphere.html | 2 + Apps/Sandcastle/gallery/development/Fog.html | 196 ++++++++++++++---- packages/engine/Source/Core/Math.js | 2 + .../Source/Renderer/AutomaticUniforms.js | 14 ++ .../engine/Source/Renderer/UniformState.js | 13 ++ packages/engine/Source/Scene/Fog.js | 9 + packages/engine/Source/Scene/FrameState.js | 8 +- .../Scene/Model/AtmospherePipelineStage.js | 15 +- .../Source/Scene/Model/ModelSceneGraph.js | 1 + packages/engine/Source/Shaders/GlobeFS.glsl | 3 +- .../Shaders/Model/AtmosphereStageFS.glsl | 5 +- 11 files changed, 214 insertions(+), 54 deletions(-) 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/development/Fog.html b/Apps/Sandcastle/gallery/development/Fog.html index dbd30f10b64..6b427b22a50 100644 --- a/Apps/Sandcastle/gallery/development/Fog.html +++ b/Apps/Sandcastle/gallery/development/Fog.html @@ -21,6 +21,22 @@

Loading...

@@ -33,7 +49,60 @@ density - + + + + + + + visual density scalar + + + + + + + Fog min brightness + + + + sse increase factor @@ -57,7 +126,9 @@ const viewModel = { enabled: true, density: 0, + visualDensityScalar: 0, sse: 0, + minimumBrightness: 0, }; // Convert the viewModel members into knockout observables. Cesium.knockout.track(viewModel); @@ -78,60 +149,105 @@ viewer.scene.fog.density = newValue; }); + Cesium.knockout + .getObservable(viewModel, "visualDensityScalar") + .subscribe(function (newValue) { + viewer.scene.fog.visualDensityScalar = newValue; + }); + + Cesium.knockout + .getObservable(viewModel, "minimumBrightness") + .subscribe(function (newValue) { + viewer.scene.fog.minimumBrightness = newValue; + }); Cesium.knockout.getObservable(viewModel, "sse").subscribe(function (newValue) { viewer.scene.fog.screenSpaceErrorFactor = newValue; }); viewModel.enabled = viewer.scene.fog.enabled; viewModel.density = viewer.scene.fog.density; + viewModel.visualDensityScalar = viewer.scene.fog.visualDensityScalar; viewModel.sse = viewer.scene.fog.screenSpaceErrorFactor; + viewModel.minimumBrightness = viewer.scene.fog.minimumBrightness; - Sandcastle.addToolbarButton("Horizon high altitude", function () { - viewer.camera.setView({ - destination: new Cesium.Cartesian3( - -2467730.5740817646, - -4390507.315824514, - 3906155.113316938, - ), - orientation: { - heading: 4.492211521856625, - pitch: -0.2687139437696304, - }, - }); + Sandcastle.addToolbarButton( + "Horizon high altitude", + function () { + viewer.camera.setView({ + destination: new Cesium.Cartesian3( + -2467730.5740817646, + -4390507.315824514, + 3906155.113316938, + ), + orientation: { + heading: 4.492211521856625, + pitch: -0.2687139437696304, + }, + }); + }, + "zoomButtons", + ); + // default to the high altitude camera + viewer.camera.setView({ + destination: new Cesium.Cartesian3( + -2467730.5740817646, + -4390507.315824514, + 3906155.113316938, + ), + orientation: { + heading: 4.492211521856625, + pitch: -0.2687139437696304, + }, }); - Sandcastle.addToolbarButton("Horizon low altitude", function () { - viewer.camera.setView({ - destination: new Cesium.Cartesian3( - -734001.9511656855, - -4214090.596769834, - 4715898.125886317, - ), - orientation: { - heading: 5.634257362559497, - pitch: -0.019548505785381032, - }, - }); - }); + Sandcastle.addToolbarButton( + "Horizon low altitude", + function () { + viewer.camera.setView({ + destination: new Cesium.Cartesian3( + -734001.9511656855, + -4214090.596769834, + 4715898.125886317, + ), + orientation: { + heading: 5.634257362559497, + pitch: -0.019548505785381032, + }, + }); + }, + "zoomButtons", + ); viewer.scene.globe._surface._debug.enableDebugOutput = true; - Sandcastle.addToolbarButton("Snap", function () { - const container = document.getElementById("cesiumContainer"); - const tmpH = container.style.height; - const tmpW = container.style.width; + Sandcastle.addToolbarButton( + "Snapshot", + function () { + const container = document.getElementById("cesiumContainer"); + const tmpH = container.style.height; + const tmpW = container.style.width; - container.style.height = "600px"; - container.style.width = "800px"; + // resize for screenshot + container.style.height = "600px"; + container.style.width = "800px"; + viewer.resize(); + viewer.render(); - viewer.resize(); - viewer.render(); - window.open(viewer.canvas.toDataURL("image/png")); - container.style.height = tmpH; - container.style.width = tmpW; - viewer.resize(); - viewer.render(); - }); + // chrome blocks opening data urls directly, add an image to a new window instead + // https://stackoverflow.com/questions/45778720/window-open-opens-a-blank-screen-in-chrome + const win = window.open(); + win.document.write(``); + // stop the browser from trying to load "nothing" forever + win.stop(); + + // reset viewer size + container.style.height = tmpH; + container.style.width = tmpW; + viewer.resize(); + viewer.render(); + }, + "zoomButtons", + ); //Sandcastle_End }; if (typeof Cesium !== "undefined") { diff --git a/packages/engine/Source/Core/Math.js b/packages/engine/Source/Core/Math.js index 150cd9aa30a..12755e4be7a 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..4cb4987d36f 100644 --- a/packages/engine/Source/Renderer/AutomaticUniforms.js +++ b/packages/engine/Source/Renderer/AutomaticUniforms.js @@ -1577,6 +1577,20 @@ 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; + // return 4.0; + }, + }), + /** * 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..1fd4563b898 100644 --- a/packages/engine/Source/Scene/Fog.js +++ b/packages/engine/Source/Scene/Fog.js @@ -34,6 +34,11 @@ function Fog() { * @default 2.0e-4 */ 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 `density` to make fog appear more or less dense. + */ + 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 +127,9 @@ function findInterval(height) { const scratchPositionNormal = new Cartesian3(); +/** + * @param {FrameState} frameState + */ Fog.prototype.update = function (frameState) { const enabled = (frameState.fog.enabled = this.enabled); if (!enabled) { @@ -167,6 +175,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); } From 8417242a40da5742780c1f7b98e46e427258a0a5 Mon Sep 17 00:00:00 2001 From: jjspace <8007967+jjspace@users.noreply.github.com> Date: Thu, 10 Oct 2024 12:21:26 -0400 Subject: [PATCH 02/11] fix types --- packages/engine/Source/Scene/Fog.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/engine/Source/Scene/Fog.js b/packages/engine/Source/Scene/Fog.js index 1fd4563b898..84ed68b40f9 100644 --- a/packages/engine/Source/Scene/Fog.js +++ b/packages/engine/Source/Scene/Fog.js @@ -129,6 +129,7 @@ const scratchPositionNormal = new Cartesian3(); /** * @param {FrameState} frameState + * @private */ Fog.prototype.update = function (frameState) { const enabled = (frameState.fog.enabled = this.enabled); From 305fc1aded922fade464b9b4531fc6ac7c7727cb Mon Sep 17 00:00:00 2001 From: jjspace <8007967+jjspace@users.noreply.github.com> Date: Fri, 11 Oct 2024 15:15:09 -0400 Subject: [PATCH 03/11] doc updates --- CHANGES.md | 1 + packages/engine/Source/Core/Math.js | 2 +- .../Source/Renderer/AutomaticUniforms.js | 1 - packages/engine/Source/Scene/Fog.js | 23 +++++++++++++++++-- 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 806d9b21907..c56a71c04d4 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,6 +7,7 @@ ##### 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) ### 1.122 - 2024-10-01 diff --git a/packages/engine/Source/Core/Math.js b/packages/engine/Source/Core/Math.js index 12755e4be7a..91579c5f6a8 100644 --- a/packages/engine/Source/Core/Math.js +++ b/packages/engine/Source/Core/Math.js @@ -1048,7 +1048,7 @@ CesiumMath.log2 = defaultValue(Math.log2, function log2(number) { }); /** - * Calculate the fog impact at a given distance. useful for culling. + * Calculate the fog impact at a given distance. Useful for culling. * Matches the equation in `fog.glsl` * @private */ diff --git a/packages/engine/Source/Renderer/AutomaticUniforms.js b/packages/engine/Source/Renderer/AutomaticUniforms.js index 4cb4987d36f..73382e649f7 100644 --- a/packages/engine/Source/Renderer/AutomaticUniforms.js +++ b/packages/engine/Source/Renderer/AutomaticUniforms.js @@ -1587,7 +1587,6 @@ const AutomaticUniforms = { datatype: WebGLConstants.FLOAT, getValue: function (uniformState) { return uniformState.fogVisualDensityScalar; - // return 4.0; }, }), diff --git a/packages/engine/Source/Scene/Fog.js b/packages/engine/Source/Scene/Fog.js index 84ed68b40f9..2a1dd52261d 100644 --- a/packages/engine/Source/Scene/Fog.js +++ b/packages/engine/Source/Scene/Fog.js @@ -7,6 +7,9 @@ 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. * + * View the {@link http://localhost:8080/Apps/Sandcastle/index.html?src=development%2FFog.html|Fog Sandcastle} + * to explore the effects of the properties below + * * @alias Fog * @constructor */ @@ -15,6 +18,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 +28,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 do't render it + * viewer.scene.fog.enabled = true; + * viewer.scene.fog.renderable = false; */ this.renderable = true; /** @@ -32,11 +42,20 @@ 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 `density` to make fog appear more or less dense. + * 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; /** From cc721ac18636460d6618dc4b314942fab0f59066 Mon Sep 17 00:00:00 2001 From: jjspace <8007967+jjspace@users.noreply.github.com> Date: Mon, 21 Oct 2024 14:23:24 -0400 Subject: [PATCH 04/11] doc adjustments, move fog sandcastle --- Apps/Sandcastle/gallery/{development => }/Fog.html | 0 Apps/Sandcastle/gallery/{development => }/Fog.jpg | Bin CHANGES.md | 4 ++++ packages/engine/Source/Scene/Fog.js | 5 ++--- 4 files changed, 6 insertions(+), 3 deletions(-) rename Apps/Sandcastle/gallery/{development => }/Fog.html (100%) rename Apps/Sandcastle/gallery/{development => }/Fog.jpg (100%) diff --git a/Apps/Sandcastle/gallery/development/Fog.html b/Apps/Sandcastle/gallery/Fog.html similarity index 100% rename from Apps/Sandcastle/gallery/development/Fog.html rename to Apps/Sandcastle/gallery/Fog.html 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/CHANGES.md b/CHANGES.md index c56a71c04d4..72fb5d2e969 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,6 +4,10 @@ #### @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) diff --git a/packages/engine/Source/Scene/Fog.js b/packages/engine/Source/Scene/Fog.js index 2a1dd52261d..79dd3e9656b 100644 --- a/packages/engine/Source/Scene/Fog.js +++ b/packages/engine/Source/Scene/Fog.js @@ -7,8 +7,7 @@ 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. * - * View the {@link http://localhost:8080/Apps/Sandcastle/index.html?src=development%2FFog.html|Fog Sandcastle} - * to explore the effects of the properties below + * @demo {@link https://sandcastle.cesium.com/index.html?src=Fog.html|Cesium Sandcastle Fog Demo} * * @alias Fog * @constructor @@ -29,7 +28,7 @@ function Fog() { * @type {boolean} * @default true * @example - * // Use fog culling but do't render it + * // Use fog culling but don't render it * viewer.scene.fog.enabled = true; * viewer.scene.fog.renderable = false; */ From 2e6f488e4bb781c3fd1e4f271815947147f3b230 Mon Sep 17 00:00:00 2001 From: jjspace <8007967+jjspace@users.noreply.github.com> Date: Mon, 21 Oct 2024 15:41:14 -0400 Subject: [PATCH 05/11] remove debug oriented code in sandcastle --- Apps/Sandcastle/gallery/Fog.html | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Apps/Sandcastle/gallery/Fog.html b/Apps/Sandcastle/gallery/Fog.html index 6b427b22a50..f22f8c8cc4b 100644 --- a/Apps/Sandcastle/gallery/Fog.html +++ b/Apps/Sandcastle/gallery/Fog.html @@ -120,8 +120,6 @@ terrain: Cesium.Terrain.fromWorldTerrain(), }); - viewer.extend(Cesium.viewerCesiumInspectorMixin); - //The viewModel tracks the state of our mini application. const viewModel = { enabled: true, @@ -218,8 +216,6 @@ "zoomButtons", ); - viewer.scene.globe._surface._debug.enableDebugOutput = true; - Sandcastle.addToolbarButton( "Snapshot", function () { From 05a4f8f8d83af9a161034dea2ccee6dbccea4e9f Mon Sep 17 00:00:00 2001 From: jjspace <8007967+jjspace@users.noreply.github.com> Date: Wed, 23 Oct 2024 14:19:32 -0400 Subject: [PATCH 06/11] change fog density per height calculation to a smooth curve --- Apps/Sandcastle/gallery/Fog.html | 125 +++++++++++++++++++++++++++- packages/engine/Source/Scene/Fog.js | 117 +++++++------------------- 2 files changed, 153 insertions(+), 89 deletions(-) diff --git a/Apps/Sandcastle/gallery/Fog.html b/Apps/Sandcastle/gallery/Fog.html index f22f8c8cc4b..1b7a2ca3da7 100644 --- a/Apps/Sandcastle/gallery/Fog.html +++ b/Apps/Sandcastle/gallery/Fog.html @@ -72,14 +72,14 @@ @@ -106,7 +106,37 @@ sse increase factor - + + + + fogScalar + + + + + + heightFalloff + + + + + + maxHeight + + + @@ -127,6 +157,9 @@ visualDensityScalar: 0, sse: 0, minimumBrightness: 0, + fogScalar: 0, + heightFalloff: 0, + maxHeight: 0, }; // Convert the viewModel members into knockout observables. Cesium.knockout.track(viewModel); @@ -161,12 +194,30 @@ Cesium.knockout.getObservable(viewModel, "sse").subscribe(function (newValue) { viewer.scene.fog.screenSpaceErrorFactor = newValue; }); + Cesium.knockout + .getObservable(viewModel, "fogScalar") + .subscribe(function (newValue) { + viewer.scene.fog.fogScalar = newValue; + }); + Cesium.knockout + .getObservable(viewModel, "heightFalloff") + .subscribe(function (newValue) { + viewer.scene.fog.heightFalloff = newValue; + }); + Cesium.knockout + .getObservable(viewModel, "maxHeight") + .subscribe(function (newValue) { + viewer.scene.fog.maxHeight = newValue; + }); viewModel.enabled = viewer.scene.fog.enabled; viewModel.density = viewer.scene.fog.density; viewModel.visualDensityScalar = viewer.scene.fog.visualDensityScalar; viewModel.sse = viewer.scene.fog.screenSpaceErrorFactor; viewModel.minimumBrightness = viewer.scene.fog.minimumBrightness; + viewModel.fogScalar = viewer.scene.fog.fogScalar; + viewModel.heightFalloff = viewer.scene.fog.heightFalloff; + viewModel.maxHeight = viewer.scene.fog.maxHeight; Sandcastle.addToolbarButton( "Horizon high altitude", @@ -244,6 +295,74 @@ }, "zoomButtons", ); + + const cameraLocation1 = { + destination: new Cesium.Cartesian3( + -2693797.551060477, + -4297135.517094725, + 3854700.7470414364, + ), + orientation: new Cesium.HeadingPitchRoll( + 4.6550106925119925, + -0.2863894863138836, + 1.3561760425773173e-7, + ), + duration: 5, + easingFunction: Cesium.EasingFunction.LINEAR_NONE, + }; + + const cameraLocation2 = { + destination: new Cesium.Cartesian3( + -2687646.8093284643, + -4303700.035604263, + 3856784.833121914, + ), + orientation: new Cesium.HeadingPitchRoll( + 4.655010692511992, + -0.28638948631389805, + 1.356176033695533e-7, + ), + duration: 5, + easingFunction: Cesium.EasingFunction.LINEAR_NONE, + }; + + const cameraLocation3 = { + destination: new Cesium.Cartesian3( + -2398620.5757977725, + -4599087.046897942, + 3953783.620126758, + ), + orientation: new Cesium.HeadingPitchRoll( + 4.655010692512, + -0.2863894863139227, + 1.356176024813749e-7, + ), + duration: 5, + easingFunction: Cesium.EasingFunction.LINEAR_NONE, + }; + + const delay = (ms) => new Promise((r) => setTimeout(r, ms)); + async function flightPath(locations, timeAtEach) { + viewer.camera.setView(locations[0]); + for (const location of locations) { + await new Promise((resolve) => { + viewer.camera.flyTo({ + ...location, + complete: () => resolve(), + }); + }); + await delay(timeAtEach); + } + } + + // Zoom and an out tests to see how the fog settings apply over a range of heights + Sandcastle.addToolbarButton("Zoom Out Test", function () { + flightPath([cameraLocation1, cameraLocation2, cameraLocation3], 1000); + }); + Sandcastle.addToolbarButton("Zoom In Test", function () { + flightPath([cameraLocation3, cameraLocation2, cameraLocation1], 1000); + }); + //Sandcastle_End }; if (typeof Cesium !== "undefined") { diff --git a/packages/engine/Source/Scene/Fog.js b/packages/engine/Source/Scene/Fog.js index 79dd3e9656b..30de83c9f16 100644 --- a/packages/engine/Source/Scene/Fog.js +++ b/packages/engine/Source/Scene/Fog.js @@ -1,6 +1,5 @@ import Cartesian3 from "../Core/Cartesian3.js"; import defined from "../Core/defined.js"; -import CesiumMath from "../Core/Math.js"; import SceneMode from "./SceneMode.js"; /** @@ -46,17 +45,36 @@ function Fog() { * viewer.scene.fog.density = 0.0004; */ this.density = 2.0e-4; + /** + * A scalar used in the function to adjust density based on the height of the camera above the terrain. + * @type {number} + * @default 0.001 + */ + this.fogScalar = 0.001; + /** + * Exponent factor used in the function to adjust density based on the height of the camera. Higher values will lead + * to more dense fog at lower heights and a slower falloff as you get higher. + * Positive values only, if the value is negative it will be clamped to 0; + * @type {number} + * @default 0.52 + */ + this.heightFalloff = 0.52; + /** + * The maximum height fog is applied. If the camera is above this height fog will be disabled. + * @type {number} + * @default 800000.0 + */ + this.maxHeight = 800000.0; /** * 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. + * Use in combination with the {@link Fog.density} to make fog appear more or less dense. * @type {number} - * @default 0.4 + * @default 1.0 * @example * // Increase fog appearance effect * viewer.scene.fog.visualDensityScalar = 0.6; */ - this.visualDensityScalar = 0.4; + this.visualDensityScalar = 1.0; /** * 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 @@ -75,74 +93,6 @@ function Fog() { this.minimumBrightness = 0.03; } -// These values were found by sampling the density at certain views and finding at what point culled tiles impacted the view at the horizon. -const heightsTable = [ - 359.393, 800.749, 1275.6501, 2151.1192, 3141.7763, 4777.5198, 6281.2493, - 12364.307, 15900.765, 49889.0549, 78026.8259, 99260.7344, 120036.3873, - 151011.0158, 156091.1953, 203849.3112, 274866.9803, 319916.3149, 493552.0528, - 628733.5874, -]; -const densityTable = [ - 2.0e-5, 2.0e-4, 1.0e-4, 7.0e-5, 5.0e-5, 4.0e-5, 3.0e-5, 1.9e-5, 1.0e-5, - 8.5e-6, 6.2e-6, 5.8e-6, 5.3e-6, 5.2e-6, 5.1e-6, 4.2e-6, 4.0e-6, 3.4e-6, - 2.6e-6, 2.2e-6, -]; - -// Scale densities by 1e6 to bring lowest value to ~1. Prevents divide by zero. -for (let i = 0; i < densityTable.length; ++i) { - densityTable[i] *= 1.0e6; -} -// Change range to [0, 1]. -const tableStartDensity = densityTable[1]; -const tableEndDensity = densityTable[densityTable.length - 1]; -for (let j = 0; j < densityTable.length; ++j) { - densityTable[j] = - (densityTable[j] - tableEndDensity) / (tableStartDensity - tableEndDensity); -} - -let tableLastIndex = 0; - -function findInterval(height) { - const heights = heightsTable; - const length = heights.length; - - if (height < heights[0]) { - tableLastIndex = 0; - return tableLastIndex; - } else if (height > heights[length - 1]) { - tableLastIndex = length - 2; - return tableLastIndex; - } - - // Take advantage of temporal coherence by checking current, next and previous intervals - // for containment of time. - if (height >= heights[tableLastIndex]) { - if (tableLastIndex + 1 < length && height < heights[tableLastIndex + 1]) { - return tableLastIndex; - } else if ( - tableLastIndex + 2 < length && - height < heights[tableLastIndex + 2] - ) { - ++tableLastIndex; - return tableLastIndex; - } - } else if (tableLastIndex - 1 >= 0 && height >= heights[tableLastIndex - 1]) { - --tableLastIndex; - return tableLastIndex; - } - - // The above failed so do a linear search. - let i; - for (i = 0; i < length - 2; ++i) { - if (height >= heights[i] && height < heights[i + 1]) { - break; - } - } - - tableLastIndex = i; - return tableLastIndex; -} - const scratchPositionNormal = new Cartesian3(); /** @@ -163,7 +113,7 @@ Fog.prototype.update = function (frameState) { // Turn off fog in space. if ( !defined(positionCartographic) || - positionCartographic.height > 800000.0 || + positionCartographic.height > this.maxHeight || frameState.mode !== SceneMode.SCENE3D ) { frameState.fog.enabled = false; @@ -172,18 +122,13 @@ Fog.prototype.update = function (frameState) { } const height = positionCartographic.height; - const i = findInterval(height); - const t = CesiumMath.clamp( - (height - heightsTable[i]) / (heightsTable[i + 1] - heightsTable[i]), - 0.0, - 1.0, - ); - let density = CesiumMath.lerp(densityTable[i], densityTable[i + 1], t); - - // Again, scale value to be in the range of densityTable (prevents divide by zero) and change to new range. - const startDensity = this.density * 1.0e6; - const endDensity = (startDensity / tableStartDensity) * tableEndDensity; - density = density * (startDensity - endDensity) * 1.0e-6; + let density = + this.density * + this.fogScalar * + Math.pow( + Math.max(height / this.maxHeight, 1e-6), + -Math.max(this.heightFalloff, 0), + ); // Fade fog in as the camera tilts toward the horizon. const positionNormal = Cartesian3.normalize( From f98bc630ab96f7df2e54f912581a93b53bc24904 Mon Sep 17 00:00:00 2001 From: jjspace <8007967+jjspace@users.noreply.github.com> Date: Thu, 24 Oct 2024 13:55:46 -0400 Subject: [PATCH 07/11] pr comment cleanup --- Apps/Sandcastle/gallery/Fog.html | 12 ++++---- packages/engine/Source/Scene/Fog.js | 43 +++++++++++++++++++++-------- 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/Apps/Sandcastle/gallery/Fog.html b/Apps/Sandcastle/gallery/Fog.html index 1b7a2ca3da7..07f8612b19c 100644 --- a/Apps/Sandcastle/gallery/Fog.html +++ b/Apps/Sandcastle/gallery/Fog.html @@ -109,14 +109,14 @@ - fogScalar + heightScalar @@ -157,7 +157,7 @@ visualDensityScalar: 0, sse: 0, minimumBrightness: 0, - fogScalar: 0, + heightScalar: 0, heightFalloff: 0, maxHeight: 0, }; @@ -195,9 +195,9 @@ viewer.scene.fog.screenSpaceErrorFactor = newValue; }); Cesium.knockout - .getObservable(viewModel, "fogScalar") + .getObservable(viewModel, "heightScalar") .subscribe(function (newValue) { - viewer.scene.fog.fogScalar = newValue; + viewer.scene.fog.heightScalar = newValue; }); Cesium.knockout .getObservable(viewModel, "heightFalloff") @@ -215,7 +215,7 @@ viewModel.visualDensityScalar = viewer.scene.fog.visualDensityScalar; viewModel.sse = viewer.scene.fog.screenSpaceErrorFactor; viewModel.minimumBrightness = viewer.scene.fog.minimumBrightness; - viewModel.fogScalar = viewer.scene.fog.fogScalar; + viewModel.heightScalar = viewer.scene.fog.heightScalar; viewModel.heightFalloff = viewer.scene.fog.heightFalloff; viewModel.maxHeight = viewer.scene.fog.maxHeight; diff --git a/packages/engine/Source/Scene/Fog.js b/packages/engine/Source/Scene/Fog.js index 30de83c9f16..36f05c85fd7 100644 --- a/packages/engine/Source/Scene/Fog.js +++ b/packages/engine/Source/Scene/Fog.js @@ -1,5 +1,7 @@ import Cartesian3 from "../Core/Cartesian3.js"; import defined from "../Core/defined.js"; +import DeveloperError from "../Core/DeveloperError.js"; +import CesiumMath from "../Core/Math.js"; import SceneMode from "./SceneMode.js"; /** @@ -50,15 +52,8 @@ function Fog() { * @type {number} * @default 0.001 */ - this.fogScalar = 0.001; - /** - * Exponent factor used in the function to adjust density based on the height of the camera. Higher values will lead - * to more dense fog at lower heights and a slower falloff as you get higher. - * Positive values only, if the value is negative it will be clamped to 0; - * @type {number} - * @default 0.52 - */ - this.heightFalloff = 0.52; + this.heightScalar = 0.001; + this._heightFalloff = 0.52; /** * The maximum height fog is applied. If the camera is above this height fog will be disabled. * @type {number} @@ -93,6 +88,30 @@ function Fog() { this.minimumBrightness = 0.03; } +Object.defineProperties(Fog.prototype, { + /** + * Exponent factor used in the function to adjust how density changes based on the height of the camera above the ellipsoid. Smaller values produce a more gradual transition as camera height increases. + * Value must be greater than 0. + * @memberof Fog.prototype + * @type {number} + * @default 0.52 + */ + heightFalloff: { + get: function () { + return this._heightFalloff; + }, + set: function (value) { + //>>includeStart('debug', pragmas.debug); + if (defined(value) && value < 0) { + throw new DeveloperError("value must be positive."); + } + //>>includeEnd('debug'); + + this._heightFalloff = value; + }, + }, +}); + const scratchPositionNormal = new Cartesian3(); /** @@ -124,10 +143,10 @@ Fog.prototype.update = function (frameState) { const height = positionCartographic.height; let density = this.density * - this.fogScalar * + this.heightScalar * Math.pow( - Math.max(height / this.maxHeight, 1e-6), - -Math.max(this.heightFalloff, 0), + Math.max(height / this.maxHeight, CesiumMath.EPSILON6), + -Math.max(this._heightFalloff, 0.0), ); // Fade fog in as the camera tilts toward the horizon. From 82aa3f087b0999bd737dd1758d94e6de9824ad1d Mon Sep 17 00:00:00 2001 From: jjspace <8007967+jjspace@users.noreply.github.com> Date: Mon, 28 Oct 2024 16:52:42 -0400 Subject: [PATCH 08/11] update specs --- packages/engine/Source/Scene/Fog.js | 9 +- packages/engine/Specs/Scene/FogSpec.js | 170 ++++++++++++++++++ .../Model/AtmospherePipelineStageSpec.js | 2 +- packages/engine/Specs/Scene/SceneSpec.js | 2 + 4 files changed, 178 insertions(+), 5 deletions(-) create mode 100644 packages/engine/Specs/Scene/FogSpec.js diff --git a/packages/engine/Source/Scene/Fog.js b/packages/engine/Source/Scene/Fog.js index 36f05c85fd7..21df1ea29d9 100644 --- a/packages/engine/Source/Scene/Fog.js +++ b/packages/engine/Source/Scene/Fog.js @@ -41,19 +41,19 @@ function Fog() { * 1000.0m above the ellipsoid, increasing the value to 3.0e-3 will cause many tiles close to the viewer be culled. * 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 + * @default 0.0006 * @example * // Double the default fog density * viewer.scene.fog.density = 0.0004; */ - this.density = 2.0e-4; + this.density = 0.0006; /** * A scalar used in the function to adjust density based on the height of the camera above the terrain. * @type {number} * @default 0.001 */ this.heightScalar = 0.001; - this._heightFalloff = 0.52; + this._heightFalloff = 0.59; /** * The maximum height fog is applied. If the camera is above this height fog will be disabled. * @type {number} @@ -65,6 +65,7 @@ function Fog() { * Use in combination with the {@link Fog.density} to make fog appear more or less dense. * @type {number} * @default 1.0 + * @experimental The value of this scalar may not be final and is subject to change. * @example * // Increase fog appearance effect * viewer.scene.fog.visualDensityScalar = 0.6; @@ -94,7 +95,7 @@ Object.defineProperties(Fog.prototype, { * Value must be greater than 0. * @memberof Fog.prototype * @type {number} - * @default 0.52 + * @default 0.59 */ heightFalloff: { get: function () { diff --git a/packages/engine/Specs/Scene/FogSpec.js b/packages/engine/Specs/Scene/FogSpec.js new file mode 100644 index 00000000000..746ebca9ffb --- /dev/null +++ b/packages/engine/Specs/Scene/FogSpec.js @@ -0,0 +1,170 @@ +import { Fog, Math as CesiumMath, SceneMode } from "../../index.js"; +import createCanvas from "../../../../Specs/createCanvas.js"; +import createScene from "../../../../Specs/createScene.js"; + +describe("Fog", () => { + describe("update", () => { + /** @type {Scene} */ + let scene; + /** @type {Fog} */ + let fog; + + beforeEach(() => { + fog = new Fog(); + scene = createScene({ + canvas: createCanvas(10, 10), + }); + }); + + afterEach(function () { + scene.destroyForSpecs(); + }); + + it("disabled when above max height", () => { + fog.maxHeight = 800000; // default + const frameState = scene.frameState; + + frameState.camera.positionCartographic.height = 800001; + fog.update(frameState); + expect(frameState.fog.enabled) + .withContext(`at height 800001`) + .toBeFalse(); + frameState.camera.positionCartographic.height = 5000; + fog.update(frameState); + expect(frameState.fog.enabled).withContext(`at height 5000`).toBeTrue(); + + fog.maxHeight = 5000; + + frameState.camera.positionCartographic.height = 5001; + fog.update(frameState); + expect(frameState.fog.enabled).withContext(`at height 5001`).toBeFalse(); + frameState.camera.positionCartographic.height = 4000; + fog.update(frameState); + expect(frameState.fog.enabled).withContext(`at height 4000`).toBeTrue(); + }); + + it("passes through expected values unaltered", () => { + fog.screenSpaceErrorFactor = 11; + fog.visualDensityScalar = 12; + fog.minimumBrightness = 13; + + const frameState = scene.frameState; + frameState.camera.positionCartographic.height = 10000; + fog.update(frameState); + console.log(frameState); + + expect(frameState.fog.enabled).toBeTrue(); + expect(frameState.fog.density).toBeGreaterThan(0); + + expect(frameState.fog.sse).toEqual(11); + expect(frameState.fog.visualDensityScalar).toEqual(12); + expect(frameState.fog.minimumBrightness).toEqual(13); + }); + + it("density is 0 when not in 3D", () => { + const frameState = scene.frameState; + + frameState.mode = SceneMode.SCENE2D; + fog.update(frameState); + expect(frameState.fog.density).toEqual(0); + }); + + describe("density function", () => { + beforeEach(() => { + fog = new Fog(); + }); + + it("density is 0 above max height", () => { + fog.maxHeight = 800000; // default + const frameState = scene.frameState; + + frameState.camera.positionCartographic.height = 800001; + fog.update(frameState); + expect(frameState.fog.density) + .withContext(`at height 800001`) + .toEqual(0); + frameState.camera.positionCartographic.height = 5000; + fog.update(frameState); + expect(frameState.fog.density) + .withContext(`at height 5000`) + .not.toEqual(0); + + fog.maxHeight = 5000; + + frameState.camera.positionCartographic.height = 5001; + fog.update(frameState); + expect(frameState.fog.density).withContext(`at height 5001`).toEqual(0); + frameState.camera.positionCartographic.height = 4000; + fog.update(frameState); + expect(frameState.fog.density) + .withContext(`at height 4000`) + .not.toEqual(0); + }); + + function testDensityAtHeight( + height, + expectedDensity, + epsilon = CesiumMath.EPSILON5, + ) { + const frameState = scene.frameState; + frameState.camera.positionCartographic.height = height; + fog.update(frameState); + expect(frameState.fog.density) + .withContext(`at height ${height}`) + .toEqualEpsilon(expectedDensity, epsilon); + } + + it("default density, close to the ground", () => { + testDensityAtHeight(1, 2.3e-9, CesiumMath.EPSILON10); + testDensityAtHeight(10, 5.9e-10, CesiumMath.EPSILON11); + testDensityAtHeight(20, 3.9e-10, CesiumMath.EPSILON11); + testDensityAtHeight(50, 2.2e-10, CesiumMath.EPSILON11); + }); + + it("default density, mid heights", () => { + testDensityAtHeight(100, 1.5e-10, CesiumMath.EPSILON11); + testDensityAtHeight(1000, 3.9e-11, CesiumMath.EPSILON12); + testDensityAtHeight(2000, 2.5e-11, CesiumMath.EPSILON12); + testDensityAtHeight(5000, 1.5e-11, CesiumMath.EPSILON12); + }); + + it("default density, high heights", () => { + testDensityAtHeight(10000, 1.0e-11, CesiumMath.EPSILON12); + testDensityAtHeight(100000, 2.5e-12, CesiumMath.EPSILON13); + testDensityAtHeight(200000, 1.7e-12, CesiumMath.EPSILON13); + testDensityAtHeight(500000, 9.9e-13, CesiumMath.EPSILON14); + }); + + it("higher density, close to the ground", () => { + fog.density = 0.005; // over double the default + testDensityAtHeight(1, 1.9e-8, CesiumMath.EPSILON9); + testDensityAtHeight(10, 4.9e-9, CesiumMath.EPSILON10); + testDensityAtHeight(20, 3.2e-9, CesiumMath.EPSILON10); + testDensityAtHeight(50, 1.9e-9, CesiumMath.EPSILON10); + }); + + it("higher density, mid heights", () => { + fog.density = 0.005; // over double default + testDensityAtHeight(100, 1.2e-9, CesiumMath.EPSILON10); + testDensityAtHeight(1000, 3.2e-10, CesiumMath.EPSILON11); + testDensityAtHeight(2000, 2.1e-10, CesiumMath.EPSILON11); + testDensityAtHeight(5000, 1.2e-10, CesiumMath.EPSILON11); + }); + + it("higher density, high heights", () => { + fog.density = 0.005; // over double default + testDensityAtHeight(10000, 8.3e-11, CesiumMath.EPSILON12); + testDensityAtHeight(100000, 2.1e-11, CesiumMath.EPSILON12); + testDensityAtHeight(200000, 1.4e-11, CesiumMath.EPSILON12); + testDensityAtHeight(500000, 8.3e-12, CesiumMath.EPSILON13); + }); + + it("heightScalar directly affects density", () => { + fog.heightScalar = 1; + testDensityAtHeight(1000, 3.9e-8, CesiumMath.EPSILON9); + fog.heightScalar = 2; + testDensityAtHeight(1000, 3.9e-8 * 2, CesiumMath.EPSILON9); + }); + }); + }); +}); diff --git a/packages/engine/Specs/Scene/Model/AtmospherePipelineStageSpec.js b/packages/engine/Specs/Scene/Model/AtmospherePipelineStageSpec.js index 02a065f4365..a19b1d1f8ed 100644 --- a/packages/engine/Specs/Scene/Model/AtmospherePipelineStageSpec.js +++ b/packages/engine/Specs/Scene/Model/AtmospherePipelineStageSpec.js @@ -41,7 +41,7 @@ describe( scene.frameState.camera.direction = new Cartesian3(0, -1, 0); // Reset the fog density - scene.fog.density = 2e-4; + scene.fog.density = 0.0006; }); afterAll(async function () { diff --git a/packages/engine/Specs/Scene/SceneSpec.js b/packages/engine/Specs/Scene/SceneSpec.js index a2f21c78969..c294126c7a0 100644 --- a/packages/engine/Specs/Scene/SceneSpec.js +++ b/packages/engine/Specs/Scene/SceneSpec.js @@ -2557,6 +2557,8 @@ describe( it("does not occlude primitives when camera is underground", async function () { const globe = new Globe(); scene.globe = globe; + // disable fog to skip fog culling + scene.fog.enabled = false; // A primitive at height -25000.0 is less than the minor axis for WGS84 and will get culled unless the camera is underground const center = Cartesian3.fromRadians( From 61a7332c27f60bfd8a89f03c4f8034664286dbc4 Mon Sep 17 00:00:00 2001 From: jjspace <8007967+jjspace@users.noreply.github.com> Date: Mon, 28 Oct 2024 17:03:03 -0400 Subject: [PATCH 09/11] change scalar default --- CHANGES.md | 6 +----- packages/engine/Source/Scene/Fog.js | 4 ++-- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 481e9f8238c..8c4f8c347f3 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,14 +4,10 @@ #### @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) +- Exposed `Fog.visualDensityScalar` to allow modifying the visual density of fog without affecting the culling aspects. Alongside this the density calculation was adjusted to make it more smooth across heights [#12248](https://github.com/CesiumGS/cesium/pull/12248) - Update Japan Buildings sandcastle to use Japan Regional Terrain [#12259](https://github.com/CesiumGS/cesium/pull/12259) ##### Fixes :wrench: diff --git a/packages/engine/Source/Scene/Fog.js b/packages/engine/Source/Scene/Fog.js index 21df1ea29d9..896d1aaa8d8 100644 --- a/packages/engine/Source/Scene/Fog.js +++ b/packages/engine/Source/Scene/Fog.js @@ -64,13 +64,13 @@ function Fog() { * 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. * @type {number} - * @default 1.0 + * @default 0.15 * @experimental The value of this scalar may not be final and is subject to change. * @example * // Increase fog appearance effect * viewer.scene.fog.visualDensityScalar = 0.6; */ - this.visualDensityScalar = 1.0; + this.visualDensityScalar = 0.15; /** * 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 From acb2da8557a6a900ee50853cd5e97625fd7f8839 Mon Sep 17 00:00:00 2001 From: jjspace <8007967+jjspace@users.noreply.github.com> Date: Wed, 30 Oct 2024 11:08:13 -0400 Subject: [PATCH 10/11] adjust minimum height influence and specs --- packages/engine/Source/Scene/Fog.js | 2 +- packages/engine/Specs/Scene/FogSpec.js | 16 ++++++++-------- packages/engine/Specs/Scene/SceneSpec.js | 5 ++--- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/packages/engine/Source/Scene/Fog.js b/packages/engine/Source/Scene/Fog.js index 896d1aaa8d8..88c3edbc4d9 100644 --- a/packages/engine/Source/Scene/Fog.js +++ b/packages/engine/Source/Scene/Fog.js @@ -146,7 +146,7 @@ Fog.prototype.update = function (frameState) { this.density * this.heightScalar * Math.pow( - Math.max(height / this.maxHeight, CesiumMath.EPSILON6), + Math.max(height / this.maxHeight, CesiumMath.EPSILON4), -Math.max(this._heightFalloff, 0.0), ); diff --git a/packages/engine/Specs/Scene/FogSpec.js b/packages/engine/Specs/Scene/FogSpec.js index 746ebca9ffb..7fca0536ff1 100644 --- a/packages/engine/Specs/Scene/FogSpec.js +++ b/packages/engine/Specs/Scene/FogSpec.js @@ -115,10 +115,10 @@ describe("Fog", () => { } it("default density, close to the ground", () => { - testDensityAtHeight(1, 2.3e-9, CesiumMath.EPSILON10); - testDensityAtHeight(10, 5.9e-10, CesiumMath.EPSILON11); - testDensityAtHeight(20, 3.9e-10, CesiumMath.EPSILON11); - testDensityAtHeight(50, 2.2e-10, CesiumMath.EPSILON11); + testDensityAtHeight(1, 1.7e-10, CesiumMath.EPSILON11); + testDensityAtHeight(10, 1.7e-10, CesiumMath.EPSILON11); + testDensityAtHeight(20, 1.7e-10, CesiumMath.EPSILON11); + testDensityAtHeight(50, 1.7e-10, CesiumMath.EPSILON11); }); it("default density, mid heights", () => { @@ -137,10 +137,10 @@ describe("Fog", () => { it("higher density, close to the ground", () => { fog.density = 0.005; // over double the default - testDensityAtHeight(1, 1.9e-8, CesiumMath.EPSILON9); - testDensityAtHeight(10, 4.9e-9, CesiumMath.EPSILON10); - testDensityAtHeight(20, 3.2e-9, CesiumMath.EPSILON10); - testDensityAtHeight(50, 1.9e-9, CesiumMath.EPSILON10); + testDensityAtHeight(1, 1.4e-9, CesiumMath.EPSILON10); + testDensityAtHeight(10, 1.4e-9, CesiumMath.EPSILON10); + testDensityAtHeight(20, 1.4e-9, CesiumMath.EPSILON10); + testDensityAtHeight(50, 1.4e-9, CesiumMath.EPSILON10); }); it("higher density, mid heights", () => { diff --git a/packages/engine/Specs/Scene/SceneSpec.js b/packages/engine/Specs/Scene/SceneSpec.js index c294126c7a0..3fc9c31602a 100644 --- a/packages/engine/Specs/Scene/SceneSpec.js +++ b/packages/engine/Specs/Scene/SceneSpec.js @@ -2557,8 +2557,7 @@ describe( it("does not occlude primitives when camera is underground", async function () { const globe = new Globe(); scene.globe = globe; - // disable fog to skip fog culling - scene.fog.enabled = false; + scene.fog.density = 0.0004; // A primitive at height -25000.0 is less than the minor axis for WGS84 and will get culled unless the camera is underground const center = Cartesian3.fromRadians( @@ -2583,7 +2582,7 @@ describe( await updateGlobeUntilDone(scene); expect(getFrustumCommandsLength(scene, Pass.OPAQUE)).toBe(0); - // Look underground at the primitive + // Look underground at the primitive, camera height ~-24,000 scene.camera.setView({ destination: new Cartesian3( -4643042.379120885, From 30ad73aa497392ea6b4d32b64f394578eea7f0f2 Mon Sep 17 00:00:00 2001 From: jjspace <8007967+jjspace@users.noreply.github.com> Date: Wed, 30 Oct 2024 11:16:29 -0400 Subject: [PATCH 11/11] pr comments --- CHANGES.md | 3 ++- packages/engine/Source/Scene/Fog.js | 2 +- packages/engine/Specs/Scene/FogSpec.js | 13 +++++++++---- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index a6ca4d25d70..ed4162dc3b7 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -19,12 +19,13 @@ ``` - `ImageBasedLighting.luminanceAtZenith` has been removed. Use `DynamicEnvironmentMapManager.atmosphereScatteringIntensity` instead. [#12129](https://github.com/CesiumGS/cesium/pull/12129) +- Changed the default `Fog.density` from `0.0002` to `0.0006`. Set `viewer.scene.fog.density = 0.002` to return to the previous behavior. [#12248](https://github.com/CesiumGS/cesium/pull/12248) ##### Additions :tada: - Updated default 3D Tiles and Model lighting when using PBR in order to create a more realistic appearance. Added `DynamicEnvironmentMapManager` to control lighting parameters. These can be accessed via `Cesium3DTileset.environmentMapManager` and `Model.environmentMapManager`. [#12129](https://github.com/CesiumGS/cesium/pull/12129) - 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. Alongside this the density calculation was adjusted to make it more smooth across heights [#12248](https://github.com/CesiumGS/cesium/pull/12248) +- Exposed `Fog.visualDensityScalar` to allow modifying the visual density of fog without affecting the culling aspects. Alongside this, the density calculation was adjusted to make it more smooth across heights. [#12248](https://github.com/CesiumGS/cesium/pull/12248) - Update Japan Buildings sandcastle to use Japan Regional Terrain [#12259](https://github.com/CesiumGS/cesium/pull/12259) - Update Bing Maps attribution link [#12229] (https://github.com/CesiumGS/cesium/pull/12265) diff --git a/packages/engine/Source/Scene/Fog.js b/packages/engine/Source/Scene/Fog.js index 88c3edbc4d9..013bd79f8bc 100644 --- a/packages/engine/Source/Scene/Fog.js +++ b/packages/engine/Source/Scene/Fog.js @@ -44,7 +44,7 @@ function Fog() { * @default 0.0006 * @example * // Double the default fog density - * viewer.scene.fog.density = 0.0004; + * viewer.scene.fog.density = 0.0012; */ this.density = 0.0006; /** diff --git a/packages/engine/Specs/Scene/FogSpec.js b/packages/engine/Specs/Scene/FogSpec.js index 7fca0536ff1..936dc25354e 100644 --- a/packages/engine/Specs/Scene/FogSpec.js +++ b/packages/engine/Specs/Scene/FogSpec.js @@ -1,5 +1,4 @@ import { Fog, Math as CesiumMath, SceneMode } from "../../index.js"; -import createCanvas from "../../../../Specs/createCanvas.js"; import createScene from "../../../../Specs/createScene.js"; describe("Fog", () => { @@ -11,9 +10,7 @@ describe("Fog", () => { beforeEach(() => { fog = new Fog(); - scene = createScene({ - canvas: createCanvas(10, 10), - }); + scene = createScene(); }); afterEach(function () { @@ -114,6 +111,14 @@ describe("Fog", () => { .toEqualEpsilon(expectedDensity, epsilon); } + it("default density, underground", () => { + testDensityAtHeight(-1, 1.7e-10, CesiumMath.EPSILON11); + testDensityAtHeight(-10, 1.7e-10, CesiumMath.EPSILON11); + testDensityAtHeight(-100, 1.7e-10, CesiumMath.EPSILON11); + testDensityAtHeight(-1000, 1.7e-10, CesiumMath.EPSILON11); + testDensityAtHeight(-10000, 1.7e-10, CesiumMath.EPSILON11); + }); + it("default density, close to the ground", () => { testDensityAtHeight(1, 1.7e-10, CesiumMath.EPSILON11); testDensityAtHeight(10, 1.7e-10, CesiumMath.EPSILON11);