智慧水务管理系统 - 精河县供水工程综合管理平台

SkyAtmosphere.js 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. import Cartesian3 from "../Core/Cartesian3.js";
  2. import defined from "../Core/defined.js";
  3. import destroyObject from "../Core/destroyObject.js";
  4. import Ellipsoid from "../Core/Ellipsoid.js";
  5. import EllipsoidGeometry from "../Core/EllipsoidGeometry.js";
  6. import GeometryPipeline from "../Core/GeometryPipeline.js";
  7. import CesiumMath from "../Core/Math.js";
  8. import Matrix4 from "../Core/Matrix4.js";
  9. import VertexFormat from "../Core/VertexFormat.js";
  10. import BufferUsage from "../Renderer/BufferUsage.js";
  11. import DrawCommand from "../Renderer/DrawCommand.js";
  12. import RenderState from "../Renderer/RenderState.js";
  13. import ShaderProgram from "../Renderer/ShaderProgram.js";
  14. import ShaderSource from "../Renderer/ShaderSource.js";
  15. import VertexArray from "../Renderer/VertexArray.js";
  16. import AtmosphereCommon from "../Shaders/AtmosphereCommon.js";
  17. import SkyAtmosphereCommon from "../Shaders/SkyAtmosphereCommon.js";
  18. import SkyAtmosphereFS from "../Shaders/SkyAtmosphereFS.js";
  19. import SkyAtmosphereVS from "../Shaders/SkyAtmosphereVS.js";
  20. import Axis from "./Axis.js";
  21. import BlendingState from "./BlendingState.js";
  22. import CullFace from "./CullFace.js";
  23. import SceneMode from "./SceneMode.js";
  24. /**
  25. * An atmosphere drawn around the limb of the provided ellipsoid. Based on
  26. * {@link http://nishitalab.org/user/nis/cdrom/sig93_nis.pdf|Display of The Earth Taking Into Account Atmospheric Scattering}.
  27. * <p>
  28. * This is only supported in 3D. Atmosphere is faded out when morphing to 2D or Columbus view.
  29. * </p>
  30. *
  31. * @alias SkyAtmosphere
  32. * @constructor
  33. *
  34. * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid that the atmosphere is drawn around.
  35. *
  36. * @example
  37. * scene.skyAtmosphere = new Cesium.SkyAtmosphere();
  38. *
  39. * @see Scene.skyAtmosphere
  40. */
  41. function SkyAtmosphere(ellipsoid) {
  42. ellipsoid = ellipsoid ?? Ellipsoid.WGS84;
  43. /**
  44. * Determines if the atmosphere is shown.
  45. *
  46. * @type {boolean}
  47. * @default true
  48. */
  49. this.show = true;
  50. /**
  51. * Compute atmosphere per-fragment instead of per-vertex.
  52. * This produces better looking atmosphere with a slight performance penalty.
  53. *
  54. * @type {boolean}
  55. * @default false
  56. */
  57. this.perFragmentAtmosphere = false;
  58. this._ellipsoid = ellipsoid;
  59. const outerEllipsoidScale = 1.025;
  60. const scaleVector = Cartesian3.multiplyByScalar(
  61. ellipsoid.radii,
  62. outerEllipsoidScale,
  63. new Cartesian3(),
  64. );
  65. this._scaleMatrix = Matrix4.fromScale(scaleVector);
  66. this._modelMatrix = new Matrix4();
  67. this._command = new DrawCommand({
  68. owner: this,
  69. modelMatrix: this._modelMatrix,
  70. });
  71. this._spSkyFromSpace = undefined;
  72. this._spSkyFromAtmosphere = undefined;
  73. this._flags = undefined;
  74. /**
  75. * The intensity of the light that is used for computing the sky atmosphere color.
  76. *
  77. * @type {number}
  78. * @default 50.0
  79. */
  80. this.atmosphereLightIntensity = 50.0;
  81. /**
  82. * The Rayleigh scattering coefficient used in the atmospheric scattering equations for the sky atmosphere.
  83. *
  84. * @type {Cartesian3}
  85. * @default Cartesian3(5.5e-6, 13.0e-6, 28.4e-6)
  86. */
  87. this.atmosphereRayleighCoefficient = new Cartesian3(5.5e-6, 13.0e-6, 28.4e-6);
  88. /**
  89. * The Mie scattering coefficient used in the atmospheric scattering equations for the sky atmosphere.
  90. *
  91. * @type {Cartesian3}
  92. * @default Cartesian3(21e-6, 21e-6, 21e-6)
  93. */
  94. this.atmosphereMieCoefficient = new Cartesian3(21e-6, 21e-6, 21e-6);
  95. /**
  96. * The Rayleigh scale height used in the atmospheric scattering equations for the sky atmosphere, in meters.
  97. *
  98. * @type {number}
  99. * @default 10000.0
  100. */
  101. this.atmosphereRayleighScaleHeight = 10000.0;
  102. /**
  103. * The Mie scale height used in the atmospheric scattering equations for the sky atmosphere, in meters.
  104. *
  105. * @type {number}
  106. * @default 3200.0
  107. */
  108. this.atmosphereMieScaleHeight = 3200.0;
  109. /**
  110. * The anisotropy of the medium to consider for Mie scattering.
  111. * <p>
  112. * Valid values are between -1.0 and 1.0.
  113. * </p>
  114. * @type {number}
  115. * @default 0.9
  116. */
  117. this.atmosphereMieAnisotropy = 0.9;
  118. /**
  119. * The hue shift to apply to the atmosphere. Defaults to 0.0 (no shift).
  120. * A hue shift of 1.0 indicates a complete rotation of the hues available.
  121. * @type {number}
  122. * @default 0.0
  123. */
  124. this.hueShift = 0.0;
  125. /**
  126. * The saturation shift to apply to the atmosphere. Defaults to 0.0 (no shift).
  127. * A saturation shift of -1.0 is monochrome.
  128. * @type {number}
  129. * @default 0.0
  130. */
  131. this.saturationShift = 0.0;
  132. /**
  133. * The brightness shift to apply to the atmosphere. Defaults to 0.0 (no shift).
  134. * A brightness shift of -1.0 is complete darkness, which will let space show through.
  135. * @type {number}
  136. * @default 0.0
  137. */
  138. this.brightnessShift = 0.0;
  139. this._hueSaturationBrightness = new Cartesian3();
  140. // outer radius, inner radius, dynamic atmosphere color flag
  141. const radiiAndDynamicAtmosphereColor = new Cartesian3();
  142. radiiAndDynamicAtmosphereColor.x =
  143. ellipsoid.maximumRadius * outerEllipsoidScale;
  144. radiiAndDynamicAtmosphereColor.y = ellipsoid.maximumRadius;
  145. // Toggles whether the sun position is used. 0 treats the sun as always directly overhead.
  146. radiiAndDynamicAtmosphereColor.z = 0;
  147. this._radiiAndDynamicAtmosphereColor = radiiAndDynamicAtmosphereColor;
  148. const that = this;
  149. this._command.uniformMap = {
  150. u_radiiAndDynamicAtmosphereColor: function () {
  151. return that._radiiAndDynamicAtmosphereColor;
  152. },
  153. u_hsbShift: function () {
  154. that._hueSaturationBrightness.x = that.hueShift;
  155. that._hueSaturationBrightness.y = that.saturationShift;
  156. that._hueSaturationBrightness.z = that.brightnessShift;
  157. return that._hueSaturationBrightness;
  158. },
  159. u_atmosphereLightIntensity: function () {
  160. return that.atmosphereLightIntensity;
  161. },
  162. u_atmosphereRayleighCoefficient: function () {
  163. return that.atmosphereRayleighCoefficient;
  164. },
  165. u_atmosphereMieCoefficient: function () {
  166. return that.atmosphereMieCoefficient;
  167. },
  168. u_atmosphereRayleighScaleHeight: function () {
  169. return that.atmosphereRayleighScaleHeight;
  170. },
  171. u_atmosphereMieScaleHeight: function () {
  172. return that.atmosphereMieScaleHeight;
  173. },
  174. u_atmosphereMieAnisotropy: function () {
  175. return that.atmosphereMieAnisotropy;
  176. },
  177. };
  178. }
  179. Object.defineProperties(SkyAtmosphere.prototype, {
  180. /**
  181. * Gets the ellipsoid the atmosphere is drawn around.
  182. * @memberof SkyAtmosphere.prototype
  183. *
  184. * @type {Ellipsoid}
  185. * @readonly
  186. */
  187. ellipsoid: {
  188. get: function () {
  189. return this._ellipsoid;
  190. },
  191. },
  192. });
  193. /**
  194. * Set the dynamic lighting enum value for the shader
  195. * @param {DynamicAtmosphereLightingType} lightingEnum The enum that determines the dynamic atmosphere light source
  196. *
  197. * @private
  198. */
  199. SkyAtmosphere.prototype.setDynamicLighting = function (lightingEnum) {
  200. this._radiiAndDynamicAtmosphereColor.z = lightingEnum;
  201. };
  202. const scratchModelMatrix = new Matrix4();
  203. /**
  204. * @private
  205. */
  206. SkyAtmosphere.prototype.update = function (frameState, globe) {
  207. if (!this.show) {
  208. return undefined;
  209. }
  210. const mode = frameState.mode;
  211. if (mode !== SceneMode.SCENE3D && mode !== SceneMode.MORPHING) {
  212. return undefined;
  213. }
  214. // The atmosphere is only rendered during the render pass; it is not pickable, it doesn't cast shadows, etc.
  215. if (!frameState.passes.render) {
  216. return undefined;
  217. }
  218. // Align the ellipsoid geometry so it always faces the same direction as the
  219. // camera to reduce artifacts when rendering atmosphere per-vertex
  220. const rotationMatrix = Matrix4.fromRotationTranslation(
  221. frameState.context.uniformState.inverseViewRotation,
  222. Cartesian3.ZERO,
  223. scratchModelMatrix,
  224. );
  225. const rotationOffsetMatrix = Matrix4.multiplyTransformation(
  226. rotationMatrix,
  227. Axis.Y_UP_TO_Z_UP,
  228. scratchModelMatrix,
  229. );
  230. const modelMatrix = Matrix4.multiply(
  231. this._scaleMatrix,
  232. rotationOffsetMatrix,
  233. scratchModelMatrix,
  234. );
  235. Matrix4.clone(modelMatrix, this._modelMatrix);
  236. const context = frameState.context;
  237. const colorCorrect = hasColorCorrection(this);
  238. const translucent = frameState.globeTranslucencyState.translucent;
  239. const perFragmentAtmosphere =
  240. this.perFragmentAtmosphere || translucent || !defined(globe) || !globe.show;
  241. const command = this._command;
  242. if (!defined(command.vertexArray)) {
  243. const geometry = EllipsoidGeometry.createGeometry(
  244. new EllipsoidGeometry({
  245. radii: new Cartesian3(1.0, 1.0, 1.0),
  246. slicePartitions: 256,
  247. stackPartitions: 256,
  248. vertexFormat: VertexFormat.POSITION_ONLY,
  249. }),
  250. );
  251. command.vertexArray = VertexArray.fromGeometry({
  252. context: context,
  253. geometry: geometry,
  254. attributeLocations: GeometryPipeline.createAttributeLocations(geometry),
  255. bufferUsage: BufferUsage.STATIC_DRAW,
  256. });
  257. command.renderState = RenderState.fromCache({
  258. cull: {
  259. enabled: true,
  260. face: CullFace.FRONT,
  261. },
  262. blending: BlendingState.ALPHA_BLEND,
  263. depthMask: false,
  264. });
  265. }
  266. const flags =
  267. colorCorrect | (perFragmentAtmosphere << 2) | (translucent << 3);
  268. if (flags !== this._flags) {
  269. this._flags = flags;
  270. const defines = [];
  271. if (colorCorrect) {
  272. defines.push("COLOR_CORRECT");
  273. }
  274. if (perFragmentAtmosphere) {
  275. defines.push("PER_FRAGMENT_ATMOSPHERE");
  276. }
  277. if (translucent) {
  278. defines.push("GLOBE_TRANSLUCENT");
  279. }
  280. const vs = new ShaderSource({
  281. defines: defines,
  282. sources: [AtmosphereCommon, SkyAtmosphereCommon, SkyAtmosphereVS],
  283. });
  284. const fs = new ShaderSource({
  285. defines: defines,
  286. sources: [AtmosphereCommon, SkyAtmosphereCommon, SkyAtmosphereFS],
  287. });
  288. this._spSkyAtmosphere = ShaderProgram.fromCache({
  289. context: context,
  290. vertexShaderSource: vs,
  291. fragmentShaderSource: fs,
  292. });
  293. command.shaderProgram = this._spSkyAtmosphere;
  294. }
  295. return command;
  296. };
  297. function hasColorCorrection(skyAtmosphere) {
  298. return !(
  299. CesiumMath.equalsEpsilon(
  300. skyAtmosphere.hueShift,
  301. 0.0,
  302. CesiumMath.EPSILON7,
  303. ) &&
  304. CesiumMath.equalsEpsilon(
  305. skyAtmosphere.saturationShift,
  306. 0.0,
  307. CesiumMath.EPSILON7,
  308. ) &&
  309. CesiumMath.equalsEpsilon(
  310. skyAtmosphere.brightnessShift,
  311. 0.0,
  312. CesiumMath.EPSILON7,
  313. )
  314. );
  315. }
  316. /**
  317. * Returns true if this object was destroyed; otherwise, false.
  318. * <br /><br />
  319. * If this object was destroyed, it should not be used; calling any function other than
  320. * <code>isDestroyed</code> will result in a {@link DeveloperError} exception.
  321. *
  322. * @returns {boolean} <code>true</code> if this object was destroyed; otherwise, <code>false</code>.
  323. *
  324. * @see SkyAtmosphere#destroy
  325. */
  326. SkyAtmosphere.prototype.isDestroyed = function () {
  327. return false;
  328. };
  329. /**
  330. * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic
  331. * release of WebGL resources, instead of relying on the garbage collector to destroy this object.
  332. * <br /><br />
  333. * Once an object is destroyed, it should not be used; calling any function other than
  334. * <code>isDestroyed</code> will result in a {@link DeveloperError} exception. Therefore,
  335. * assign the return value (<code>undefined</code>) to the object as done in the example.
  336. *
  337. * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
  338. *
  339. *
  340. * @example
  341. * skyAtmosphere = skyAtmosphere && skyAtmosphere.destroy();
  342. *
  343. * @see SkyAtmosphere#isDestroyed
  344. */
  345. SkyAtmosphere.prototype.destroy = function () {
  346. const command = this._command;
  347. command.vertexArray = command.vertexArray && command.vertexArray.destroy();
  348. this._spSkyAtmosphere =
  349. this._spSkyAtmosphere && this._spSkyAtmosphere.destroy();
  350. return destroyObject(this);
  351. };
  352. export default SkyAtmosphere;