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