原文链接及内容

效果如下视频所示:

示例代码如下:

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
<style>
@import url(../templates/bucket.css);

.cesium-performanceDisplay-defaultContainer {
top: 10px;
}
</style>
<div id="cesiumContainer" class="fullSize"></div>
<div id="loadingOverlay">
<h1>Loading...</h1>
</div>
<div id="toolbar">
<table>
<tbody>
<tr>
<td>云的缩放比例和最大尺寸设置</td>
<td>
<input type="checkbox" data-bind="checked: scaleWithMaximumSize">
</td>
</tr>
<tr>
<td>缩放-X方向</td>
<td>
<input type="range" min="5.0" max="50.0" step="1.0"
data-bind="value: scaleX, valueUpdate: 'input', enable: !scaleWithMaximumSize">
<input type="text" size="1" data-bind="value: scaleX, enable: !scaleWithMaximumSize">
</td>
</tr>
<tr>
<td>缩放-Y方向</td>
<td>
<input type="range" min="5.0" max="50.0" step="1.0"
data-bind="value: scaleY, valueUpdate: 'input', enable: !scaleWithMaximumSize">
<input type="text" size="1" data-bind="value: scaleY, enable: !scaleWithMaximumSize">
</td>
</tr>
<tr>
<td>最大尺寸-X方向</td>
<td>
<input type="range" min="5.0" max="50.0" step="1.0" data-bind="value: maximumSizeX, valueUpdate: 'input'">
<input type="text" size="1" data-bind="value: maximumSizeX">
</td>
</tr>
<tr>
<td>最大尺寸-Y方向</td>
<td>
<input type="range" min="5.0" max="50.0" step="1.0" data-bind="value: maximumSizeY, valueUpdate: 'input'">
<input type="text" size="1" data-bind="value: maximumSizeY">
</td>
</tr>
<tr>
<td>最大尺寸-Z方向</td>
<td>
<input type="range" min="5.0" max="50.0" step="1.0" data-bind="value: maximumSizeZ, valueUpdate: 'input'">
<input type="text" size="1" data-bind="value: maximumSizeZ">
</td>
</tr>
<tr>
<td>启用切面(slice)渲染</td>
<td>
<input type="checkbox" data-bind="checked: renderSlice">
</td>
</tr>
<tr>
<td>slice属性</td>
<td>
<input type="range" min="0.0" max="1.0" step="0.01"
data-bind="value: slice, valueUpdate: 'input', enable: renderSlice">
<input type="text" size="1" data-bind="value: slice, enable: renderSlice">
</td>
</tr>
<tr>
<td>颜色</td>
<td><select data-bind="options: colors, value: color"></select></td>
</tr>
<tr>
<td>亮度</td>
<td>
<input type="range" min="0.0" max="1.0" step="0.01" data-bind="value: brightness, valueUpdate: 'input'">
<input type="text" size="1" data-bind="value: brightness">
</td>
</tr>
</tbody>
</table>
</div>
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
const viewer = new Cesium.Viewer("cesiumContainer", {
geocoder: false,
sceneModePicker: false,
homeButton: false,
navigationHelpButton: false,
baseLayerPicker: false,
navigationInstructionsInitiallyVisible: false,
animation: false,
timeline: false,
fullscreenButton: false,
selectionIndicator: false,
skyBox: false,
shouldAnimate: true,
});

viewer.cesiumWidget.creditContainer.style.display = "none";
viewer.scene.debugShowFramesPerSecond = true;

const scene = viewer.scene;
const position = Cesium.Cartesian3.fromDegrees(-123.0744619, 44.0503706, 50);

function getColor(colorName) {
return Cesium.Color[colorName.toUpperCase()];
}
/**
* 这些噪声参数已设为默认值,但可进行调整以生成不同的云效果。
* 不过,由于噪声是预先计算的,因此无法动态更改。
*/
const clouds = scene.primitives.add(
new Cesium.CloudCollection({
noiseDetail: 16.0,
noiseOffset: Cesium.Cartesian3.ZERO,
})
);

const cloudParameters = {
scaleWithMaximumSize: true,
scaleX: 25,//积云横向缩放比例;
scaleY: 12,//积云纵向缩放比例;
//maximumSize: 更改云的最大尺寸,分为立体的三个方向
maximumSizeX: 25,
maximumSizeY: 12,
maximumSizeZ: 15,
renderSlice: true, // 如果为 false,则渲染椭球体的整个表面
slice: 0.36,
brightness: 1.0,
color: "White",//云的颜色,默认值为Color.WHITE
colors: ["White", "Red", "Green", "Blue", "Yellow", "Gray"],
};

const cloud = clouds.add({
position: position,
scale: new Cesium.Cartesian2(cloudParameters.scaleX, cloudParameters.scaleY),
maximumSize: new Cesium.Cartesian3(
cloudParameters.maximumSizeX,
cloudParameters.maximumSizeY,
cloudParameters.maximumSizeZ
),
color: getColor(cloudParameters.color),
slice: cloudParameters.renderSlice ? cloudParameters.slice : -1.0,
brightness: cloudParameters.brightness,
});

Cesium.knockout.track(cloudParameters);
const toolbar = document.getElementById("toolbar");
Cesium.knockout.applyBindings(cloudParameters, toolbar);

