原文链接及内容

效果如下视频所示:

示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
const viewer = new Cesium.Viewer("cesiumContainer", {
geocoder: false,
sceneModePicker: false,
homeButton: false,
navigationHelpButton: false,
baseLayerPicker: false,
navigationInstructionsInitiallyVisible: false,
fullscreenButton: false,
selectionIndicator: false,
skyBox: false,
timeline: false,
animation: false,
shouldAnimate: true,
infoBox: false,
});

viewer.cesiumWidget.creditContainer.style.display = "none";

viewer.scene.camera.setView({
destination: new Cesium.Cartesian3(
1216356.033078094,
-4736402.278325668,
4081270.375520902,
),
orientation: new Cesium.HeadingPitchRoll(
0.08033365594766728,
-0.29519015695063455,
0.00027759141518046704,
),
endTransform: Cesium.Matrix4.IDENTITY,
});

if (!viewer.scene.context.depthTexture) {
window.alert("此浏览器不支持雾后期处理(post process)。");
}

const fragmentShaderSource = `
float getDistance(sampler2D depthTexture, vec2 texCoords)
{
float depth = czm_unpackDepth(texture(depthTexture, texCoords));
if (depth == 0.0) {
return czm_infinity;
}
vec4 eyeCoordinate = czm_windowToEyeCoordinates(gl_FragCoord.xy, depth);
return -eyeCoordinate.z / eyeCoordinate.w;
}
float interpolateByDistance(vec4 nearFarScalar, float distance)
{
float startDistance = nearFarScalar.x;
float startValue = nearFarScalar.y;
float endDistance = nearFarScalar.z;
float endValue = nearFarScalar.w;
float t = clamp((distance - startDistance) / (endDistance - startDistance), 0.0, 1.0);
return mix(startValue, endValue, t);
}
vec4 alphaBlend(vec4 sourceColor, vec4 destinationColor)
{
return sourceColor * vec4(sourceColor.aaa, 1.0) + destinationColor * (1.0 - sourceColor.a);
}
uniform sampler2D colorTexture;
uniform sampler2D depthTexture;
uniform vec4 fogByDistance;
uniform vec4 fogColor;
in vec2 v_textureCoordinates;
void main(void)
{
float distance = getDistance(depthTexture, v_textureCoordinates);
vec4 sceneColor = texture(colorTexture, v_textureCoordinates);
float blendAmount = interpolateByDistance(fogByDistance, distance);
vec4 finalFogColor = vec4(fogColor.rgb, fogColor.a * blendAmount);
out_FragColor = alphaBlend(finalFogColor, sceneColor);
}
`;

const ellipsoid = viewer.scene.globe.ellipsoid;
/**
* postProcessStages是一个 PostProcessStageCollection 对象,用于管理场景中的所有后处理阶段。
*/
const postProcessStage = viewer.scene.postProcessStages.add(
new Cesium.PostProcessStage({
/**
* fragmentShader属性: 要使用的片段着色器。默认的 sampler2D uniform 是 colorTexture 和 depthTexture。
* color 纹理是渲染场景或上一阶段的输出。
* depth 纹理是渲染场景的输出。
* 着色器应包含一个或两个 uniform。还有一个名为 v_textureCoordinates 的 vec2 变体,可用于对纹理进行采样。
*/
fragmentShader: fragmentShaderSource,
// uniforms属性:一个对象,其属性将用于设置着色器 uniform。属性可以是常量值或函数。常量值也可以是 URI、数据 URI 或用作纹理的 HTML 元素。
uniforms: {
/**
* fogByDistance: 它的类型是 Cesium.Cartesian4,对应 GLSL 中的 vec4,
* 通常用于控制雾效果的参数,但具体含义取决于 fragmentShaderSource 中如何使用这个 uniform。
* x (10): 雾开始的距离(近)。
* y (0.0): 雾的密度或强度(通常表示起始强度,这里是0.0)。
* z (200): 雾完全不透明的距离(远)。
* w (1.0): 雾的密度或衰减因子(通常用于控制雾的稀薄程度)。
*/
fogByDistance: new Cesium.Cartesian4(10, 0.0, 200, 1.0),
fogColor: Cesium.Color.BLACK,//雾的颜色为黑色
},
}),
);

try {
const tileset = await Cesium.Cesium3DTileset.fromIonAssetId(40866);
viewer.scene.primitives.add(tileset);
} catch (error) {
console.log(`瓦片数据加载出错: ${error}`);
}