123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402 |
- import Cartesian3 from "../Core/Cartesian3.js";
- import defaultValue from "../Core/defaultValue.js";
- import defined from "../Core/defined.js";
- import destroyObject from "../Core/destroyObject.js";
- import Ellipsoid from "../Core/Ellipsoid.js";
- import EllipsoidGeometry from "../Core/EllipsoidGeometry.js";
- import GeometryPipeline from "../Core/GeometryPipeline.js";
- import CesiumMath from "../Core/Math.js";
- import Matrix4 from "../Core/Matrix4.js";
- import VertexFormat from "../Core/VertexFormat.js";
- import BufferUsage from "../Renderer/BufferUsage.js";
- import DrawCommand from "../Renderer/DrawCommand.js";
- import RenderState from "../Renderer/RenderState.js";
- import ShaderProgram from "../Renderer/ShaderProgram.js";
- import ShaderSource from "../Renderer/ShaderSource.js";
- import VertexArray from "../Renderer/VertexArray.js";
- import AtmosphereCommon from "../Shaders/AtmosphereCommon.js";
- import SkyAtmosphereCommon from "../Shaders/SkyAtmosphereCommon.js";
- import SkyAtmosphereFS from "../Shaders/SkyAtmosphereFS.js";
- import SkyAtmosphereVS from "../Shaders/SkyAtmosphereVS.js";
- import Axis from "./Axis.js";
- import BlendingState from "./BlendingState.js";
- import CullFace from "./CullFace.js";
- import SceneMode from "./SceneMode.js";
- /**
- * An atmosphere drawn around the limb of the provided ellipsoid. Based on
- * {@link http://nishitalab.org/user/nis/cdrom/sig93_nis.pdf|Display of The Earth Taking Into Account Atmospheric Scattering}.
- * <p>
- * This is only supported in 3D. Atmosphere is faded out when morphing to 2D or Columbus view.
- * </p>
- *
- * @alias SkyAtmosphere
- * @constructor
- *
- * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid that the atmosphere is drawn around.
- *
- * @example
- * scene.skyAtmosphere = new Cesium.SkyAtmosphere();
- *
- * @see Scene.skyAtmosphere
- */
- function SkyAtmosphere(ellipsoid) {
- ellipsoid = defaultValue(ellipsoid, Ellipsoid.WGS84);
- /**
- * Determines if the atmosphere is shown.
- *
- * @type {Boolean}
- * @default true
- */
- this.show = true;
- /**
- * Compute atmosphere per-fragment instead of per-vertex.
- * This produces better looking atmosphere with a slight performance penalty.
- *
- * @type {Boolean}
- * @default false
- */
- this.perFragmentAtmosphere = false;
- this._ellipsoid = ellipsoid;
- const outerEllipsoidScale = 1.025;
- const scaleVector = Cartesian3.multiplyByScalar(
- ellipsoid.radii,
- outerEllipsoidScale,
- new Cartesian3()
- );
- this._scaleMatrix = Matrix4.fromScale(scaleVector);
- this._modelMatrix = new Matrix4();
- this._command = new DrawCommand({
- owner: this,
- modelMatrix: this._modelMatrix,
- });
- this._spSkyFromSpace = undefined;
- this._spSkyFromAtmosphere = undefined;
- this._flags = undefined;
- /**
- * The intensity of the light that is used for computing the sky atmosphere color.
- *
- * @type {Number}
- * @default 50.0
- */
- this.atmosphereLightIntensity = 50.0;
- /**
- * The Rayleigh scattering coefficient used in the atmospheric scattering equations for the sky atmosphere.
- *
- * @type {Cartesian3}
- * @default Cartesian3(5.5e-6, 13.0e-6, 28.4e-6)
- */
- this.atmosphereRayleighCoefficient = new Cartesian3(5.5e-6, 13.0e-6, 28.4e-6);
- /**
- * The Mie scattering coefficient used in the atmospheric scattering equations for the sky atmosphere.
- *
- * @type {Cartesian3}
- * @default Cartesian3(21e-6, 21e-6, 21e-6)
- */
- this.atmosphereMieCoefficient = new Cartesian3(21e-6, 21e-6, 21e-6);
- /**
- * The Rayleigh scale height used in the atmospheric scattering equations for the sky atmosphere, in meters.
- *
- * @type {Number}
- * @default 10000.0
- */
- this.atmosphereRayleighScaleHeight = 10000.0;
- /**
- * The Mie scale height used in the atmospheric scattering equations for the sky atmosphere, in meters.
- *
- * @type {Number}
- * @default 3200.0
- */
- this.atmosphereMieScaleHeight = 3200.0;
- /**
- * The anisotropy of the medium to consider for Mie scattering.
- * <p>
- * Valid values are between -1.0 and 1.0.
- * </p>
- * @type {Number}
- * @default 0.9
- */
- this.atmosphereMieAnisotropy = 0.9;
- /**
- * The hue shift to apply to the atmosphere. Defaults to 0.0 (no shift).
- * A hue shift of 1.0 indicates a complete rotation of the hues available.
- * @type {Number}
- * @default 0.0
- */
- this.hueShift = 0.0;
- /**
- * The saturation shift to apply to the atmosphere. Defaults to 0.0 (no shift).
- * A saturation shift of -1.0 is monochrome.
- * @type {Number}
- * @default 0.0
- */
- this.saturationShift = 0.0;
- /**
- * The brightness shift to apply to the atmosphere. Defaults to 0.0 (no shift).
- * A brightness shift of -1.0 is complete darkness, which will let space show through.
- * @type {Number}
- * @default 0.0
- */
- this.brightnessShift = 0.0;
- this._hueSaturationBrightness = new Cartesian3();
- // outer radius, inner radius, dynamic atmosphere color flag
- const radiiAndDynamicAtmosphereColor = new Cartesian3();
- radiiAndDynamicAtmosphereColor.x =
- ellipsoid.maximumRadius * outerEllipsoidScale;
- radiiAndDynamicAtmosphereColor.y = ellipsoid.maximumRadius;
- // Toggles whether the sun position is used. 0 treats the sun as always directly overhead.
- radiiAndDynamicAtmosphereColor.z = 0;
- this._radiiAndDynamicAtmosphereColor = radiiAndDynamicAtmosphereColor;
- const that = this;
- this._command.uniformMap = {
- u_radiiAndDynamicAtmosphereColor: function () {
- return that._radiiAndDynamicAtmosphereColor;
- },
- u_hsbShift: function () {
- that._hueSaturationBrightness.x = that.hueShift;
- that._hueSaturationBrightness.y = that.saturationShift;
- that._hueSaturationBrightness.z = that.brightnessShift;
- return that._hueSaturationBrightness;
- },
- u_atmosphereLightIntensity: function () {
- return that.atmosphereLightIntensity;
- },
- u_atmosphereRayleighCoefficient: function () {
- return that.atmosphereRayleighCoefficient;
- },
- u_atmosphereMieCoefficient: function () {
- return that.atmosphereMieCoefficient;
- },
- u_atmosphereRayleighScaleHeight: function () {
- return that.atmosphereRayleighScaleHeight;
- },
- u_atmosphereMieScaleHeight: function () {
- return that.atmosphereMieScaleHeight;
- },
- u_atmosphereMieAnisotropy: function () {
- return that.atmosphereMieAnisotropy;
- },
- };
- }
- Object.defineProperties(SkyAtmosphere.prototype, {
- /**
- * Gets the ellipsoid the atmosphere is drawn around.
- * @memberof SkyAtmosphere.prototype
- *
- * @type {Ellipsoid}
- * @readonly
- */
- ellipsoid: {
- get: function () {
- return this._ellipsoid;
- },
- },
- });
- /**
- * @private
- */
- SkyAtmosphere.prototype.setDynamicAtmosphereColor = function (
- enableLighting,
- useSunDirection
- ) {
- const lightEnum = enableLighting ? (useSunDirection ? 2.0 : 1.0) : 0.0;
- this._radiiAndDynamicAtmosphereColor.z = lightEnum;
- };
- const scratchModelMatrix = new Matrix4();
- /**
- * @private
- */
- SkyAtmosphere.prototype.update = function (frameState, globe) {
- if (!this.show) {
- return undefined;
- }
- const mode = frameState.mode;
- if (mode !== SceneMode.SCENE3D && mode !== SceneMode.MORPHING) {
- return undefined;
- }
- // The atmosphere is only rendered during the render pass; it is not pickable, it doesn't cast shadows, etc.
- if (!frameState.passes.render) {
- return undefined;
- }
- // Align the ellipsoid geometry so it always faces the same direction as the
- // camera to reduce artifacts when rendering atmosphere per-vertex
- const rotationMatrix = Matrix4.fromRotationTranslation(
- frameState.context.uniformState.inverseViewRotation,
- Cartesian3.ZERO,
- scratchModelMatrix
- );
- const rotationOffsetMatrix = Matrix4.multiplyTransformation(
- rotationMatrix,
- Axis.Y_UP_TO_Z_UP,
- scratchModelMatrix
- );
- const modelMatrix = Matrix4.multiply(
- this._scaleMatrix,
- rotationOffsetMatrix,
- scratchModelMatrix
- );
- Matrix4.clone(modelMatrix, this._modelMatrix);
- const context = frameState.context;
- const colorCorrect = hasColorCorrection(this);
- const translucent = frameState.globeTranslucencyState.translucent;
- const perFragmentAtmosphere =
- this.perFragmentAtmosphere || translucent || !defined(globe) || !globe.show;
- const command = this._command;
- if (!defined(command.vertexArray)) {
- const geometry = EllipsoidGeometry.createGeometry(
- new EllipsoidGeometry({
- radii: new Cartesian3(1.0, 1.0, 1.0),
- slicePartitions: 256,
- stackPartitions: 256,
- vertexFormat: VertexFormat.POSITION_ONLY,
- })
- );
- command.vertexArray = VertexArray.fromGeometry({
- context: context,
- geometry: geometry,
- attributeLocations: GeometryPipeline.createAttributeLocations(geometry),
- bufferUsage: BufferUsage.STATIC_DRAW,
- });
- command.renderState = RenderState.fromCache({
- cull: {
- enabled: true,
- face: CullFace.FRONT,
- },
- blending: BlendingState.ALPHA_BLEND,
- depthMask: false,
- });
- }
- const flags =
- colorCorrect | (perFragmentAtmosphere << 2) | (translucent << 3);
- if (flags !== this._flags) {
- this._flags = flags;
- const defines = [];
- if (colorCorrect) {
- defines.push("COLOR_CORRECT");
- }
- if (perFragmentAtmosphere) {
- defines.push("PER_FRAGMENT_ATMOSPHERE");
- }
- if (translucent) {
- defines.push("GLOBE_TRANSLUCENT");
- }
- const vs = new ShaderSource({
- defines: defines,
- sources: [AtmosphereCommon, SkyAtmosphereCommon, SkyAtmosphereVS],
- });
- const fs = new ShaderSource({
- defines: defines,
- sources: [AtmosphereCommon, SkyAtmosphereCommon, SkyAtmosphereFS],
- });
- this._spSkyAtmosphere = ShaderProgram.fromCache({
- context: context,
- vertexShaderSource: vs,
- fragmentShaderSource: fs,
- });
- command.shaderProgram = this._spSkyAtmosphere;
- }
- return command;
- };
- function hasColorCorrection(skyAtmosphere) {
- return !(
- CesiumMath.equalsEpsilon(
- skyAtmosphere.hueShift,
- 0.0,
- CesiumMath.EPSILON7
- ) &&
- CesiumMath.equalsEpsilon(
- skyAtmosphere.saturationShift,
- 0.0,
- CesiumMath.EPSILON7
- ) &&
- CesiumMath.equalsEpsilon(
- skyAtmosphere.brightnessShift,
- 0.0,
- CesiumMath.EPSILON7
- )
- );
- }
- /**
- * Returns true if this object was destroyed; otherwise, false.
- * <br /><br />
- * If this object was destroyed, it should not be used; calling any function other than
- * <code>isDestroyed</code> will result in a {@link DeveloperError} exception.
- *
- * @returns {Boolean} <code>true</code> if this object was destroyed; otherwise, <code>false</code>.
- *
- * @see SkyAtmosphere#destroy
- */
- SkyAtmosphere.prototype.isDestroyed = function () {
- return false;
- };
- /**
- * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic
- * release of WebGL resources, instead of relying on the garbage collector to destroy this object.
- * <br /><br />
- * Once an object is destroyed, it should not be used; calling any function other than
- * <code>isDestroyed</code> will result in a {@link DeveloperError} exception. Therefore,
- * assign the return value (<code>undefined</code>) to the object as done in the example.
- *
- * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
- *
- *
- * @example
- * skyAtmosphere = skyAtmosphere && skyAtmosphere.destroy();
- *
- * @see SkyAtmosphere#isDestroyed
- */
- SkyAtmosphere.prototype.destroy = function () {
- const command = this._command;
- command.vertexArray = command.vertexArray && command.vertexArray.destroy();
- this._spSkyAtmosphere =
- this._spSkyAtmosphere && this._spSkyAtmosphere.destroy();
- return destroyObject(this);
- };
- export default SkyAtmosphere;
|