mirror of
				https://github.com/jiawanlong/Cesium-Examples.git
				synced 2025-11-04 09:14:17 +00:00 
			
		
		
		
	
		
			
	
	
		
			521 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			521 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 
								 | 
							
								/**
							 | 
						|||
| 
								 | 
							
								 * 可视域分析。
							 | 
						|||
| 
								 | 
							
								 *
							 | 
						|||
| 
								 | 
							
								 * @author Helsing
							 | 
						|||
| 
								 | 
							
								 * @date 2020/08/28
							 | 
						|||
| 
								 | 
							
								 * @alias viewshed
							 | 
						|||
| 
								 | 
							
								 * @class
							 | 
						|||
| 
								 | 
							
								 * @param {Cesium.Viewer} viewer Cesium三维视窗。
							 | 
						|||
| 
								 | 
							
								 * @param {Object} options 选项。
							 | 
						|||
| 
								 | 
							
								 * @param {Cesium.Cartesian3} options.viewPosition 观测点位置。
							 | 
						|||
| 
								 | 
							
								 * @param {Cesium.Cartesian3} options.viewPositionEnd 最远观测点位置(如果设置了观测距离,这个属性可以不设置)。
							 | 
						|||
| 
								 | 
							
								 * @param {Number} options.viewDistance 观测距离(单位`米`,默认值100)。
							 | 
						|||
| 
								 | 
							
								 * @param {Number} options.viewHeading 航向角(单位`度`,默认值0)。
							 | 
						|||
| 
								 | 
							
								 * @param {Number} options.viewPitch 俯仰角(单位`度`,默认值0)。
							 | 
						|||
| 
								 | 
							
								 * @param {Number} options.horizontalViewAngle 可视域水平夹角(单位`度`,默认值90)。
							 | 
						|||
| 
								 | 
							
								 * @param {Number} options.verticalViewAngle 可视域垂直夹角(单位`度`,默认值60)。
							 | 
						|||
| 
								 | 
							
								 * @param {Cesium.Color} options.visibleAreaColor 可视区域颜色(默认值`绿色`)。
							 | 
						|||
| 
								 | 
							
								 * @param {Cesium.Color} options.invisibleAreaColor 不可视区域颜色(默认值`红色`)。
							 | 
						|||
| 
								 | 
							
								 * @param {Boolean} options.enabled 阴影贴图是否可用。
							 | 
						|||
| 
								 | 
							
								 * @param {Boolean} options.softShadows 是否启用柔和阴影。
							 | 
						|||
| 
								 | 
							
								 * @param {Boolean} options.size 每个阴影贴图的大小。
							 | 
						|||
| 
								 | 
							
								 */
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								class viewshed extends analyser {
							 | 
						|||
| 
								 | 
							
								    constructor(viewer, options) {
							 | 
						|||
| 
								 | 
							
								        super(viewer);
							 | 
						|||
| 
								 | 
							
								        this.viewer = viewer;
							 | 
						|||
| 
								 | 
							
								        this.viewPosition = options.viewPosition;
							 | 
						|||
| 
								 | 
							
								        this.viewPositionEnd = options.viewPositionEnd;
							 | 
						|||
| 
								 | 
							
								        this.viewDistance = this.viewPositionEnd ? Cesium.Cartesian3.distance(this.viewPosition, this.viewPositionEnd) : (options.viewDistance || 100.0);
							 | 
						|||
| 
								 | 
							
								        this.viewHeading = this.viewPositionEnd ? getHeading(this.viewPosition, this.viewPositionEnd) : (options.viewHeading || 0.0);
							 | 
						|||
| 
								 | 
							
								        this.viewPitch = this.viewPositionEnd ? getPitch(this.viewPosition, this.viewPositionEnd) : (options.viewPitch || 0.0);
							 | 
						|||
| 
								 | 
							
								        this.horizontalViewAngle = options.horizontalViewAngle || 90.0;
							 | 
						|||
| 
								 | 
							
								        this.verticalViewAngle = options.verticalViewAngle || 60.0;
							 | 
						|||
| 
								 | 
							
								        this.visibleAreaColor = options.visibleAreaColor || Cesium.Color.GREEN;
							 | 
						|||
| 
								 | 
							
								        this.invisibleAreaColor = options.invisibleAreaColor || Cesium.Color.RED;
							 | 
						|||
| 
								 | 
							
								        this.enabled = (typeof options.enabled === "boolean") ? options.enabled : true;
							 | 
						|||
| 
								 | 
							
								        this.softShadows = (typeof options.softShadows === "boolean") ? options.softShadows : true;
							 | 
						|||
| 
								 | 
							
								        this.size = options.size || 2048;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        this.options = options;
							 | 
						|||
| 
								 | 
							
								        this.id = Cesium.createGuid();
							 | 
						|||
| 
								 | 
							
								        this._resultTip = this.viewer.entities.add({
							 | 
						|||
| 
								 | 
							
								            id: this.id,
							 | 
						|||
| 
								 | 
							
								            label: {
							 | 
						|||
| 
								 | 
							
								                fillColor: Cesium.Color.YELLOW,
							 | 
						|||
| 
								 | 
							
								                showBackground: true,
							 | 
						|||
| 
								 | 
							
								                font: '14px monospace',
							 | 
						|||
| 
								 | 
							
								                horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
							 | 
						|||
| 
								 | 
							
								                verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
							 | 
						|||
| 
								 | 
							
								                pixelOffset: new Cesium.Cartesian2(0, -10)
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								        });
							 | 
						|||
| 
								 | 
							
								        this.posArray = [];
							 | 
						|||
| 
								 | 
							
								        this._markers = [];
							 | 
						|||
| 
								 | 
							
								        this.state = this.BEYONANALYSER_STATE.PREPARE;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        this.action();
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    action() {
							 | 
						|||
| 
								 | 
							
								        let _self = this;
							 | 
						|||
| 
								 | 
							
								        var ellipsoid = this.viewer.scene.globe.ellipsoid;
							 | 
						|||
| 
								 | 
							
								        _self.handler.setInputAction(function (movement) {
							 | 
						|||
| 
								 | 
							
								            var cartesian = latlng.getCurrentMousePosition(_self.viewer.scene, movement.position);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (_self._markers.length == 0) {
							 | 
						|||
| 
								 | 
							
												var temp1 = Cesium.Cartographic.fromCartesian( cartesian );
							 | 
						|||
| 
								 | 
							
												var h1 ;
							 | 
						|||
| 
								 | 
							
												if (_self.options.qdOffset) {
							 | 
						|||
| 
								 | 
							
													h1 = temp1.height + _self.options.qdOffset
							 | 
						|||
| 
								 | 
							
												}else{
							 | 
						|||
| 
								 | 
							
													h1 = temp1.height + 1;
							 | 
						|||
| 
								 | 
							
												}
							 | 
						|||
| 
								 | 
							
												var cartographictemp = Cesium.Cartographic.fromDegrees( temp1.longitude / Math.PI * 180, temp1.latitude / Math.PI * 180, h1);
							 | 
						|||
| 
								 | 
							
												cartesian = ellipsoid.cartographicToCartesian(cartographictemp);
							 | 
						|||
| 
								 | 
							
											} else if (_self._markers.length == 1) {
							 | 
						|||
| 
								 | 
							
												var temp1 = Cesium.Cartographic.fromCartesian( cartesian );
							 | 
						|||
| 
								 | 
							
												var h1 ;
							 | 
						|||
| 
								 | 
							
												if (_self.options.zdOffset) {
							 | 
						|||
| 
								 | 
							
													h1 = temp1.height + _self.options.qdOffset
							 | 
						|||
| 
								 | 
							
												}else{
							 | 
						|||
| 
								 | 
							
													h1 = temp1.height + 1;
							 | 
						|||
| 
								 | 
							
												}
							 | 
						|||
| 
								 | 
							
												var cartographictemp = Cesium.Cartographic.fromDegrees( temp1.longitude / Math.PI * 180, temp1.latitude / Math.PI * 180, h1);
							 | 
						|||
| 
								 | 
							
												cartesian = ellipsoid.cartographicToCartesian(cartographictemp);
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (!cartesian) {
							 | 
						|||
| 
								 | 
							
								                return;
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            _self.posArray.push(cartesian);
							 | 
						|||
| 
								 | 
							
								            if (_self._markers.length == 0) {
							 | 
						|||
| 
								 | 
							
								                var startSphere = _self.viewer.entities.add({
							 | 
						|||
| 
								 | 
							
								                    position: cartesian,
							 | 
						|||
| 
								 | 
							
								                    ellipsoid: {
							 | 
						|||
| 
								 | 
							
								                        radii: new Cesium.Cartesian3(1.0, 1.0, 1.0),
							 | 
						|||
| 
								 | 
							
								                        material: Cesium.Color.BLUE
							 | 
						|||
| 
								 | 
							
								                    },
							 | 
						|||
| 
								 | 
							
								                    label: {
							 | 
						|||
| 
								 | 
							
								                        text: "视线起点",
							 | 
						|||
| 
								 | 
							
								                        fillColor: Cesium.Color.YELLOW,
							 | 
						|||
| 
								 | 
							
								                        pixelOffset: {
							 | 
						|||
| 
								 | 
							
								                            x: 0,
							 | 
						|||
| 
								 | 
							
								                            y: -20
							 | 
						|||
| 
								 | 
							
								                        },
							 | 
						|||
| 
								 | 
							
								                        scale: 0.5
							 | 
						|||
| 
								 | 
							
								                    }
							 | 
						|||
| 
								 | 
							
								                });
							 | 
						|||
| 
								 | 
							
								                _self._markers.push(startSphere);
							 | 
						|||
| 
								 | 
							
								                _self.state = _self.BEYONANALYSER_STATE.OPERATING;
							 | 
						|||
| 
								 | 
							
								            } else if (_self._markers.length == 1) {
							 | 
						|||
| 
								 | 
							
								                var redSphere = _self.viewer.entities.add({
							 | 
						|||
| 
								 | 
							
								                    position: cartesian,
							 | 
						|||
| 
								 | 
							
								                    ellipsoid: {
							 | 
						|||
| 
								 | 
							
								                        radii: new Cesium.Cartesian3(1.0, 1.0, 1.0),
							 | 
						|||
| 
								 | 
							
								                        material: Cesium.Color.RED
							 | 
						|||
| 
								 | 
							
								                    },
							 | 
						|||
| 
								 | 
							
								                    label: {
							 | 
						|||
| 
								 | 
							
								                        text: "视线终点",
							 | 
						|||
| 
								 | 
							
								                        fillColor: Cesium.Color.YELLOW,
							 | 
						|||
| 
								 | 
							
								                        pixelOffset: {
							 | 
						|||
| 
								 | 
							
								                            x: 0,
							 | 
						|||
| 
								 | 
							
								                            y: -20
							 | 
						|||
| 
								 | 
							
								                        },
							 | 
						|||
| 
								 | 
							
								                        scale: 0.5
							 | 
						|||
| 
								 | 
							
								                    }
							 | 
						|||
| 
								 | 
							
								                });
							 | 
						|||
| 
								 | 
							
								                _self._markers.push(redSphere);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                _self.viewPosition = _self.posArray[0];
							 | 
						|||
| 
								 | 
							
								                _self.viewPositionEnd = cartesian;
							 | 
						|||
| 
								 | 
							
								                _self.viewDistance = _self.viewPositionEnd ? Cesium.Cartesian3.distance(_self.viewPosition, _self.viewPositionEnd) : (_self.options.viewDistance || 100.0);
							 | 
						|||
| 
								 | 
							
								                _self.viewHeading = _self.viewPositionEnd ? getHeading(_self.viewPosition, _self.viewPositionEnd) : (_self.options.viewHeading || 0.0);
							 | 
						|||
| 
								 | 
							
								                _self.viewPitch = _self.viewPositionEnd ? getPitch(_self.viewPosition, _self.viewPositionEnd) : (_self.options.viewPitch || 0.0);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                _self.state = _self.BEYONANALYSER_STATE.END;
							 | 
						|||
| 
								 | 
							
								                _self.handler.destroy();
							 | 
						|||
| 
								 | 
							
								                _self.handler = null;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                _self.remove();
							 | 
						|||
| 
								 | 
							
								                _self.update();
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								        }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
							 | 
						|||
| 
								 | 
							
								        //移动
							 | 
						|||
| 
								 | 
							
								        var info;
							 | 
						|||
| 
								 | 
							
								        _self.handler.setInputAction(function (movement) {
							 | 
						|||
| 
								 | 
							
								            var cartesian = _self.viewer.scene.pickPosition(movement.endPosition);
							 | 
						|||
| 
								 | 
							
								            if (_self.state === _self.BEYONANALYSER_STATE.PREPARE) {
							 | 
						|||
| 
								 | 
							
								                info = '点击设定起点';
							 | 
						|||
| 
								 | 
							
								                _self.showTip(_self._resultTip, true, cartesian, info);
							 | 
						|||
| 
								 | 
							
								            } else if (_self.state === _self.BEYONANALYSER_STATE.OPERATING) {
							 | 
						|||
| 
								 | 
							
								                info = '点击设定终点';
							 | 
						|||
| 
								 | 
							
								                _self.showTip(_self._resultTip, true, cartesian, info);
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								        }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    remove() {
							 | 
						|||
| 
								 | 
							
								        if (this._markers.length == 0) {
							 | 
						|||
| 
								 | 
							
								            return false;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        for (let index = 0; index < this._markers.length; index++) {
							 | 
						|||
| 
								 | 
							
								            var element = this._markers[index];
							 | 
						|||
| 
								 | 
							
								            this.viewer.entities.remove(element);
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								        this._markers.length = 0;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        this.viewer.entities.remove(this._resultTip);
							 | 
						|||
| 
								 | 
							
								        this._resultTip = undefined;
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    add() {
							 | 
						|||
| 
								 | 
							
								        this.createLightCamera();
							 | 
						|||
| 
								 | 
							
								        this.createShadowMap();
							 | 
						|||
| 
								 | 
							
								        this.createPostStage();
							 | 
						|||
| 
								 | 
							
								        this.drawFrustumOutline();
							 | 
						|||
| 
								 | 
							
								        this.drawSketch();
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    update() {
							 | 
						|||
| 
								 | 
							
								        this.clear();
							 | 
						|||
| 
								 | 
							
								        this.add();
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    clear() {
							 | 
						|||
| 
								 | 
							
								        if (this.sketch) {
							 | 
						|||
| 
								 | 
							
								            this.viewer.entities.removeById(this.sketch.id);
							 | 
						|||
| 
								 | 
							
								            this.sketch = null;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								        if (this.frustumOutline) {
							 | 
						|||
| 
								 | 
							
								            this.frustumOutline.destroy();
							 | 
						|||
| 
								 | 
							
								            this.frustumOutline = null;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								        if (this.postStage) {
							 | 
						|||
| 
								 | 
							
								            this.viewer.scene.postProcessStages.remove(this.postStage);
							 | 
						|||
| 
								 | 
							
								            this.postStage = null;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    //创建相机
							 | 
						|||
| 
								 | 
							
								    createLightCamera() {
							 | 
						|||
| 
								 | 
							
								        this.lightCamera = new Cesium.Camera(this.viewer.scene);
							 | 
						|||
| 
								 | 
							
								        this.lightCamera.position = this.viewPosition;
							 | 
						|||
| 
								 | 
							
								        // if (this.viewPositionEnd) {
							 | 
						|||
| 
								 | 
							
								        //     let direction = Cesium.Cartesian3.normalize(Cesium.Cartesian3.subtract(this.viewPositionEnd, this.viewPosition, new Cesium.Cartesian3()), new Cesium.Cartesian3());
							 | 
						|||
| 
								 | 
							
								        //     this.lightCamera.direction = direction; // direction是相机面向的方向
							 | 
						|||
| 
								 | 
							
								        // }
							 | 
						|||
| 
								 | 
							
								        this.lightCamera.frustum.near = this.viewDistance * 0.001;
							 | 
						|||
| 
								 | 
							
								        this.lightCamera.frustum.far = this.viewDistance;
							 | 
						|||
| 
								 | 
							
								        const hr = Cesium.Math.toRadians(this.horizontalViewAngle);
							 | 
						|||
| 
								 | 
							
								        const vr = Cesium.Math.toRadians(this.verticalViewAngle);
							 | 
						|||
| 
								 | 
							
								        const aspectRatio =
							 | 
						|||
| 
								 | 
							
								            (this.viewDistance * Math.tan(hr / 2) * 2) /
							 | 
						|||
| 
								 | 
							
								            (this.viewDistance * Math.tan(vr / 2) * 2);
							 | 
						|||
| 
								 | 
							
								        this.lightCamera.frustum.aspectRatio = aspectRatio;
							 | 
						|||
| 
								 | 
							
								        if (hr > vr) {
							 | 
						|||
| 
								 | 
							
								            this.lightCamera.frustum.fov = hr;
							 | 
						|||
| 
								 | 
							
								        } else {
							 | 
						|||
| 
								 | 
							
								            this.lightCamera.frustum.fov = vr;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								        this.lightCamera.setView({
							 | 
						|||
| 
								 | 
							
								            destination: this.viewPosition,
							 | 
						|||
| 
								 | 
							
								            orientation: {
							 | 
						|||
| 
								 | 
							
								                heading: Cesium.Math.toRadians(this.viewHeading || 0),
							 | 
						|||
| 
								 | 
							
								                pitch: Cesium.Math.toRadians(this.viewPitch || 0),
							 | 
						|||
| 
								 | 
							
								                roll: 0
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								        });
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    //创建阴影贴图
							 | 
						|||
| 
								 | 
							
								    createShadowMap() {
							 | 
						|||
| 
								 | 
							
								        this.shadowMap = new Cesium.ShadowMap({
							 | 
						|||
| 
								 | 
							
								            context: (this.viewer.scene).context,
							 | 
						|||
| 
								 | 
							
								            lightCamera: this.lightCamera,
							 | 
						|||
| 
								 | 
							
								            enabled: this.enabled,
							 | 
						|||
| 
								 | 
							
								            isPointLight: true,
							 | 
						|||
| 
								 | 
							
								            pointLightRadius: this.viewDistance,
							 | 
						|||
| 
								 | 
							
								            cascadesEnabled: false,
							 | 
						|||
| 
								 | 
							
								            size: this.size,
							 | 
						|||
| 
								 | 
							
								            softShadows: this.softShadows,
							 | 
						|||
| 
								 | 
							
								            normalOffset: false,
							 | 
						|||
| 
								 | 
							
								            fromLightSource: false
							 | 
						|||
| 
								 | 
							
								        });
							 | 
						|||
| 
								 | 
							
								        this.viewer.scene.shadowMap = this.shadowMap;
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    //创建PostStage
							 | 
						|||
| 
								 | 
							
								    createPostStage() {
							 | 
						|||
| 
								 | 
							
								        const fs = `
							 | 
						|||
| 
								 | 
							
								        #define USE_CUBE_MAP_SHADOW true
							 | 
						|||
| 
								 | 
							
								        uniform sampler2D colorTexture;
							 | 
						|||
| 
								 | 
							
								        uniform sampler2D depthTexture;
							 | 
						|||
| 
								 | 
							
								        varying vec2 v_textureCoordinates;
							 | 
						|||
| 
								 | 
							
								        uniform mat4 camera_projection_matrix;
							 | 
						|||
| 
								 | 
							
								        uniform mat4 camera_view_matrix;
							 | 
						|||
| 
								 | 
							
								        uniform samplerCube shadowMap_textureCube;
							 | 
						|||
| 
								 | 
							
								        uniform mat4 shadowMap_matrix;
							 | 
						|||
| 
								 | 
							
								        uniform vec4 shadowMap_lightPositionEC;
							 | 
						|||
| 
								 | 
							
								        uniform vec4 shadowMap_normalOffsetScaleDistanceMaxDistanceAndDarkness;
							 | 
						|||
| 
								 | 
							
								        uniform vec4 shadowMap_texelSizeDepthBiasAndNormalShadingSmooth;
							 | 
						|||
| 
								 | 
							
								        uniform float helsing_viewDistance; 
							 | 
						|||
| 
								 | 
							
								        uniform vec4 helsing_visibleAreaColor;
							 | 
						|||
| 
								 | 
							
								        uniform vec4 helsing_invisibleAreaColor;
							 | 
						|||
| 
								 | 
							
								        struct zx_shadowParameters
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            vec3 texCoords;
							 | 
						|||
| 
								 | 
							
								            float depthBias;
							 | 
						|||
| 
								 | 
							
								            float depth;
							 | 
						|||
| 
								 | 
							
								            float nDotL;
							 | 
						|||
| 
								 | 
							
								            vec2 texelStepSize;
							 | 
						|||
| 
								 | 
							
								            float normalShadingSmooth;
							 | 
						|||
| 
								 | 
							
								            float darkness;
							 | 
						|||
| 
								 | 
							
								        };
							 | 
						|||
| 
								 | 
							
								        float czm_shadowVisibility(samplerCube shadowMap, zx_shadowParameters shadowParameters)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            float depthBias = shadowParameters.depthBias;
							 | 
						|||
| 
								 | 
							
								            float depth = shadowParameters.depth;
							 | 
						|||
| 
								 | 
							
								            float nDotL = shadowParameters.nDotL;
							 | 
						|||
| 
								 | 
							
								            float normalShadingSmooth = shadowParameters.normalShadingSmooth;
							 | 
						|||
| 
								 | 
							
								            float darkness = shadowParameters.darkness;
							 | 
						|||
| 
								 | 
							
								            vec3 uvw = shadowParameters.texCoords;
							 | 
						|||
| 
								 | 
							
								            depth -= depthBias;
							 | 
						|||
| 
								 | 
							
								            float visibility = czm_shadowDepthCompare(shadowMap, uvw, depth);
							 | 
						|||
| 
								 | 
							
								            return czm_private_shadowVisibility(visibility, nDotL, normalShadingSmooth, darkness);
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								        vec4 getPositionEC(){
							 | 
						|||
| 
								 | 
							
								            return czm_windowToEyeCoordinates(gl_FragCoord);
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								        vec3 getNormalEC(){
							 | 
						|||
| 
								 | 
							
								            return vec3(1.);
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								        vec4 toEye( vec2 uv, float depth){
							 | 
						|||
| 
								 | 
							
								            vec2 xy=vec2((uv.x*2.-1.),(uv.y*2.-1.));
							 | 
						|||
| 
								 | 
							
								            vec4 posInCamera=czm_inverseProjection*vec4(xy,depth,1.);
							 | 
						|||
| 
								 | 
							
								            posInCamera=posInCamera/posInCamera.w;
							 | 
						|||
| 
								 | 
							
								            return posInCamera;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								        vec3 pointProjectOnPlane( vec3 planeNormal, vec3 planeOrigin, vec3 point){
							 | 
						|||
| 
								 | 
							
								            vec3 v01=point-planeOrigin;
							 | 
						|||
| 
								 | 
							
								            float d=dot(planeNormal,v01);
							 | 
						|||
| 
								 | 
							
								            return(point-planeNormal*d);
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								        float getDepth( vec4 depth){
							 | 
						|||
| 
								 | 
							
								            float z_window=czm_unpackDepth(depth);
							 | 
						|||
| 
								 | 
							
								            z_window=czm_reverseLogDepth(z_window);
							 | 
						|||
| 
								 | 
							
								            float n_range=czm_depthRange.near;
							 | 
						|||
| 
								 | 
							
								            float f_range=czm_depthRange.far;
							 | 
						|||
| 
								 | 
							
								            return(2.*z_window-n_range-f_range)/(f_range-n_range);
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								        float shadow( vec4 positionEC){
							 | 
						|||
| 
								 | 
							
								            vec3 normalEC=getNormalEC();
							 | 
						|||
| 
								 | 
							
								            zx_shadowParameters shadowParameters;
							 | 
						|||
| 
								 | 
							
								            shadowParameters.texelStepSize=shadowMap_texelSizeDepthBiasAndNormalShadingSmooth.xy;
							 | 
						|||
| 
								 | 
							
								            shadowParameters.depthBias=shadowMap_texelSizeDepthBiasAndNormalShadingSmooth.z;
							 | 
						|||
| 
								 | 
							
								            shadowParameters.normalShadingSmooth=shadowMap_texelSizeDepthBiasAndNormalShadingSmooth.w;
							 | 
						|||
| 
								 | 
							
								            shadowParameters.darkness=shadowMap_normalOffsetScaleDistanceMaxDistanceAndDarkness.w;
							 | 
						|||
| 
								 | 
							
								            vec3 directionEC=positionEC.xyz-shadowMap_lightPositionEC.xyz;
							 | 
						|||
| 
								 | 
							
								            float distance=length(directionEC);
							 | 
						|||
| 
								 | 
							
								            directionEC=normalize(directionEC);
							 | 
						|||
| 
								 | 
							
								            float radius=shadowMap_lightPositionEC.w;
							 | 
						|||
| 
								 | 
							
								            if(distance>radius)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                return 2.0;
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								            vec3 directionWC=czm_inverseViewRotation*directionEC;
							 | 
						|||
| 
								 | 
							
								            shadowParameters.depth=distance/radius-0.0003;
							 | 
						|||
| 
								 | 
							
								            shadowParameters.nDotL=clamp(dot(normalEC,-directionEC),0.,1.);
							 | 
						|||
| 
								 | 
							
								            shadowParameters.texCoords=directionWC;
							 | 
						|||
| 
								 | 
							
								            float visibility=czm_shadowVisibility(shadowMap_textureCube,shadowParameters);
							 | 
						|||
| 
								 | 
							
								            return visibility;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								        bool visible( vec4 result)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            result.x/=result.w;
							 | 
						|||
| 
								 | 
							
								            result.y/=result.w;
							 | 
						|||
| 
								 | 
							
								            result.z/=result.w;
							 | 
						|||
| 
								 | 
							
								            return result.x>=-1.&&result.x<=1.
							 | 
						|||
| 
								 | 
							
								            &&result.y>=-1.&&result.y<=1.
							 | 
						|||
| 
								 | 
							
								            &&result.z>=-1.&&result.z<=1.;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								        void main(){
							 | 
						|||
| 
								 | 
							
								            // 釉色 = 结构二维(颜色纹理, 纹理坐标)
							 | 
						|||
| 
								 | 
							
								            gl_FragColor = texture2D(colorTexture, v_textureCoordinates);
							 | 
						|||
| 
								 | 
							
								            // 深度 = 获取深度(结构二维(深度纹理, 纹理坐标))
							 | 
						|||
| 
								 | 
							
								            float depth = getDepth(texture2D(depthTexture, v_textureCoordinates));
							 | 
						|||
| 
								 | 
							
								            // 视角 = (纹理坐标, 深度)
							 | 
						|||
| 
								 | 
							
								            vec4 viewPos = toEye(v_textureCoordinates, depth);
							 | 
						|||
| 
								 | 
							
								            // 世界坐标
							 | 
						|||
| 
								 | 
							
								            vec4 wordPos = czm_inverseView * viewPos;
							 | 
						|||
| 
								 | 
							
								            // 虚拟相机中坐标
							 | 
						|||
| 
								 | 
							
								            vec4 vcPos = camera_view_matrix * wordPos;
							 | 
						|||
| 
								 | 
							
								            float near = .001 * helsing_viewDistance;
							 | 
						|||
| 
								 | 
							
								            float dis = length(vcPos.xyz);
							 | 
						|||
| 
								 | 
							
								            if(dis > near && dis < helsing_viewDistance){
							 | 
						|||
| 
								 | 
							
								                // 透视投影
							 | 
						|||
| 
								 | 
							
								                vec4 posInEye = camera_projection_matrix * vcPos;
							 | 
						|||
| 
								 | 
							
								                // 可视区颜色
							 | 
						|||
| 
								 | 
							
								                // vec4 helsing_visibleAreaColor=vec4(0.,1.,0.,.5);
							 | 
						|||
| 
								 | 
							
								                // vec4 helsing_invisibleAreaColor=vec4(1.,0.,0.,.5);
							 | 
						|||
| 
								 | 
							
								                if(visible(posInEye)){
							 | 
						|||
| 
								 | 
							
								                    float vis = shadow(viewPos);
							 | 
						|||
| 
								 | 
							
								                    if(vis > 0.3){
							 | 
						|||
| 
								 | 
							
								                        gl_FragColor = mix(gl_FragColor,helsing_visibleAreaColor,.5);
							 | 
						|||
| 
								 | 
							
								                    } else{
							 | 
						|||
| 
								 | 
							
								                        gl_FragColor = mix(gl_FragColor,helsing_invisibleAreaColor,.5);
							 | 
						|||
| 
								 | 
							
								                    }
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								        }`;
							 | 
						|||
| 
								 | 
							
								        const postStage = new Cesium.PostProcessStage({
							 | 
						|||
| 
								 | 
							
								            fragmentShader: fs,
							 | 
						|||
| 
								 | 
							
								            uniforms: {
							 | 
						|||
| 
								 | 
							
								                shadowMap_textureCube: () => {
							 | 
						|||
| 
								 | 
							
								                    this.shadowMap.update(Reflect.get(this.viewer.scene, "_frameState"));
							 | 
						|||
| 
								 | 
							
								                    return Reflect.get(this.shadowMap, "_shadowMapTexture");
							 | 
						|||
| 
								 | 
							
								                },
							 | 
						|||
| 
								 | 
							
								                shadowMap_matrix: () => {
							 | 
						|||
| 
								 | 
							
								                    this.shadowMap.update(Reflect.get(this.viewer.scene, "_frameState"));
							 | 
						|||
| 
								 | 
							
								                    return Reflect.get(this.shadowMap, "_shadowMapMatrix");
							 | 
						|||
| 
								 | 
							
								                },
							 | 
						|||
| 
								 | 
							
								                shadowMap_lightPositionEC: () => {
							 | 
						|||
| 
								 | 
							
								                    this.shadowMap.update(Reflect.get(this.viewer.scene, "_frameState"));
							 | 
						|||
| 
								 | 
							
								                    return Reflect.get(this.shadowMap, "_lightPositionEC");
							 | 
						|||
| 
								 | 
							
								                },
							 | 
						|||
| 
								 | 
							
								                shadowMap_normalOffsetScaleDistanceMaxDistanceAndDarkness: () => {
							 | 
						|||
| 
								 | 
							
								                    this.shadowMap.update(Reflect.get(this.viewer.scene, "_frameState"));
							 | 
						|||
| 
								 | 
							
								                    const bias = this.shadowMap._pointBias;
							 | 
						|||
| 
								 | 
							
								                    return Cesium.Cartesian4.fromElements(
							 | 
						|||
| 
								 | 
							
								                        bias.normalOffsetScale,
							 | 
						|||
| 
								 | 
							
								                        this.shadowMap._distance,
							 | 
						|||
| 
								 | 
							
								                        this.shadowMap.maximumDistance,
							 | 
						|||
| 
								 | 
							
								                        0.0,
							 | 
						|||
| 
								 | 
							
								                        new Cesium.Cartesian4()
							 | 
						|||
| 
								 | 
							
								                    );
							 | 
						|||
| 
								 | 
							
								                },
							 | 
						|||
| 
								 | 
							
								                shadowMap_texelSizeDepthBiasAndNormalShadingSmooth: () => {
							 | 
						|||
| 
								 | 
							
								                    this.shadowMap.update(Reflect.get(this.viewer.scene, "_frameState"));
							 | 
						|||
| 
								 | 
							
								                    const bias = this.shadowMap._pointBias;
							 | 
						|||
| 
								 | 
							
								                    const scratchTexelStepSize = new Cesium.Cartesian2();
							 | 
						|||
| 
								 | 
							
								                    const texelStepSize = scratchTexelStepSize;
							 | 
						|||
| 
								 | 
							
								                    texelStepSize.x = 1.0 / this.shadowMap._textureSize.x;
							 | 
						|||
| 
								 | 
							
								                    texelStepSize.y = 1.0 / this.shadowMap._textureSize.y;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                    return Cesium.Cartesian4.fromElements(
							 | 
						|||
| 
								 | 
							
								                        texelStepSize.x,
							 | 
						|||
| 
								 | 
							
								                        texelStepSize.y,
							 | 
						|||
| 
								 | 
							
								                        bias.depthBias,
							 | 
						|||
| 
								 | 
							
								                        bias.normalShadingSmooth,
							 | 
						|||
| 
								 | 
							
								                        new Cesium.Cartesian4()
							 | 
						|||
| 
								 | 
							
								                    );
							 | 
						|||
| 
								 | 
							
								                },
							 | 
						|||
| 
								 | 
							
								                camera_projection_matrix: this.lightCamera.frustum.projectionMatrix,
							 | 
						|||
| 
								 | 
							
								                camera_view_matrix: this.lightCamera.viewMatrix,
							 | 
						|||
| 
								 | 
							
								                helsing_viewDistance: () => {
							 | 
						|||
| 
								 | 
							
								                    return this.viewDistance;
							 | 
						|||
| 
								 | 
							
								                },
							 | 
						|||
| 
								 | 
							
								                helsing_visibleAreaColor: this.visibleAreaColor,
							 | 
						|||
| 
								 | 
							
								                helsing_invisibleAreaColor: this.invisibleAreaColor,
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								        });
							 | 
						|||
| 
								 | 
							
								        this.postStage = this.viewer.scene.postProcessStages.add(postStage);
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    //创建视锥线
							 | 
						|||
| 
								 | 
							
								    drawFrustumOutline() {
							 | 
						|||
| 
								 | 
							
								        const scratchRight = new Cesium.Cartesian3();
							 | 
						|||
| 
								 | 
							
								        const scratchRotation = new Cesium.Matrix3();
							 | 
						|||
| 
								 | 
							
								        const scratchOrientation = new Cesium.Quaternion();
							 | 
						|||
| 
								 | 
							
								        const position = this.lightCamera.positionWC;
							 | 
						|||
| 
								 | 
							
								        const direction = this.lightCamera.directionWC;
							 | 
						|||
| 
								 | 
							
								        const up = this.lightCamera.upWC;
							 | 
						|||
| 
								 | 
							
								        let right = this.lightCamera.rightWC;
							 | 
						|||
| 
								 | 
							
								        right = Cesium.Cartesian3.negate(right, scratchRight);
							 | 
						|||
| 
								 | 
							
								        let rotation = scratchRotation;
							 | 
						|||
| 
								 | 
							
								        Cesium.Matrix3.setColumn(rotation, 0, right, rotation);
							 | 
						|||
| 
								 | 
							
								        Cesium.Matrix3.setColumn(rotation, 1, up, rotation);
							 | 
						|||
| 
								 | 
							
								        Cesium.Matrix3.setColumn(rotation, 2, direction, rotation);
							 | 
						|||
| 
								 | 
							
								        let orientation = Cesium.Quaternion.fromRotationMatrix(rotation, scratchOrientation);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        let instance = new Cesium.GeometryInstance({
							 | 
						|||
| 
								 | 
							
								            geometry: new Cesium.FrustumOutlineGeometry({
							 | 
						|||
| 
								 | 
							
								                frustum: this.lightCamera.frustum,
							 | 
						|||
| 
								 | 
							
								                origin: this.viewPosition,
							 | 
						|||
| 
								 | 
							
								                orientation: orientation
							 | 
						|||
| 
								 | 
							
								            }),
							 | 
						|||
| 
								 | 
							
								            id: Math.random().toString(36).substr(2),
							 | 
						|||
| 
								 | 
							
								            attributes: {
							 | 
						|||
| 
								 | 
							
								                color: Cesium.ColorGeometryInstanceAttribute.fromColor(
							 | 
						|||
| 
								 | 
							
								                    Cesium.Color.YELLOWGREEN //new Cesium.Color(0.0, 1.0, 0.0, 1.0)
							 | 
						|||
| 
								 | 
							
								                ),
							 | 
						|||
| 
								 | 
							
								                show: new Cesium.ShowGeometryInstanceAttribute(true)
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								        });
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        this.frustumOutline = this.viewer.scene.primitives.add(
							 | 
						|||
| 
								 | 
							
								            new Cesium.Primitive({
							 | 
						|||
| 
								 | 
							
								                geometryInstances: [instance],
							 | 
						|||
| 
								 | 
							
								                appearance: new Cesium.PerInstanceColorAppearance({
							 | 
						|||
| 
								 | 
							
								                    flat: true,
							 | 
						|||
| 
								 | 
							
								                    translucent: false
							 | 
						|||
| 
								 | 
							
								                })
							 | 
						|||
| 
								 | 
							
								            })
							 | 
						|||
| 
								 | 
							
								        );
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    //创建视网
							 | 
						|||
| 
								 | 
							
								    drawSketch() {
							 | 
						|||
| 
								 | 
							
								        this.sketch = this.viewer.entities.add({
							 | 
						|||
| 
								 | 
							
								            name: 'sketch',
							 | 
						|||
| 
								 | 
							
								            position: this.viewPosition,
							 | 
						|||
| 
								 | 
							
								            orientation: Cesium.Transforms.headingPitchRollQuaternion(
							 | 
						|||
| 
								 | 
							
								                this.viewPosition,
							 | 
						|||
| 
								 | 
							
								                Cesium.HeadingPitchRoll.fromDegrees(this.viewHeading - this.horizontalViewAngle, this.viewPitch, 0.0)
							 | 
						|||
| 
								 | 
							
								            ),
							 | 
						|||
| 
								 | 
							
								            ellipsoid: {
							 | 
						|||
| 
								 | 
							
								                radii: new Cesium.Cartesian3(
							 | 
						|||
| 
								 | 
							
								                    this.viewDistance,
							 | 
						|||
| 
								 | 
							
								                    this.viewDistance,
							 | 
						|||
| 
								 | 
							
								                    this.viewDistance
							 | 
						|||
| 
								 | 
							
								                ),
							 | 
						|||
| 
								 | 
							
								                // innerRadii: new Cesium.Cartesian3(2.0, 2.0, 2.0),
							 | 
						|||
| 
								 | 
							
								                minimumClock: Cesium.Math.toRadians(-this.horizontalViewAngle / 2),
							 | 
						|||
| 
								 | 
							
								                maximumClock: Cesium.Math.toRadians(this.horizontalViewAngle / 2),
							 | 
						|||
| 
								 | 
							
								                minimumCone: Cesium.Math.toRadians(this.verticalViewAngle + 7.75),
							 | 
						|||
| 
								 | 
							
								                maximumCone: Cesium.Math.toRadians(180 - this.verticalViewAngle - 7.75),
							 | 
						|||
| 
								 | 
							
								                fill: false,
							 | 
						|||
| 
								 | 
							
								                outline: true,
							 | 
						|||
| 
								 | 
							
								                subdivisions: 256,
							 | 
						|||
| 
								 | 
							
								                stackPartitions: 64,
							 | 
						|||
| 
								 | 
							
								                slicePartitions: 64,
							 | 
						|||
| 
								 | 
							
								                outlineColor: Cesium.Color.YELLOWGREEN
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								        });
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								//获取偏航角
							 | 
						|||
| 
								 | 
							
								function getHeading(fromPosition, toPosition) {
							 | 
						|||
| 
								 | 
							
								    let finalPosition = new Cesium.Cartesian3();
							 | 
						|||
| 
								 | 
							
								    let matrix4 = Cesium.Transforms.eastNorthUpToFixedFrame(fromPosition);
							 | 
						|||
| 
								 | 
							
								    Cesium.Matrix4.inverse(matrix4, matrix4);
							 | 
						|||
| 
								 | 
							
								    Cesium.Matrix4.multiplyByPoint(matrix4, toPosition, finalPosition);
							 | 
						|||
| 
								 | 
							
								    Cesium.Cartesian3.normalize(finalPosition, finalPosition);
							 | 
						|||
| 
								 | 
							
								    return Cesium.Math.toDegrees(Math.atan2(finalPosition.x, finalPosition.y));
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								//获取俯仰角
							 | 
						|||
| 
								 | 
							
								function getPitch(fromPosition, toPosition) {
							 | 
						|||
| 
								 | 
							
								    let finalPosition = new Cesium.Cartesian3();
							 | 
						|||
| 
								 | 
							
								    let matrix4 = Cesium.Transforms.eastNorthUpToFixedFrame(fromPosition);
							 | 
						|||
| 
								 | 
							
								    Cesium.Matrix4.inverse(matrix4, matrix4);
							 | 
						|||
| 
								 | 
							
								    Cesium.Matrix4.multiplyByPoint(matrix4, toPosition, finalPosition);
							 | 
						|||
| 
								 | 
							
								    Cesium.Cartesian3.normalize(finalPosition, finalPosition);
							 | 
						|||
| 
								 | 
							
								    return Cesium.Math.toDegrees(Math.asin(finalPosition.z));
							 | 
						|||
| 
								 | 
							
								}
							 |