/** * @Author: Caven * @Date: 2021-02-21 17:50:31 */ import { Cesium } from '@dc-modules/namespace' const { BoxGeometry, Cartesian3, defined, DeveloperError, GeometryPipeline, Matrix3, Matrix4, Transforms, VertexFormat, BufferUsage, CubeMap, loadCubeMap, RenderState, VertexArray, BlendingState, SceneMode, ShaderProgram, ShaderSource } = Cesium const SkyBoxFS = ` uniform samplerCube u_cubeMap; varying vec3 v_texCoord; void main() { vec4 color = textureCube(u_cubeMap, normalize(v_texCoord)); gl_FragColor = vec4(czm_gammaCorrect(color).rgb, czm_morphTime); } ` const SkyBoxVS = ` attribute vec3 position; varying vec3 v_texCoord; uniform mat3 u_rotateMatrix; void main() { vec3 p = czm_viewRotation * u_rotateMatrix * (czm_temeToPseudoFixed * (czm_entireFrustum.y * position)); gl_Position = czm_projection * vec4(p, 1.0); v_texCoord = position.xyz; } ` class SkyBox extends Cesium.SkyBox { constructor(options = {}) { super(options) this.offsetAngle = options?.offsetAngle || 90 } update(frameState, useHdr) { const that = this if (!this.show) { return undefined } if ( frameState.mode !== SceneMode.SCENE3D && frameState.mode !== SceneMode.MORPHING ) { return undefined } if (!frameState.passes.render) { return undefined } const context = frameState.context if (this._sources !== this.sources) { this._sources = this.sources const sources = this.sources if ( !defined(sources.positiveX) || !defined(sources.negativeX) || !defined(sources.positiveY) || !defined(sources.negativeY) || !defined(sources.positiveZ) || !defined(sources.negativeZ) ) { throw new DeveloperError( 'this.sources is required and must have positiveX, negativeX, positiveY, negativeY, positiveZ, and negativeZ properties.' ) } if ( typeof sources.positiveX !== typeof sources.negativeX || typeof sources.positiveX !== typeof sources.positiveY || typeof sources.positiveX !== typeof sources.negativeY || typeof sources.positiveX !== typeof sources.positiveZ || typeof sources.positiveX !== typeof sources.negativeZ ) { throw new DeveloperError( 'this.sources properties must all be the same type.' ) } if (typeof sources.positiveX === 'string') { // Given urls for cube-map images. Load them. loadCubeMap(context, this._sources).then(function(cubeMap) { that._cubeMap = that._cubeMap && that._cubeMap.destroy() that._cubeMap = cubeMap }) } else { this._cubeMap = this._cubeMap && this._cubeMap.destroy() this._cubeMap = new CubeMap({ context: context, source: sources }) } } const command = this._command command.modelMatrix = Transforms.eastNorthUpToFixedFrame( frameState.camera.positionWC ) if (this.offsetAngle !== 0) { Matrix4.multiply( command.modelMatrix, Matrix4.fromRotationTranslation( Matrix3.fromRotationZ((this.offsetAngle / 180) * Math.PI) ), command.modelMatrix ) } if (!defined(command.vertexArray)) { command.uniformMap = { u_cubeMap: function() { return that._cubeMap }, u_rotateMatrix: function() { return Matrix4.getMatrix3(command.modelMatrix, new Matrix3()) } } const geometry = BoxGeometry.createGeometry( BoxGeometry.fromDimensions({ dimensions: new Cartesian3(2.0, 2.0, 2.0), vertexFormat: VertexFormat.POSITION_ONLY }) ) const attributeLocations = (this._attributeLocations = GeometryPipeline.createAttributeLocations( geometry )) command.vertexArray = VertexArray.fromGeometry({ context: context, geometry: geometry, attributeLocations: attributeLocations, bufferUsage: BufferUsage._DRAW }) command.renderState = RenderState.fromCache({ blending: BlendingState.ALPHA_BLEND }) } if (!defined(command.shaderProgram) || this._useHdr !== useHdr) { const fs = new ShaderSource({ defines: [useHdr ? 'HDR' : ''], sources: [SkyBoxFS] }) command.shaderProgram = ShaderProgram.fromCache({ context: context, vertexShaderSource: SkyBoxVS, fragmentShaderSource: fs, attributeLocations: this._attributeLocations }) this._useHdr = useHdr } if (!defined(this._cubeMap)) { return undefined } return command } } export default SkyBox