cesium天空盒子对应方位

3,347 阅读1分钟

  星辰天空盒子不够用怎么办,想换个蓝天,按照官网给出的参考代码发现视角是倾斜的,并不能跟火星科技或者是其他的gis给出的示例那样是非常好看的近地天空盒,本次研究开始。

cesium版本:V1.67.0

一:调整网上下载的天空盒素材

  站在negz的位置,背对电脑屏幕,对应关系如下:

  • negz→down
  • posx→right
  • negx→left
  • posy→front
  • posz→up
  • negy→back

  right图左旋90度,left图右旋90度,front图旋转180度,back图不管。

二:修改cesium的skybox源码

(cesium/Source/Scene/skyBox.js)

1)引入依赖

import Transforms from '../Core/Transforms.js';
import Matrix3 from '../Core/Matrix3.js'

2)添加近地属性

function SkyBox(options) {
    this.sources = options.sources;
    this._sources = undefined;

    /**
     * 是否开启近地模式
     */
    this.nearGround = options.nearGround;
    }

3)添加旋转矩阵检测

command.uniformMap = {
                        u_cubeMap: function() {
                            return that._cubeMap;
                        },
                /**
                   * 添加旋转矩阵
                  */
                    u_rotateMatrix: function() {
                        return that.nearGround ? (command.modelMatrix = Transforms.eastNorthUpToFixedFrame(frameState.camera._positionWC),
                            Matrix4.getMatrix3(command.modelMatrix, new Matrix3)) : Matrix3.IDENTITY;
                    }
                    };

(SkyBoxVS.glsl)

attribute vec3 position;
uniform mat3 u_rotateMatrix;
varying vec3 v_texCoord;

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;
}

打包重新生成下,打包命令是npn run release。

三:实现代码

const defaultSkyBox = viewer.scene.skyBox;
    const cloudSkyBox = new Cesium.SkyBox({
        sources: {
            positiveX: '../Source/Images/skybox/Right.jpg',
            negativeX: '../Source/Images/skybox/Left.jpg',
            positiveY: '../Source/Images/skybox/Front.jpg',
            negativeY: '../Source/Images/skybox/Back.jpg',
            positiveZ: '../Source/Images/skybox/Up.jpg',
            negativeZ: '../Source/Images/skybox/Down.jpg'

        }
    });
    viewer.scene.postRender.addEventListener(function() {
        const e = viewer.camera.position;
        if (Cesium.Cartographic.fromCartesian(e).height < 2000) {
            viewer.scene.skyBox.nearGround = true;
            viewer.scene.skyBox = cloudSkyBox;
            viewer.scene.skyAtmosphere.show = false;
        } else {
            viewer.scene.skyBox = defaultSkyBox;
            viewer.scene.skyAtmosphere.show = true;
        }
    });

最终结果如下: