You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SkyBox.js 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /**
  2. * @Author: Caven
  3. * @Date: 2021-02-21 17:50:31
  4. */
  5. import { Cesium } from '@dc-modules/namespace'
  6. const {
  7. BoxGeometry,
  8. Cartesian3,
  9. defined,
  10. DeveloperError,
  11. GeometryPipeline,
  12. Matrix3,
  13. Matrix4,
  14. Transforms,
  15. VertexFormat,
  16. BufferUsage,
  17. CubeMap,
  18. loadCubeMap,
  19. RenderState,
  20. VertexArray,
  21. BlendingState,
  22. SceneMode,
  23. ShaderProgram,
  24. ShaderSource
  25. } = Cesium
  26. const SkyBoxFS = `
  27. uniform samplerCube u_cubeMap;
  28. varying vec3 v_texCoord;
  29. void main()
  30. {
  31. vec4 color = textureCube(u_cubeMap, normalize(v_texCoord));
  32. gl_FragColor = vec4(czm_gammaCorrect(color).rgb, czm_morphTime);
  33. }
  34. `
  35. const SkyBoxVS = `
  36. attribute vec3 position;
  37. varying vec3 v_texCoord;
  38. uniform mat3 u_rotateMatrix;
  39. void main()
  40. {
  41. vec3 p = czm_viewRotation * u_rotateMatrix * (czm_temeToPseudoFixed * (czm_entireFrustum.y * position));
  42. gl_Position = czm_projection * vec4(p, 1.0);
  43. v_texCoord = position.xyz;
  44. }
  45. `
  46. class SkyBox extends Cesium.SkyBox {
  47. constructor(options = {}) {
  48. super(options)
  49. this.offsetAngle = options?.offsetAngle || 90
  50. }
  51. update(frameState, useHdr) {
  52. const that = this
  53. if (!this.show) {
  54. return undefined
  55. }
  56. if (
  57. frameState.mode !== SceneMode.SCENE3D &&
  58. frameState.mode !== SceneMode.MORPHING
  59. ) {
  60. return undefined
  61. }
  62. if (!frameState.passes.render) {
  63. return undefined
  64. }
  65. const context = frameState.context
  66. if (this._sources !== this.sources) {
  67. this._sources = this.sources
  68. const sources = this.sources
  69. if (
  70. !defined(sources.positiveX) ||
  71. !defined(sources.negativeX) ||
  72. !defined(sources.positiveY) ||
  73. !defined(sources.negativeY) ||
  74. !defined(sources.positiveZ) ||
  75. !defined(sources.negativeZ)
  76. ) {
  77. throw new DeveloperError(
  78. 'this.sources is required and must have positiveX, negativeX, positiveY, negativeY, positiveZ, and negativeZ properties.'
  79. )
  80. }
  81. if (
  82. typeof sources.positiveX !== typeof sources.negativeX ||
  83. typeof sources.positiveX !== typeof sources.positiveY ||
  84. typeof sources.positiveX !== typeof sources.negativeY ||
  85. typeof sources.positiveX !== typeof sources.positiveZ ||
  86. typeof sources.positiveX !== typeof sources.negativeZ
  87. ) {
  88. throw new DeveloperError(
  89. 'this.sources properties must all be the same type.'
  90. )
  91. }
  92. if (typeof sources.positiveX === 'string') {
  93. // Given urls for cube-map images. Load them.
  94. loadCubeMap(context, this._sources).then(function(cubeMap) {
  95. that._cubeMap = that._cubeMap && that._cubeMap.destroy()
  96. that._cubeMap = cubeMap
  97. })
  98. } else {
  99. this._cubeMap = this._cubeMap && this._cubeMap.destroy()
  100. this._cubeMap = new CubeMap({
  101. context: context,
  102. source: sources
  103. })
  104. }
  105. }
  106. const command = this._command
  107. command.modelMatrix = Transforms.eastNorthUpToFixedFrame(
  108. frameState.camera.positionWC
  109. )
  110. if (this.offsetAngle !== 0) {
  111. Matrix4.multiply(
  112. command.modelMatrix,
  113. Matrix4.fromRotationTranslation(
  114. Matrix3.fromRotationZ((this.offsetAngle / 180) * Math.PI)
  115. ),
  116. command.modelMatrix
  117. )
  118. }
  119. if (!defined(command.vertexArray)) {
  120. command.uniformMap = {
  121. u_cubeMap: function() {
  122. return that._cubeMap
  123. },
  124. u_rotateMatrix: function() {
  125. return Matrix4.getMatrix3(command.modelMatrix, new Matrix3())
  126. }
  127. }
  128. const geometry = BoxGeometry.createGeometry(
  129. BoxGeometry.fromDimensions({
  130. dimensions: new Cartesian3(2.0, 2.0, 2.0),
  131. vertexFormat: VertexFormat.POSITION_ONLY
  132. })
  133. )
  134. const attributeLocations = (this._attributeLocations = GeometryPipeline.createAttributeLocations(
  135. geometry
  136. ))
  137. command.vertexArray = VertexArray.fromGeometry({
  138. context: context,
  139. geometry: geometry,
  140. attributeLocations: attributeLocations,
  141. bufferUsage: BufferUsage._DRAW
  142. })
  143. command.renderState = RenderState.fromCache({
  144. blending: BlendingState.ALPHA_BLEND
  145. })
  146. }
  147. if (!defined(command.shaderProgram) || this._useHdr !== useHdr) {
  148. const fs = new ShaderSource({
  149. defines: [useHdr ? 'HDR' : ''],
  150. sources: [SkyBoxFS]
  151. })
  152. command.shaderProgram = ShaderProgram.fromCache({
  153. context: context,
  154. vertexShaderSource: SkyBoxVS,
  155. fragmentShaderSource: fs,
  156. attributeLocations: this._attributeLocations
  157. })
  158. this._useHdr = useHdr
  159. }
  160. if (!defined(this._cubeMap)) {
  161. return undefined
  162. }
  163. return command
  164. }
  165. }
  166. export default SkyBox