mirror of
https://github.com/jiawanlong/Cesium-Examples.git
synced 2025-07-04 15:17:36 +00:00
121 lines
5.1 KiB
HTML
121 lines
5.1 KiB
HTML
<!--********************************************************************
|
||
* by jiawanlong
|
||
*********************************************************************-->
|
||
<!DOCTYPE html>
|
||
<html>
|
||
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<link rel="stylesheet" href="./../../libs/cesium/Cesium1.98/Widgets/widgets.css">
|
||
<script type="text/javascript" src="./../../libs/cesium/Cesium1.98/Cesium.js"></script>
|
||
</head>
|
||
|
||
<body style="margin: 0; overflow: hidden; background: #fff; width: 100%; height: 100%; position: absolute; top: 0">
|
||
<div id="map" style="margin: 0 auto; width: 100%; height: 100%"></div>
|
||
<script type="text/javascript">
|
||
|
||
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI3ZjQ5ZGUzNC1jNWYwLTQ1ZTMtYmNjYS05YTY4ZTVmN2I2MDkiLCJpZCI6MTE3MTM4LCJpYXQiOjE2NzY0NDUyODB9.ZaNSBIfc1sGLhQd_xqhiSsc0yr8oS0wt1hAo9gbke6M'
|
||
const viewer = new Cesium.Viewer('map', {});
|
||
|
||
// 开启帧率
|
||
viewer.scene.debugShowFramesPerSecond = true;
|
||
// 深度监测
|
||
viewer.scene.globe.depthTestAgainstTerrain = true;
|
||
// 清除默认地形
|
||
viewer.scene.terrainProvider = new Cesium.EllipsoidTerrainProvider({});
|
||
|
||
// 加载火星地形
|
||
viewer.terrainProvider = new Cesium.CesiumTerrainProvider({
|
||
url: 'http://data.mars3d.cn/terrain'
|
||
})
|
||
|
||
const fs = `
|
||
uniform sampler2D colorTexture; // 颜色纹理
|
||
uniform sampler2D depthTexture; // 深度纹理
|
||
in vec2 v_textureCoordinates; // 纹理坐标
|
||
uniform float u_earthRadiusOnCamera;
|
||
uniform float u_cameraHeight;
|
||
uniform float u_fogHeight;
|
||
uniform vec3 u_fogColor;
|
||
uniform float u_globalDensity;
|
||
// 通过深度纹理与纹理坐标得到世界坐标
|
||
vec4 getWorldCoordinate(sampler2D depthTexture, vec2 texCoords) {
|
||
float depthOrLogDepth = czm_unpackDepth(texture(depthTexture, texCoords));
|
||
vec4 eyeCoordinate = czm_windowToEyeCoordinates(gl_FragCoord.xy, depthOrLogDepth);
|
||
eyeCoordinate = eyeCoordinate / eyeCoordinate.w;
|
||
vec4 worldCoordinate = czm_inverseView * eyeCoordinate;
|
||
worldCoordinate = worldCoordinate / worldCoordinate.w;
|
||
return worldCoordinate;
|
||
}
|
||
// 计算粗略的高程,依赖js传递的相机位置处的地球高程u_earthRadiusOnCamera。好处是计算量非常低
|
||
float getRoughHeight(vec4 worldCoordinate) {
|
||
float disToCenter = length(vec3(worldCoordinate));
|
||
return disToCenter - u_earthRadiusOnCamera;
|
||
}
|
||
// 得到a向量在b向量的投影长度,如果同向结果为正,异向结果为复
|
||
float projectVector(vec3 a, vec3 b) {
|
||
float scale = dot(a, b) / dot(b, b);
|
||
float k = scale / abs(scale);
|
||
return k * length(scale * b);
|
||
}
|
||
// 线性浓度积分高度雾
|
||
float linearHeightFog(vec3 positionToCamera, float cameraHeight, float pixelHeight, float fogMaxHeight) {
|
||
float globalDensity = u_globalDensity / 10.0;
|
||
vec3 up = -1.0 * normalize(czm_viewerPositionWC);
|
||
float vh = projectVector(normalize(positionToCamera), up);
|
||
|
||
// 让相机沿着视线方向移动 雾气产生距离 的距离
|
||
float s = step(100.0, length(positionToCamera));
|
||
vec3 sub = mix(positionToCamera, normalize(positionToCamera) * 100.0, s);
|
||
positionToCamera -= sub;
|
||
cameraHeight = mix(pixelHeight, cameraHeight - 100.0 * vh, s);
|
||
|
||
float b = mix(cameraHeight, fogMaxHeight, step(fogMaxHeight, cameraHeight));
|
||
float a = mix(pixelHeight, fogMaxHeight, step(fogMaxHeight, pixelHeight));
|
||
|
||
float fog = (b - a) - 0.5 * (pow(b, 2.0) - pow(a, 2.0)) / fogMaxHeight;
|
||
fog = globalDensity * fog / vh;
|
||
|
||
if(abs(vh) <= 0.01 && cameraHeight < fogMaxHeight) {
|
||
float disToCamera = length(positionToCamera);
|
||
fog = globalDensity * (1.0 - cameraHeight / fogMaxHeight) * disToCamera;
|
||
}
|
||
|
||
fog = mix(0.0, 1.0, fog / (fog + 1.0));
|
||
|
||
return fog;
|
||
}
|
||
void main(void) {
|
||
vec4 color = texture(colorTexture, v_textureCoordinates);
|
||
vec4 positionWC = getWorldCoordinate(depthTexture, v_textureCoordinates);
|
||
float pixelHeight = getRoughHeight(positionWC);
|
||
vec3 positionToCamera = vec3(vec3(positionWC) - czm_viewerPositionWC);
|
||
float fog = linearHeightFog(positionToCamera, u_cameraHeight, pixelHeight, u_fogHeight);
|
||
out_FragColor = mix(color, vec4(u_fogColor, 1.0), fog);
|
||
}`
|
||
|
||
|
||
const customPostProcessStage = new Cesium.PostProcessStage({
|
||
fragmentShader: fs,
|
||
uniforms: {
|
||
u_earthRadiusOnCamera: () => Cesium.Cartesian3.magnitude(viewer.camera.positionWC) - viewer.camera.positionCartographic.height,
|
||
u_cameraHeight: () => viewer.camera.positionCartographic.height,
|
||
u_fogColor: () => new Cesium.Color(0.8, 0.82, 0.84),
|
||
u_fogHeight: () => 1000,
|
||
u_globalDensity: () => 0.6,
|
||
}
|
||
})
|
||
viewer.scene.postProcessStages.add(customPostProcessStage)
|
||
|
||
viewer.camera.setView({
|
||
destination:new Cesium.Cartesian3(-1386705.7605894802,5226754.975571179,3375582.2076837276),
|
||
orientation: {
|
||
heading:3.968066845543675, // east, default value is 0.0 (north)
|
||
pitch: -0.300780994602595, // default value (looking down)
|
||
roll: 0.00007913394522685024 // default value
|
||
}
|
||
});
|
||
</script>
|
||
</body>
|
||
|
||
</html> |