Skip to content

Commit

Permalink
expose new scalar to change the visual density of fog
Browse files Browse the repository at this point in the history
  • Loading branch information
jjspace committed Oct 10, 2024
1 parent 7aefae9 commit 5ec99b2
Show file tree
Hide file tree
Showing 11 changed files with 214 additions and 54 deletions.
2 changes: 2 additions & 0 deletions Apps/Sandcastle/gallery/Atmosphere.html
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
196 changes: 156 additions & 40 deletions Apps/Sandcastle/gallery/development/Fog.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,22 @@
<body class="sandcastle-loading" data-sandcastle-bucket="bucket-requirejs.html">
<style>
@import url(../templates/bucket.css);
#toolbar {
background: rgba(42, 42, 42, 0.8);
padding: 4px;
border-radius: 4px;
}
#zoomButtons {
display: flex;
flex-direction: column;
align-items: flex-start;
}
input[type="range"] {
width: 6em;
}
input[type="number"] {
width: 5em;
}
</style>
<div id="cesiumContainer" class="fullSize"></div>
<div id="loadingOverlay"><h1>Loading...</h1></div>
Expand All @@ -33,7 +49,60 @@
</tr>
<tr>
<td>density</td>
<td><input type="text" size="5" data-bind="value: density" /></td>
<td>
<input
type="range"
data-bind="value: density, valueUpdate: 'input'"
min="0.0001"
max="0.002"
step="0.0001"
/>
<input
type="number"
min="0.0001"
max="0.002"
step="0.0001"
data-bind="value: density"
/>
</td>
</tr>
<tr>
<td>visual density scalar</td>
<td>
<input
type="range"
min="0.01"
max="2"
step="0.01"
data-bind="value: visualDensityScalar, valueUpdate: 'input'"
/>
<input
type="number"
min="0.01"
max="2"
step="0.01"
data-bind="value: visualDensityScalar"
/>
</td>
</tr>
<tr>
<td for="input-fogminbrightness">Fog min brightness</td>
<td>
<input
type="range"
data-bind="value: minimumBrightness, valueUpdate: 'input'"
min="0"
max="1"
step="0.01"
/>
<input
type="number"
data-bind="value: minimumBrightness"
min="0"
max="1"
step="0.01"
/>
</td>
</tr>
<tr>
<td>sse increase factor</td>
Expand All @@ -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);
Expand All @@ -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(`<img src="${viewer.canvas.toDataURL("image/png")}" />`);
// 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") {
Expand Down
2 changes: 2 additions & 0 deletions packages/engine/Source/Core/Math.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
14 changes: 14 additions & 0 deletions packages/engine/Source/Renderer/AutomaticUniforms.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down
13 changes: 13 additions & 0 deletions packages/engine/Source/Renderer/UniformState.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ function UniformState() {
this._specularEnvironmentMapsMaximumLOD = undefined;

this._fogDensity = undefined;
this._fogVisualDensityScalar = undefined;
this._fogMinimumBrightness = undefined;

this._atmosphereHsbShift = undefined;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down
9 changes: 9 additions & 0 deletions packages/engine/Source/Scene/Fog.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
};
Expand Down
8 changes: 5 additions & 3 deletions packages/engine/Source/Scene/FrameState.js
Original file line number Diff line number Diff line change
Expand Up @@ -261,9 +261,10 @@ function FrameState(context, creditDisplay, jobScheduler) {
* @type {object}
* @property {boolean} enabled <code>true</code> if fog is enabled, <code>false</code> otherwise. This affects both fog culling and rendering.
* @property {boolean} renderable <code>true</code> if fog should be rendered, <code>false</code> 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.
*/

/**
Expand All @@ -277,6 +278,7 @@ function FrameState(context, creditDisplay, jobScheduler) {
enabled: false,
renderable: false,
density: undefined,
visualDensityScalar: undefined,
sse: undefined,
minimumBrightness: undefined,
};
Expand Down
Loading

0 comments on commit 5ec99b2

Please sign in to comment.