Cesium-Examples/examples/cesiumEx/5.1.10、高度雾升级.html

121 lines
5.1 KiB
HTML
Raw Normal View History

2025-03-11 08:25:45 +00:00
<!--********************************************************************
* by jiawanlong
*********************************************************************-->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
2025-03-19 03:00:22 +00:00
<link rel="stylesheet" href="./../../libs/cesium/Cesium1.98/Widgets/widgets.css">
<script type="text/javascript" src="./../../libs/cesium/Cesium1.98/Cesium.js"></script>
2025-03-11 08:25:45 +00:00
</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>