Cesium-Examples/examples/cesiumEx/5.1.10、高度雾升级.html
2025-03-19 11:00:22 +08:00

121 lines
5.1 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!--********************************************************************
* 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>