Cesium.knockout
.getObservable(cloudParameters, "scaleWithMaximumSize")
.subscribe(function (newValue) {
if (Boolean(newValue)) {
cloudParameters.scaleX = cloudParameters.maximumSizeX;
cloudParameters.scaleY = cloudParameters.maximumSizeY;
}
});

Cesium.knockout
.getObservable(cloudParameters, "scaleX")
.subscribe(function (newValue) {
const value = Number(newValue);
cloud.scale = new Cesium.Cartesian2(value, cloud.scale.y);
});

Cesium.knockout
.getObservable(cloudParameters, "scaleY")
.subscribe(function (newValue) {
const value = Number(newValue);
cloud.scale = new Cesium.Cartesian2(cloud.scale.x, value);
});

Cesium.knockout
.getObservable(cloudParameters, "maximumSizeX")
.subscribe(function (newValue) {
const value = Number(newValue);
cloud.maximumSize = new Cesium.Cartesian3(
value,
cloud.maximumSize.y,
cloud.maximumSize.z
);
if (cloudParameters.scaleWithMaximumSize) {
cloud.scale = new Cesium.Cartesian2(value, cloud.scale.y);
}
});

Cesium.knockout
.getObservable(cloudParameters, "maximumSizeY")
.subscribe(function (newValue) {
const value = Number(newValue);
cloud.maximumSize = new Cesium.Cartesian3(
cloud.maximumSize.x,
value,
cloud.maximumSize.z
);
if (cloudParameters.scaleWithMaximumSize) {
cloud.scale = new Cesium.Cartesian2(cloud.scale.x, value);
}
});

Cesium.knockout
.getObservable(cloudParameters, "maximumSizeZ")
.subscribe(function (newValue) {
const value = Number(newValue);
cloud.maximumSize = new Cesium.Cartesian3(
cloud.maximumSize.x,
cloud.maximumSize.y,
value
);
});

Cesium.knockout
.getObservable(cloudParameters, "renderSlice")
.subscribe(function (newValue) {
if (Boolean(newValue)) {
cloud.slice = Number(cloudParameters.slice);
} else {
cloud.slice = -1.0;
}
});

Cesium.knockout
.getObservable(cloudParameters, "slice")
.subscribe(function (newValue) {
cloud.slice = Number(newValue);
});

Cesium.knockout
.getObservable(cloudParameters, "color")
.subscribe(function (newValue) {
cloud.color = getColor(newValue);
});

Cesium.knockout
.getObservable(cloudParameters, "brightness")
.subscribe(function (newValue) {
cloud.brightness = Number(newValue);
});

viewer.camera.lookAt(position, new Cesium.Cartesian3(30, 30, -10));

CloudCollection-云的集合

关于CloudCollection,请参考官方文档介绍:https://cesium.com/learn/cesiumjs/ref-doc/CloudCollection.html?classFilter=Cloud。

  • noiseDetail: 控制用于渲染积云的预计算噪声纹理中捕获的细节量。为了使纹理可平铺,这必须是 2 的幂。为了获得最佳效果,请将其设置为介于 8.0 和 32.0(含)之间的 2 的幂。
    noiseDetail属性不同值情况下积云效果
  • noiseOffset: 对噪声纹理坐标应用平移以生成不同的数据。如果默认噪声无法生成美观的云层效果,可调整此参数。
    noiseOffset属性不同值情况下积云效果

CumulusCloud-积云

关于CumulusCloud,请参考官方文档介绍:https://cesium.com/learn/cesiumjs/ref-doc/CumulusCloud.html。

  • scale: 设置积云的比例,单位为米。scale将会影响云的大小,但不会影响云的实际外观。
    更改scale属性后的效果

  • maximumSize: 设置云的最大尺寸。这定义了云可以出现的最大椭球体体积。它并不保证特定的尺寸,而是指定了云出现的边界,更改它可能会影响云的形状。

    更改 maximumSize 的 z 值对云的外观影响最大,因为它会更改云的深度,从而更改云形成纹理的采样位置。
    更改maximumSize属性后的效果

  • slice: 默认值为-1,获取或设置在 Billboard 上渲染的云的“切片”,即为公告牌的外观选择的云的特定横截面。给定一个介于 0 和 1 之间的值,该切片将根据其在 z 方向上的最大大小指定在云中相交的深度。
    更改slice属性后的效果
    由于计算此切片的性质,低于 0.2 的值可能会导致横截面太小,并且椭球体的边缘将可见。同样,高于 0.7 的值 将导致云显得更小。超出范围 [0.1, 0.9] 的值 应该完全避免,因为它们不会产生理想的结果。
    slice属性超出0.1~0.9范围后的效果
    如果 slice 设置为负数,则云将不会渲染横截面。相反,它将呈现可见的椭球体外部。对于值较小的 ‘maximumSize.z’ 的云,这可以产生漂亮的结果,但对于较大的云,这可能会导致云意外地扭曲到椭球体体积。
    slice属性设置为负数后的效果

  • brightness: 默认值为1.0,用于获取或设置云的亮度。这可用于提供 cloud 更暗、更灰的外观。
    brightness属性设置效果