@@ -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);