You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
197 lines
5.6 KiB
JavaScript
197 lines
5.6 KiB
JavaScript
import Cartesian3 from "../Core/Cartesian3.js";
|
|
import defined from "../Core/defined.js";
|
|
import CesiumMath from "../Core/Math.js";
|
|
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.
|
|
*
|
|
* @alias Fog
|
|
* @constructor
|
|
*/
|
|
function Fog() {
|
|
/**
|
|
* <code>true</code> if fog is enabled, <code>false</code> otherwise.
|
|
* @type {Boolean}
|
|
* @default true
|
|
*/
|
|
this.enabled = true;
|
|
/**
|
|
* A scalar that determines the density of the fog. Terrain that is in full fog are culled.
|
|
* The density of the fog increases as this number approaches 1.0 and becomes less dense as it approaches zero.
|
|
* The more dense the fog is, the more aggressively the terrain is culled. For example, if the camera is a height of
|
|
* 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
|
|
*/
|
|
this.density = 2.0e-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
|
|
* for mountainous regions, less tiles will need to be requested, but the terrain meshes near the horizon may be a noticeably
|
|
* lower resolution. If the value is increased in a relatively flat area, there will be little noticeable change on the horizon.
|
|
* @type {Number}
|
|
* @default 2.0
|
|
*/
|
|
this.screenSpaceErrorFactor = 2.0;
|
|
/**
|
|
* The minimum brightness of the fog color from lighting. A value of 0.0 can cause the fog to be completely black. A value of 1.0 will not affect
|
|
* the brightness at all.
|
|
* @type {Number}
|
|
* @default 0.03
|
|
*/
|
|
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.
|
|
var 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,
|
|
];
|
|
var 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 (var i = 0; i < densityTable.length; ++i) {
|
|
densityTable[i] *= 1.0e6;
|
|
}
|
|
// Change range to [0, 1].
|
|
var tableStartDensity = densityTable[1];
|
|
var tableEndDensity = densityTable[densityTable.length - 1];
|
|
for (var j = 0; j < densityTable.length; ++j) {
|
|
densityTable[j] =
|
|
(densityTable[j] - tableEndDensity) / (tableStartDensity - tableEndDensity);
|
|
}
|
|
|
|
var tableLastIndex = 0;
|
|
|
|
function findInterval(height) {
|
|
var heights = heightsTable;
|
|
var 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.
|
|
var i;
|
|
for (i = 0; i < length - 2; ++i) {
|
|
if (height >= heights[i] && height < heights[i + 1]) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
tableLastIndex = i;
|
|
return tableLastIndex;
|
|
}
|
|
|
|
var scratchPositionNormal = new Cartesian3();
|
|
|
|
Fog.prototype.update = function (frameState) {
|
|
var enabled = (frameState.fog.enabled = this.enabled);
|
|
if (!enabled) {
|
|
return;
|
|
}
|
|
|
|
var camera = frameState.camera;
|
|
var positionCartographic = camera.positionCartographic;
|
|
|
|
// Turn off fog in space.
|
|
if (
|
|
!defined(positionCartographic) ||
|
|
positionCartographic.height > 800000.0 ||
|
|
frameState.mode !== SceneMode.SCENE3D
|
|
) {
|
|
frameState.fog.enabled = false;
|
|
return;
|
|
}
|
|
|
|
var height = positionCartographic.height;
|
|
var i = findInterval(height);
|
|
var t = CesiumMath.clamp(
|
|
(height - heightsTable[i]) / (heightsTable[i + 1] - heightsTable[i]),
|
|
0.0,
|
|
1.0
|
|
);
|
|
var 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.
|
|
var startDensity = this.density * 1.0e6;
|
|
var endDensity = (startDensity / tableStartDensity) * tableEndDensity;
|
|
density = density * (startDensity - endDensity) * 1.0e-6;
|
|
|
|
// Fade fog in as the camera tilts toward the horizon.
|
|
var positionNormal = Cartesian3.normalize(
|
|
camera.positionWC,
|
|
scratchPositionNormal
|
|
);
|
|
var dot = Math.abs(Cartesian3.dot(camera.directionWC, positionNormal));
|
|
density *= 1.0 - dot;
|
|
|
|
frameState.fog.density = density;
|
|
frameState.fog.sse = this.screenSpaceErrorFactor;
|
|
frameState.fog.minimumBrightness = this.minimumBrightness;
|
|
};
|
|
export default Fog;
|