@lijuhong1981/cesium.utils 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/README.md +62 -2
  2. package/package.json +33 -4
  3. package/src/additions/Geographic.js +603 -0
  4. package/src/additions/GeographicTransform.js +291 -0
  5. package/src/additions/GeometryInstanceAttributes.js +164 -0
  6. package/src/additions/ModelMatrixTransforms.js +822 -0
  7. package/src/additions/PropertyChangedListener.js +72 -0
  8. package/src/additions/PropertyType.js +30 -0
  9. package/src/additions/StTransforms.js +266 -0
  10. package/src/additions/TranslationRotationScaleTransform.js +809 -0
  11. package/src/additions/index.js +8 -0
  12. package/src/index.js +4 -0
  13. package/src/parses/index.js +46 -0
  14. package/src/parses/parseAltitude.js +32 -0
  15. package/src/parses/parseArcType.js +26 -0
  16. package/src/parses/parseAttitudeToHeadingPitchRoll.js +26 -0
  17. package/src/parses/parseAttitudeToMatrix3.js +17 -0
  18. package/src/parses/parseAttitudeToQuaternion.js +21 -0
  19. package/src/parses/parseCartographicToCartesian.js +21 -0
  20. package/src/parses/parseCartographicsToPositions.js +20 -0
  21. package/src/parses/parseClassificationType.js +24 -0
  22. package/src/parses/parseClockRange.js +26 -0
  23. package/src/parses/parseColorBlendMode.js +26 -0
  24. package/src/parses/parseCornerType.js +24 -0
  25. package/src/parses/parseCullFace.js +28 -0
  26. package/src/parses/parseEulerToHeadingPitchRoll.js +21 -0
  27. package/src/parses/parseEulerToQuaternion.js +18 -0
  28. package/src/parses/parseGeographicToCartesian.js +21 -0
  29. package/src/parses/parseGeographicsToPositions.js +20 -0
  30. package/src/parses/parseHeading.js +28 -0
  31. package/src/parses/parseHeightReference.js +24 -0
  32. package/src/parses/parseHorizontalOrigin.js +26 -0
  33. package/src/parses/parseLabelStyle.js +26 -0
  34. package/src/parses/parseLatitude.js +28 -0
  35. package/src/parses/parseLongitude.js +28 -0
  36. package/src/parses/parsePitch.js +26 -0
  37. package/src/parses/parseRoll.js +26 -0
  38. package/src/parses/parseRotationToHeadingPitchRoll.js +40 -0
  39. package/src/parses/parseRotationToMatrix3.js +25 -0
  40. package/src/parses/parseRotationToQuaternion.js +27 -0
  41. package/src/parses/parseShadowMode.js +26 -0
  42. package/src/parses/parseToBoundingRectangle.js +33 -0
  43. package/src/parses/parseToCartesian2.js +35 -0
  44. package/src/parses/parseToCartesian3.js +37 -0
  45. package/src/parses/parseToCartesian3Array.js +21 -0
  46. package/src/parses/parseToCartesian4.js +39 -0
  47. package/src/parses/parseToCartographic.js +31 -0
  48. package/src/parses/parseToColor.js +33 -0
  49. package/src/parses/parseToDistanceDisplayCondition.js +41 -0
  50. package/src/parses/parseToGeographic.js +31 -0
  51. package/src/parses/parseToHeadingPitchRange.js +45 -0
  52. package/src/parses/parseToJulianDate.js +23 -0
  53. package/src/parses/parseToNearFarScalar.js +33 -0
  54. package/src/parses/parseToPlane.js +37 -0
  55. package/src/parses/parseToPolygonHierarchy.js +48 -0
  56. package/src/parses/parseToRange.js +26 -0
  57. package/src/parses/parseToRectangle.js +32 -0
  58. package/src/parses/parseToTimeInterval.js +45 -0
  59. package/src/parses/parseVerticalOrigin.js +28 -0
  60. package/src/revisions/BoundingSphere.revise.js +107 -0
  61. package/src/revisions/Camera.revise.js +366 -0
  62. package/src/revisions/Cartesian.revise.js +313 -0
  63. package/src/revisions/Cartographic.revise.js +443 -0
  64. package/src/revisions/Check.revise.js +164 -0
  65. package/src/revisions/Color.revise.js +271 -0
  66. package/src/revisions/DistanceDisplayCondition.revise.js +37 -0
  67. package/src/revisions/Ellipsoid.revise.js +64 -0
  68. package/src/revisions/Geometry.revise.js +79 -0
  69. package/src/revisions/Globe.revise.js +92 -0
  70. package/src/revisions/HeadingPitchRoll.revise.js +328 -0
  71. package/src/revisions/JulianDate.revise.js +28 -0
  72. package/src/revisions/Material.revise.js +308 -0
  73. package/src/revisions/Math.revise.js +98 -0
  74. package/src/revisions/Matrix.revise.js +578 -0
  75. package/src/revisions/POI.revise.js +178 -0
  76. package/src/revisions/Plane.revise.js +43 -0
  77. package/src/revisions/PolylinePipeline.revise.js +54 -0
  78. package/src/revisions/PostProcessStageLibrary.revise.js +1143 -0
  79. package/src/revisions/Primitive.revise.js +83 -0
  80. package/src/revisions/Property.revise.js +37 -0
  81. package/src/revisions/Quaternion.revise.js +66 -0
  82. package/src/revisions/Rectangle.revise.js +570 -0
  83. package/src/revisions/SceneTransforms.revise.js +82 -0
  84. package/src/revisions/Spherical.revise.js +35 -0
  85. package/src/revisions/index.js +25 -0
  86. package/src/utils/Scratch.js +165 -0
  87. package/src/utils/computeCirclePositions.js +48 -0
  88. package/src/utils/computeCircleRadius.js +19 -0
  89. package/src/utils/computeModelMatrix.js +109 -0
  90. package/src/utils/computeStTransform.js +57 -0
  91. package/src/utils/createGeometry.js +114 -0
  92. package/src/utils/createPointCloudGeometry.js +79 -0
  93. package/src/utils/getGeometryInstanceAttributes.js +43 -0
  94. package/src/utils/getPositionFromTarget.js +29 -0
  95. package/src/utils/getRenderState.js +35 -0
  96. package/src/utils/index.js +13 -0
  97. package/src/utils/isColorMaterial.js +13 -0
  98. package/src/utils/isTranslucent.js +13 -0
  99. package/src/utils/resolveModelMatrixByFixedFrame.js +30 -0
@@ -0,0 +1,1143 @@
1
+ import setOptions from '@lijuhong1981/jslib/src/setParameters.js';
2
+ import parseNumber from "@lijuhong1981/jsmath/src/parseNumber.js";
3
+ import { Cartesian3, Cartesian4, Math as CesiumMath, Check, Color, createGuid, defined, DeveloperError, Matrix3, Matrix4, PostProcessStage, PostProcessStageComposite, PostProcessStageLibrary, Quaternion } from "cesium";
4
+ import Geographic from '../additions/Geographic.js';
5
+ import parseGeographicToCartesian from '../parses/parseGeographicToCartesian.js';
6
+ import parseToCartesian3 from '../parses/parseToCartesian3.js';
7
+ import parseToColor from '../parses/parseToColor.js';
8
+
9
+ /**
10
+ * 扩展 Cesium 的 PostProcessStage 类,补充批量设置选项的方法。
11
+ * @class PostProcessStage
12
+ * @see {@link https://cesium.com/learn/cesiumjs/ref-doc/PostProcessStage.html}
13
+ */
14
+ /**
15
+ * 扩展 Cesium 的 PostProcessStageLibrary 类,补充圆形扫描、迷雾、高亮、天际线等后处理阶段创建方法。
16
+ * @class PostProcessStageLibrary
17
+ * @see {@link https://cesium.com/learn/cesiumjs/ref-doc/PostProcessStageLibrary.html}
18
+ */
19
+
20
+ /**
21
+ * 批量设置当前后处理阶段的选项与属性。
22
+ * @param {object} options 选项对象,其属性将被设置到当前 stage 上。
23
+ * @memberof PostProcessStage
24
+ */
25
+ PostProcessStage.prototype.setOptions = function (options) {
26
+ setOptions(this, options);
27
+ };
28
+
29
+ //解析和检测圆环设置
30
+ function parseAndCheckCircle(circle, defaultColor, defaultPower) {
31
+ circle.color = parseToColor(circle.color) ?? defaultColor;
32
+ Check.typeOf.number.greaterThan('radius', circle.radius, 0);
33
+ circle.power = circle.power ?? defaultPower;
34
+ Check.typeOf.number.greaterThanOrEquals('power', circle.power, 0);
35
+ // console.log('circle:', circle);
36
+ }
37
+
38
+ //解析和检测多重圆环设置
39
+ function parseAndCheckCircles(circles, defaultColor, defaultPower) {
40
+ for (let i = circles.length - 1; i >= 0; i--) {
41
+ parseAndCheckCircle(circles[i], defaultColor, defaultPower);
42
+ }
43
+ }
44
+
45
+ //多重圆环排序,按半径大小升序排列
46
+ function sortCircles(circles) {
47
+ let temp;
48
+ for (let i = 1; i < circles.length; i++) {
49
+ for (let j = i; j > 0; j--) {
50
+ if (circles[j].radius < circles[j - 1].radius) {
51
+ temp = circles[j];
52
+ circles[j] = circles[j - 1];
53
+ circles[j - 1] = temp;
54
+ }
55
+ }
56
+ }
57
+ // console.log('sortCircles:', circles);
58
+ }
59
+
60
+ //将多重圆环设置项分解至数组
61
+ function decomposeCircles(circles, outColors, outRadii, outPowers) {
62
+ for (let i = 0; i < circles.length; i++) {
63
+ outColors[i] = circles[i].color;
64
+ outRadii[i] = circles[i].radius;
65
+ outPowers[i] = circles[i].power;
66
+ }
67
+ // console.log('outColors:', outColors, 'outRadii:', outRadii);
68
+ }
69
+
70
+ /**
71
+ * 创建圆形扩散扫描后处理阶段。
72
+ * @param {object} options 配置项。
73
+ * @param {object} [options.map] Viewer 或 Scene 对象(与 scene 二选一),必需项之一。
74
+ * @param {object} [options.scene] Viewer 或 Scene 对象。
75
+ * @param {Geographic|Cartesian3|Cartographic|Array} [options.geographic] 圆心地理坐标。
76
+ * @param {Cartesian3} [options.position] 圆心位置。
77
+ * @param {Cartesian3} [options.center] 圆心位置(与 position 等效)。
78
+ * @param {string} [options.name] 阶段名称。
79
+ * @param {object} [options.properties] 自定义属性。
80
+ * @param {boolean} [options.circleDiffuse=true] 是否开启圆形扩散动画。
81
+ * @param {number} [options.radius=100] 扩散半径,单位米,须大于 0。
82
+ * @param {number} [options.duration=2.0] 扩散动画持续时间,单位秒。
83
+ * @param {Color|string} [options.color='#ff0000'] 扩散颜色。
84
+ * @param {number} [options.opacity=1] 透明度,取值 0 到 1。
85
+ * @param {boolean} [options.gradientColor=false] 是否启用渐变色。
86
+ * @param {Color|string} [options.startColor] 渐变起始颜色。
87
+ * @param {Color|string} [options.endColor] 渐变结束颜色。
88
+ * @param {number} [options.power=3.0] 扩散指数,值越小扩散环越厚。
89
+ * @param {boolean} [options.multiple=false] 是否开启多重圆环。
90
+ * @param {Array} [options.multiCircles=[]] 多重圆环设置数组。
91
+ * @param {boolean} [options.radarScan=false] 是否开启雷达扫描动画。
92
+ * @param {Color|string} [options.scanColor] 雷达扫描线颜色。
93
+ * @param {number} [options.scanPower=3.0] 雷达扫描线扩散指数。
94
+ * @param {number} [options.scanDuration=2.0] 雷达扫描动画持续时间,单位秒。
95
+ * @returns {PostProcessStage} 生成的圆形扩散扫描后处理阶段。
96
+ * @memberof PostProcessStageLibrary
97
+ * @static
98
+ */
99
+ PostProcessStageLibrary.createCircleScanStage = function (options) {
100
+ Check.defined('options', options);
101
+
102
+ //Viewer或Scene对象,必需项
103
+ const scene = options.map ?? options.scene;
104
+ Check.defined('scene', scene);
105
+
106
+ const name = options.name ?? 'CircleScan_' + createGuid();
107
+ const properties = options.properties;
108
+
109
+ //获取圆心点位置,Cartesian3对象
110
+ let center;
111
+ if (defined(options.geographic))
112
+ center = parseGeographicToCartesian(options.geographic, undefined, scene.ellipsoid);
113
+ else if (defined(options.position) || defined(options.center))
114
+ center = parseToCartesian3(options.position || options.center);
115
+ else
116
+ throw new DeveloperError('geographic or postition or center undefined.');
117
+
118
+ //圆心位置,Cartesian4对象
119
+ const cartesian4Center = new Cartesian4();
120
+ //高度+500后的圆心位置,Cartesian4对象
121
+ const cartesian4CenterByHigher = new Cartesian4();
122
+ //经度+0.001后的圆心位置,Cartesian4对象
123
+ const cartesian4CenterByRight = new Cartesian4();
124
+
125
+ //更新圆心相关参数
126
+ function updateCenterCoordinates() {
127
+ cartesian4Center.x = center.x;
128
+ cartesian4Center.y = center.y;
129
+ cartesian4Center.z = center.z;
130
+ cartesian4Center.w = 1;
131
+
132
+ //获得当前圆心位置的地理坐标
133
+ const geographic = center.toGeographic();
134
+ //高度+500,用于计算平面法线
135
+ const geographicByHigher = Geographic.fromDegrees(geographic.longitude, geographic.latitude, geographic.height + 500);
136
+ const centerByHigher = geographicByHigher.toCartesian();
137
+ cartesian4CenterByHigher.x = centerByHigher.x;
138
+ cartesian4CenterByHigher.y = centerByHigher.y;
139
+ cartesian4CenterByHigher.z = centerByHigher.z;
140
+ cartesian4CenterByHigher.w = 1;
141
+ //经度+0.001,用于计算平面法线
142
+ const geographicByRight = Geographic.fromDegrees(geographic.longitude + 0.001, geographic.latitude, geographic.height);
143
+ const centerByRight = geographicByRight.toCartesian();
144
+ cartesian4CenterByRight.x = centerByRight.x;
145
+ cartesian4CenterByRight.y = centerByRight.y;
146
+ cartesian4CenterByRight.z = centerByRight.z;
147
+ cartesian4CenterByRight.w = 1;
148
+ }
149
+
150
+ updateCenterCoordinates();
151
+
152
+ const scratchViewMatrix = new Matrix4();
153
+ const scratchCartesian4Center = new Cartesian4();
154
+ const scratchCartesian4CenterByHigher = new Cartesian4();
155
+ const scratchCartesian4CenterByRight = new Cartesian4();
156
+ const scratchCartesian3Normal = new Cartesian3();
157
+ const scratchCartesian3Direction = new Cartesian3();
158
+ const scratchCartesian3RotateDirection = new Cartesian3();
159
+ const scratchQuaternion = new Quaternion();
160
+ const scratchMatrix3 = new Matrix3();
161
+
162
+ //转换至相机视图位置
163
+ function updateCenterCoordinatesToEye() {
164
+ if (!Matrix4.equals(scene.camera.viewMatrix, scratchViewMatrix)) {
165
+ Matrix4.clone(scene.camera.viewMatrix, scratchViewMatrix);
166
+
167
+ Matrix4.multiplyByVector(scratchViewMatrix, cartesian4Center, scratchCartesian4Center);
168
+ Matrix4.multiplyByVector(scratchViewMatrix, cartesian4CenterByHigher, scratchCartesian4CenterByHigher);
169
+ Matrix4.multiplyByVector(scratchViewMatrix, cartesian4CenterByRight, scratchCartesian4CenterByRight);
170
+
171
+ Cartesian3.subtract(scratchCartesian4CenterByHigher, scratchCartesian4Center, scratchCartesian3Normal);
172
+ Cartesian3.normalize(scratchCartesian3Normal, scratchCartesian3Normal);
173
+
174
+ Cartesian3.subtract(scratchCartesian4CenterByRight, scratchCartesian4Center, scratchCartesian3Direction);
175
+ Cartesian3.normalize(scratchCartesian3Direction, scratchCartesian3Direction);
176
+ // console.log('center:', scratchCartesian4Center);
177
+ // console.log('ndc:', Matrix4.multiplyByVector(map.camera.frustum.projectionMatrix, scratchCartesian4Center, new Cartesian4()));
178
+ }
179
+ }
180
+
181
+ updateCenterCoordinatesToEye();
182
+
183
+ //是否开启圆形扩散动画
184
+ let circleDiffuse = options.circleDiffuse ?? true;
185
+ Check.typeOf.bool('circleDiffuse', circleDiffuse);
186
+ //半径,单位米,必须大于0
187
+ let radius = options.radius ?? 100;
188
+ Check.typeOf.number.greaterThan('radius', radius, 0);
189
+ //动画持续时间,单位秒
190
+ let duration = options.duration ?? 2.0;
191
+ Check.typeOf.number('duration', duration);
192
+ let milliDuration = duration * 1000;
193
+ //颜色设置
194
+ let color = parseToColor(options.color ?? '#ff0000');
195
+ //透明度设置
196
+ let opacity = options.opacity ?? 1;
197
+ Check.typeOf.number.greaterThanOrEquals('opacity', opacity, 0);
198
+ Check.typeOf.number.lessThanOrEquals('opacity', opacity, 1);
199
+ color = color.withAlpha(opacity, color);
200
+ //是否启用渐变色
201
+ let gradientColor = options.gradientColor ?? false;
202
+ Check.typeOf.bool('gradientColor', gradientColor);
203
+ //开始颜色
204
+ let startColor;
205
+ if (options.startColor)
206
+ startColor = parseToColor(options.startColor);
207
+ //结束颜色
208
+ let endColor;
209
+ if (options.endColor)
210
+ endColor = parseToColor(options.endColor);
211
+ //扩散指数,值越小扩散环越厚,最小值0
212
+ let power = options.power ?? 3.0;
213
+ Check.typeOf.number.greaterThanOrEquals('power', power, 0);
214
+ //是否开启多重圆环
215
+ let multiple = options.multiple ?? false;
216
+ Check.typeOf.bool('multiple', multiple);
217
+ //多重圆环设置数组
218
+ let multiCircles = options.multiCircles ?? new Array();
219
+ Check.typeOf.array('multiCircles', multiCircles);
220
+ let numberOfMultiple = 1,
221
+ maxRadius;
222
+ let colors = new Array();
223
+ let radii = new Array();
224
+ let powers = new Array();
225
+ handleCircles(multiCircles);
226
+ //是否开启雷达扫描动画
227
+ let radarScan = options.radarScan ?? false;
228
+ Check.typeOf.bool('radarScan', radarScan);
229
+ //雷达扫描线颜色
230
+ let scanColor;
231
+ if (options.scanColor)
232
+ scanColor = parseToColor(options.scanColor);
233
+ //雷达扫描线扩散指数,值越小扩散环越厚,最小值0
234
+ let scanPower = options.scanPower ?? 3.0;
235
+ Check.typeOf.number.greaterThanOrEquals('scanPower', scanPower, 0);
236
+ //雷达扫描动画持续时间,单位秒
237
+ let scanDuration = options.scanDuration ?? 2.0;
238
+ Check.typeOf.number.greaterThan('scanDuration', scanDuration, 0);
239
+ let milliScanDuration = scanDuration * 1000;
240
+
241
+ //记录当前时间
242
+ const startTime = (new Date()).getTime();
243
+
244
+ //分解多重圆环
245
+ function resolveCircles(circles) {
246
+ colors = new Array();
247
+ radii = new Array();
248
+ powers = new Array();
249
+ decomposeCircles(circles, colors, radii, powers);
250
+
251
+ //获取最大半径
252
+ maxRadius = radii[radii.length - 1];
253
+ //获取多重圆环数量
254
+ numberOfMultiple = circles.length;
255
+ }
256
+
257
+ //处理多重圆环
258
+ function handleCircles(circles) {
259
+ if (circles.length > 0) {
260
+ parseAndCheckCircles(circles, color, power);
261
+ sortCircles(circles);
262
+ resolveCircles(circles);
263
+ } else {
264
+ multiple = false;
265
+ }
266
+ }
267
+
268
+ const fragmentShader =
269
+ "uniform sampler2D colorTexture;\n" +
270
+ "uniform sampler2D depthTexture;\n" +
271
+ "in vec2 v_textureCoordinates;\n" +
272
+ "uniform vec4 u_centerEC;\n" +
273
+ "uniform vec3 u_planeNormalEC;\n" +
274
+ "uniform vec3 u_scanLineDirectionEC;\n" +
275
+ "uniform bool u_circleDiffuse;\n" +
276
+ "uniform float u_radius;\n" +
277
+ "uniform float u_maxRadius;\n" +
278
+ "uniform vec4 u_diffuseColor;\n" +
279
+ "uniform bool u_gradientColor;\n" +
280
+ "uniform vec4 u_startColor;\n" +
281
+ "uniform vec4 u_endColor;\n" +
282
+ "uniform float u_power;\n" +
283
+ "uniform bool u_multiple;\n" +
284
+ "uniform vec4 u_diffuseColors[" + numberOfMultiple + "];\n" +
285
+ "uniform float u_radii[" + numberOfMultiple + "];\n" +
286
+ "uniform float u_powers[" + numberOfMultiple + "];\n" +
287
+ "uniform bool u_radarScan;\n" +
288
+ "uniform vec4 u_scanColor;\n" +
289
+ "uniform float u_scanPower;\n" +
290
+
291
+ "float getDepth(in vec4 depth)\n" +
292
+ "{\n" +
293
+ " float z_window = czm_unpackDepth(depth);\n" +
294
+ " z_window = czm_reverseLogDepth(z_window);\n" +
295
+ " float near = czm_depthRange.near;\n" +
296
+ " float far = czm_depthRange.far;\n" +
297
+ " return (2.0 * z_window - near - far) / (far - near);\n" +
298
+ "}\n" +
299
+
300
+ "vec4 textureCoordinatesToEye(in vec2 uv, in float depth)\n" +
301
+ "{\n" +
302
+ " vec2 xy = vec2((uv.x * 2.0 - 1.0), (uv.y * 2.0 - 1.0));\n" +
303
+ " vec4 posInCamera = czm_inverseProjection * vec4(xy, depth, 1.0);\n" +
304
+ " posInCamera = posInCamera / posInCamera.w;\n" +
305
+ " return posInCamera;\n" +
306
+ "}\n" +
307
+
308
+ "vec3 pointProjectOnPlane(in vec3 planeNormal, in vec3 planeOrigin, in vec3 point)\n" +
309
+ "{\n" +
310
+ " vec3 v01 = point - planeOrigin;\n" +
311
+ " float d = dot(planeNormal, v01) ;\n" +
312
+ " return (point - planeNormal * d);\n" +
313
+ "}\n" +
314
+
315
+ "bool isPointOnLineRight(in vec3 lineOrigin, in vec3 lineDirection, in vec3 lineNormal, in vec3 testPoint)\n" +
316
+ "{\n" +
317
+ " vec3 direction = testPoint - lineOrigin;\n" +
318
+ " normalize(direction);\n" +
319
+ " vec3 temp = cross(direction, lineDirection);\n" +
320
+ " float d = dot(temp, lineNormal);\n" +
321
+ " return d > 0.5;\n" +
322
+ "}\n" +
323
+
324
+ "void main()\n" +
325
+ "{\n" +
326
+ " out_FragColor = texture(colorTexture, v_textureCoordinates);\n" +
327
+ " float depth = getDepth(texture(depthTexture, v_textureCoordinates));\n" +
328
+ " vec4 eyePos = textureCoordinatesToEye(v_textureCoordinates, depth);\n" +
329
+ " vec3 projectOnPlane = pointProjectOnPlane(u_planeNormalEC.xyz, u_centerEC.xyz, eyePos.xyz);\n" +
330
+ " float dis = length(projectOnPlane.xyz - u_centerEC.xyz);\n" +
331
+ " if (u_circleDiffuse && dis <= u_radius)\n" +
332
+ " {\n" +
333
+ " if(u_multiple && " + numberOfMultiple + " > 0)\n" +
334
+ " {\n" +
335
+ " for(int i = 0; i < " + numberOfMultiple + "; i++)\n" +
336
+ " {\n" +
337
+ " float radius = u_radii[i];\n" +
338
+ " if(dis <= radius)\n" +
339
+ " {\n" +
340
+ " float f = 1.0 - abs(radius - dis) / radius;\n" +
341
+ " f = pow(f, u_powers[i]);\n" +
342
+ " vec4 diffuseColor = u_diffuseColors[i];\n" +
343
+ " out_FragColor = mix(out_FragColor, diffuseColor, f);\n" +
344
+ " break;\n" +
345
+ " }\n" +
346
+ " }\n" +
347
+ " }\n" +
348
+ " else\n" +
349
+ " {\n" +
350
+ " float f = 1.0 - abs(u_radius - dis) / u_radius;\n" +
351
+ " f = pow(f, u_power);\n" +
352
+ " if (u_gradientColor)\n" +
353
+ " {\n" +
354
+ " float p = dis / u_maxRadius;\n" +
355
+ " vec4 diffuseColor = mix(u_startColor, u_endColor, p);\n" +
356
+ " out_FragColor = mix(out_FragColor, diffuseColor, f);\n" +
357
+ " }\n" +
358
+ " else\n" +
359
+ " {\n" +
360
+ " out_FragColor = mix(out_FragColor, u_diffuseColor, f);\n" +
361
+ " }\n" +
362
+ " }\n" +
363
+ " }\n" +
364
+ " if (u_radarScan && dis <= u_maxRadius)\n" +
365
+ " {\n" +
366
+ " float diameter = u_maxRadius * 2.0;\n" +
367
+ " if(isPointOnLineRight(u_centerEC.xyz, u_scanLineDirectionEC.xyz, u_planeNormalEC.xyz, projectOnPlane.xyz))\n" +
368
+ " {\n" +
369
+ " vec3 lineEndPoint = vec3(u_centerEC.xyz) + u_scanLineDirectionEC * u_maxRadius;\n" +
370
+ " float dis1 = length(projectOnPlane.xyz - lineEndPoint);\n" +
371
+ " float f = abs(diameter - dis1) / diameter;\n" +
372
+ " f = pow(f, u_scanPower);\n" +
373
+ " out_FragColor = mix(out_FragColor, u_scanColor, f);\n" +
374
+ " }\n" +
375
+ " }\n" +
376
+ "}\n";
377
+
378
+ const stage = new PostProcessStage({
379
+ name: name,
380
+ fragmentShader: fragmentShader,
381
+ uniforms: {
382
+ u_centerEC: function () {
383
+ updateCenterCoordinatesToEye();
384
+ return scratchCartesian4Center;
385
+ },
386
+ u_planeNormalEC: function () {
387
+ return scratchCartesian3Normal;
388
+ },
389
+ u_scanLineDirectionEC: function () {
390
+ const normal = scratchCartesian3Normal;
391
+ const direction = scratchCartesian3Direction.clone(scratchCartesian3RotateDirection);
392
+
393
+ const percent = (((new Date()).getTime() - startTime) % milliScanDuration) / milliScanDuration;
394
+ Quaternion.fromAxisAngle(normal, percent * CesiumMath.TWO_PI, scratchQuaternion);
395
+ Matrix3.fromQuaternion(scratchQuaternion, scratchMatrix3);
396
+ Matrix3.multiplyByVector(scratchMatrix3, direction, direction);
397
+ Cartesian3.normalize(direction, direction);
398
+ return direction;
399
+ },
400
+ u_circleDiffuse: function () {
401
+ return circleDiffuse;
402
+ },
403
+ u_radius: function () {
404
+ if (milliDuration <= 0) {
405
+ if (multiple)
406
+ return maxRadius;
407
+ else
408
+ return radius;
409
+ } else {
410
+ const percent = (((new Date()).getTime() - startTime) % milliDuration) / milliDuration;
411
+ if (multiple)
412
+ return maxRadius * percent;
413
+ else
414
+ return radius * percent;
415
+ }
416
+ },
417
+ u_maxRadius: function () {
418
+ if (multiple)
419
+ return maxRadius;
420
+ else
421
+ return radius;
422
+ },
423
+ u_diffuseColor: color,
424
+ u_gradientColor: function () {
425
+ if (gradientColor) {
426
+ //开启渐变色时判断下startColor与endColor是否存在
427
+ return defined(startColor) || defined(endColor);
428
+ }
429
+ return gradientColor;
430
+ },
431
+ u_startColor: function () {
432
+ return startColor || color;
433
+ },
434
+ u_endColor: function () {
435
+ return endColor || color;
436
+ },
437
+ u_power: function () {
438
+ return power;
439
+ },
440
+ u_multiple: function () {
441
+ return multiple;
442
+ },
443
+ u_diffuseColors: function () {
444
+ return colors;
445
+ },
446
+ u_radii: function () {
447
+ return radii;
448
+ },
449
+ u_powers: function () {
450
+ return powers;
451
+ },
452
+ u_radarScan: function () {
453
+ return radarScan;
454
+ },
455
+ u_scanColor: function () {
456
+ return scanColor || color;
457
+ },
458
+ u_scanPower: function () {
459
+ return scanPower;
460
+ }
461
+ }
462
+ });
463
+
464
+ Object.defineProperties(stage, {
465
+ properties: {
466
+ get: function () {
467
+ return properties;
468
+ }
469
+ },
470
+ geographic: {
471
+ set: function (value) {
472
+ this.center = parseGeographicToCartesian(value, center);
473
+ },
474
+ get: function () {
475
+ return this.center.toGeographic();
476
+ }
477
+ },
478
+ position: {
479
+ set: function (value) {
480
+ this.center = parseToCartesian3(value);
481
+ },
482
+ get: function () {
483
+ return this.center;
484
+ }
485
+ },
486
+ center: {
487
+ set: function (value) {
488
+ value = parseToCartesian3(value);
489
+ if (!Cartesian3.equals(value, center)) {
490
+ center = value.clone(center);
491
+ updateCenterCoordinates();
492
+ }
493
+ },
494
+ get: function () {
495
+ return center;
496
+ }
497
+ },
498
+ circleDiffuse: {
499
+ set: function (value) {
500
+ Check.typeOf.bool('circleDiffuse', value);
501
+ circleDiffuse = value;
502
+ },
503
+ get: function () {
504
+ return circleDiffuse;
505
+ }
506
+ },
507
+ color: {
508
+ set: function (value) {
509
+ value = parseToColor(value);
510
+ if (!Color.equals(value, color)) {
511
+ color = value.clone(color);
512
+ color = color.withAlpha(opacity, color);
513
+ }
514
+ },
515
+ get: function () {
516
+ return color;
517
+ }
518
+ },
519
+ opacity: {
520
+ set: function (value) {
521
+ Check.typeOf.number.greaterThanOrEquals('opacity', value, 0);
522
+ Check.typeOf.number.lessThanOrEquals('opacity', value, 1);
523
+ if (opacity !== value) {
524
+ opacity = value;
525
+ color = color.withAlpha(opacity, color);
526
+ }
527
+ },
528
+ get: function () {
529
+ return opacity;
530
+ }
531
+ },
532
+ gradientColor: {
533
+ set: function (value) {
534
+ Check.typeOf.bool('gradientColor', value);
535
+ gradientColor = value;
536
+ }
537
+ },
538
+ startColor: {
539
+ set: function (value) {
540
+ if (!defined(value)) {
541
+ startColor = undefined;
542
+ return;
543
+ }
544
+ value = parseToColor(value);
545
+ if (!Color.equals(value, startColor)) {
546
+ startColor = value.clone(startColor);
547
+ }
548
+ },
549
+ get: function () {
550
+ return startColor;
551
+ }
552
+ },
553
+ endColor: {
554
+ set: function (value) {
555
+ if (!defined(value)) {
556
+ endColor = undefined;
557
+ return;
558
+ }
559
+ value = parseToColor(value);
560
+ if (!Color.equals(value, endColor)) {
561
+ endColor = value.clone(endColor);
562
+ }
563
+ },
564
+ get: function () {
565
+ return endColor;
566
+ }
567
+ },
568
+ radius: {
569
+ set: function (value) {
570
+ Check.typeOf.number.greaterThan('radius', value, 0);
571
+ if (radius !== value)
572
+ radius = value;
573
+ },
574
+ get: function () {
575
+ return radius;
576
+ }
577
+ },
578
+ duration: {
579
+ set: function (value) {
580
+ Check.typeOf.number('duration', value);
581
+ if (duration !== value) {
582
+ duration = value;
583
+ milliDuration = duration * 1000;
584
+ }
585
+ },
586
+ get: function () {
587
+ return duration;
588
+ }
589
+ },
590
+ power: {
591
+ set: function (value) {
592
+ Check.typeOf.number.greaterThanOrEquals('power', value, 0);
593
+ if (power !== value)
594
+ power = value;
595
+ },
596
+ get: function () {
597
+ return power;
598
+ }
599
+ },
600
+ multiple: {
601
+ set: function (value) {
602
+ Check.typeOf.bool('multiple', value);
603
+ multiple = value;
604
+ },
605
+ get: function () {
606
+ return multiple;
607
+ }
608
+ },
609
+ multiCircles: {
610
+ set: function (value) {
611
+ Check.typeOf.array('multiCircles', value);
612
+ multiCircles = value;
613
+ handleCircles(multiCircles);
614
+ },
615
+ get: function () {
616
+ return multiCircles;
617
+ }
618
+ },
619
+ radarScan: {
620
+ set: function (value) {
621
+ Check.typeOf.bool('radarScan', value);
622
+ radarScan = value;
623
+ },
624
+ get: function () {
625
+ return radarScan;
626
+ }
627
+ },
628
+ scanColor: {
629
+ set: function (value) {
630
+ if (!defined(value)) {
631
+ scanColor = undefined;
632
+ return;
633
+ }
634
+ value = parseToColor(value);
635
+ if (!Color.equals(value, scanColor)) {
636
+ endColor = value.clone(scanColor);
637
+ }
638
+ },
639
+ get: function () {
640
+ return scanColor || color;
641
+ }
642
+ },
643
+ scanDuration: {
644
+ set: function (value) {
645
+ Check.typeOf.number.greaterThan('scanDuration', value, 0);
646
+ if (scanDuration !== value) {
647
+ scanDuration = value;
648
+ milliScanDuration = scanDuration * 1000;
649
+ }
650
+ },
651
+ get: function () {
652
+ return scanDuration;
653
+ }
654
+ },
655
+ scanPower: {
656
+ set: function (value) {
657
+ Check.typeOf.number.greaterThanOrEquals('scanPower', value, 0);
658
+ if (scanPower !== value)
659
+ scanPower = value;
660
+ },
661
+ get: function () {
662
+ return scanPower;
663
+ }
664
+ }
665
+ });
666
+
667
+ /**
668
+ * 向圆形扫描阶段添加一个圆环。
669
+ * @param {object} circle 圆环设置,包含 color、radius、power 属性。
670
+ * @memberof PostProcessStage
671
+ */
672
+ stage.addCircle = function (circle) {
673
+ parseAndCheckCircle(circle, color);
674
+ multiCircles.push(circle);
675
+ sortCircles(multiCircles);
676
+ resolveCircles(multiCircles);
677
+ };
678
+
679
+ /**
680
+ * 移除圆形扫描阶段指定索引的圆环。
681
+ * @param {number} index 待移除圆环的索引。
682
+ * @memberof PostProcessStage
683
+ */
684
+ stage.removeCircleAt = function (index) {
685
+ Check.typeOf.integer.greaterThanOrEquals('index', index, 0);
686
+ Check.typeOf.integer.lessThan('index', index, multiCircles.length);
687
+ multiCircles.splice(index, 1);
688
+ if (multiCircles.length === 0)
689
+ multiple = false;
690
+ else
691
+ numberOfMultiple = multiCircles.length;
692
+ };
693
+
694
+ /**
695
+ * 移除圆形扫描阶段的全部圆环。
696
+ * @memberof PostProcessStage
697
+ */
698
+ stage.removeAllCircles = function () {
699
+ multiple = false;
700
+ multiCircles = new Array();
701
+ };
702
+
703
+ stage.setOptions(options);
704
+ return stage;
705
+ };
706
+
707
+ const NearFarScalarFogFragmentShaderSource =
708
+ "float getDistance(sampler2D depthTexture, vec2 texCoords) \n" +
709
+ "{ \n" +
710
+ " float depth = czm_unpackDepth(texture(depthTexture, texCoords)); \n" +
711
+ " if (depth == 0.0) { \n" +
712
+ " return czm_infinity; \n" +
713
+ " } \n" +
714
+ " vec4 eyeCoordinate = czm_windowToEyeCoordinates(gl_FragCoord.xy, depth); \n" +
715
+ " return -eyeCoordinate.z / eyeCoordinate.w; \n" +
716
+ "} \n" +
717
+
718
+ "float interpolateByDistance(vec4 nearFarScalar, float distance) \n" +
719
+ "{ \n" +
720
+ " float startDistance = nearFarScalar.x; \n" +
721
+ " float startValue = nearFarScalar.y; \n" +
722
+ " float endDistance = nearFarScalar.z; \n" +
723
+ " float endValue = nearFarScalar.w; \n" +
724
+ " float t = clamp((distance - startDistance) / (endDistance - startDistance), 0.0, 1.0); \n" +
725
+ " return mix(startValue, endValue, t); \n" +
726
+ "} \n" +
727
+
728
+ "vec4 alphaBlend(vec4 sourceColor, vec4 destinationColor) \n" +
729
+ "{ \n" +
730
+ " return sourceColor * vec4(sourceColor.aaa, 1.0) + destinationColor * (1.0 - sourceColor.a); \n" +
731
+ "} \n" +
732
+
733
+ "uniform sampler2D colorTexture; \n" +
734
+ "uniform sampler2D depthTexture; \n" +
735
+ "uniform bool u_fogEnable; \n" +
736
+ "uniform vec4 u_fogByDistance; \n" +
737
+ "uniform vec4 u_fogColor; \n" +
738
+ "in vec2 v_textureCoordinates; \n" +
739
+
740
+ "void main(void) \n" +
741
+ "{ \n" +
742
+ " if (u_fogEnable) { \n" +
743
+ " float distance = getDistance(depthTexture, v_textureCoordinates); \n" +
744
+ " vec4 sceneColor = texture(colorTexture, v_textureCoordinates); \n" +
745
+ " float blendAmount = interpolateByDistance(u_fogByDistance, distance); \n" +
746
+ " vec4 finalFogColor = vec4(u_fogColor.rgb, u_fogColor.a * blendAmount); \n" +
747
+ " out_FragColor = alphaBlend(finalFogColor, sceneColor); \n" +
748
+ " } else { \n" +
749
+ " out_FragColor = texture(colorTexture, v_textureCoordinates); \n" +
750
+ " } \n" +
751
+ "} \n";
752
+
753
+ /**
754
+ * 创建基于近远距离线性插值的迷雾后处理阶段。
755
+ * @param {object} [options={}] 配置项。
756
+ * @param {string} [options.name] 阶段名称。
757
+ * @param {object} [options.properties] 自定义属性。
758
+ * @param {boolean} [options.enable=true] 是否开启迷雾。
759
+ * @param {Color|string} [options.color='#fff'] 迷雾颜色。
760
+ * @param {number} [options.near=10] 近距。
761
+ * @param {number} [options.nearValue=0.0] 近距插值。
762
+ * @param {number} [options.far=500] 远距。
763
+ * @param {number} [options.farValue=1.0] 远距插值。
764
+ * @returns {PostProcessStage} 生成的迷雾后处理阶段。
765
+ * @memberof PostProcessStageLibrary
766
+ * @static
767
+ */
768
+ PostProcessStageLibrary.createNearFarScalarFogStage = function (options = {}) {
769
+ const name = options.name ?? 'NearFarScalarFog_' + createGuid();
770
+ const properties = options.properties;
771
+
772
+ //是否开启迷雾
773
+ let fogEnable = options.enable ?? true;
774
+ //颜色设置
775
+ let fogColor = parseToColor(options.color ?? '#fff');
776
+ //近距
777
+ let near = options.near ?? 10;
778
+ //近距插入值
779
+ let nearValue = options.nearValue ?? 0.0;
780
+ //远距
781
+ let far = options.far ?? 500;
782
+ //远距插入值
783
+ let farValue = options.farValue ?? 1.0;
784
+
785
+ const fogByDistance = new Cartesian4(near, nearValue, far, farValue);
786
+
787
+ const stage = new PostProcessStage({
788
+ name: name,
789
+ fragmentShader: NearFarScalarFogFragmentShaderSource,
790
+ uniforms: {
791
+ u_fogEnable: function () {
792
+ return fogEnable;
793
+ },
794
+ u_fogColor: fogColor,
795
+ u_fogByDistance: fogByDistance,
796
+ }
797
+ });
798
+
799
+ Object.defineProperties(stage, {
800
+ properties: {
801
+ get: function () {
802
+ return properties;
803
+ }
804
+ },
805
+ enable: {
806
+ set: function (value) {
807
+ Check.typeOf.bool('enable', value);
808
+ fogEnable = value;
809
+ },
810
+ get: function () {
811
+ return fogEnable;
812
+ }
813
+ },
814
+ color: {
815
+ set: function (value) {
816
+ value = parseToColor(value);
817
+ Color.clone(value, fogColor);
818
+ },
819
+ get: function () {
820
+ return fogColor;
821
+ }
822
+ },
823
+ near: {
824
+ set: function (value) {
825
+ value = parseNumber(value);
826
+ fogByDistance.x = value;
827
+ },
828
+ get: function () {
829
+ return fogByDistance.x;
830
+ }
831
+ },
832
+ nearValue: {
833
+ set: function (value) {
834
+ value = parseNumber(value);
835
+ fogByDistance.y = value;
836
+ },
837
+ get: function () {
838
+ return fogByDistance.y;
839
+ }
840
+ },
841
+ far: {
842
+ set: function (value) {
843
+ value = parseNumber(value);
844
+ fogByDistance.z = value;
845
+ },
846
+ get: function () {
847
+ return fogByDistance.z;
848
+ }
849
+ },
850
+ farValue: {
851
+ set: function (value) {
852
+ value = parseNumber(value);
853
+ fogByDistance.w = value;
854
+ },
855
+ get: function () {
856
+ return fogByDistance.w;
857
+ }
858
+ }
859
+ });
860
+
861
+ stage.setOptions(options);
862
+ return stage;
863
+ };
864
+
865
+ const Exp2FogFragmentShaderSource =
866
+ "uniform sampler2D colorTexture;\n" +
867
+ "uniform sampler2D depthTexture;\n" +
868
+ "in vec2 v_textureCoordinates;\n" +
869
+ "uniform bool u_fogEnable;\n" +
870
+ "uniform vec4 u_fogColor;\n" +
871
+ "uniform float u_fogDensity;\n" +
872
+
873
+ "float getDepth(in vec4 depth)\n" +
874
+ "{\n" +
875
+ " float z_window = czm_unpackDepth(depth);\n" +
876
+ " z_window = czm_reverseLogDepth(z_window);\n" +
877
+ " float near = czm_depthRange.near;\n" +
878
+ " float far = czm_depthRange.far;\n" +
879
+ " return (2.0 * z_window - near - far) / (far - near);\n" +
880
+ "}\n" +
881
+
882
+ "vec4 textureCoordinatesToEye(in vec2 uv, in float depth)\n" +
883
+ "{\n" +
884
+ " vec2 xy = vec2((uv.x * 2.0 - 1.0), (uv.y * 2.0 - 1.0));\n" +
885
+ " vec4 posInCamera = czm_inverseProjection * vec4(xy, depth, 1.0);\n" +
886
+ " posInCamera = posInCamera / posInCamera.w;\n" +
887
+ " return posInCamera;\n" +
888
+ "}\n" +
889
+
890
+ "void main()\n" +
891
+ "{\n" +
892
+ " out_FragColor = texture(colorTexture, v_textureCoordinates);\n" +
893
+ " if (u_fogEnable && u_fogDensity > 0.0)\n" +
894
+ " {\n" +
895
+ " float depth = getDepth(texture(depthTexture, v_textureCoordinates));\n" +
896
+ " vec4 eyePos = textureCoordinatesToEye(v_textureCoordinates, depth);\n" +
897
+ " float fogDepth = -eyePos.z;" +
898
+ " float fogFactor = 1.0 - exp(-u_fogDensity * u_fogDensity * fogDepth * fogDepth);\n" +
899
+ " fogFactor = clamp(fogFactor, 0.0, 1.0);\n" +
900
+ " out_FragColor.rgb = mix(out_FragColor.rgb, u_fogColor.rgb, fogFactor);\n" +
901
+ " }\n" +
902
+ "}";
903
+
904
+ /**
905
+ * 创建指数平方(Exp2)浓淡效果的迷雾后处理阶段。
906
+ * @param {object} [options={}] 配置项。
907
+ * @param {string} [options.name] 阶段名称。
908
+ * @param {object} [options.properties] 自定义属性。
909
+ * @param {boolean} [options.enable=true] 是否开启迷雾。
910
+ * @param {Color|string} [options.color='#fff'] 迷雾颜色。
911
+ * @param {number} [options.density=1] 迷雾密度。
912
+ * @returns {PostProcessStage} 生成的迷雾后处理阶段。
913
+ * @memberof PostProcessStageLibrary
914
+ * @static
915
+ */
916
+ PostProcessStageLibrary.createExp2FogStage = function (options = {}) {
917
+ const name = options.name ?? 'Exp2Fog_' + createGuid();
918
+ const properties = options.properties;
919
+
920
+ //是否开启迷雾
921
+ let fogEnable = options.enable ?? true;
922
+ //颜色设置
923
+ let fogColor = parseToColor(options.color ?? '#fff');
924
+ //密度设置
925
+ let fogDensity = options.density ?? 1;
926
+
927
+ const stage = new PostProcessStage({
928
+ name: name,
929
+ fragmentShader: Exp2FogFragmentShaderSource,
930
+ uniforms: {
931
+ u_fogEnable: function () {
932
+ return fogEnable;
933
+ },
934
+ u_fogColor: fogColor,
935
+ u_fogDensity: function () {
936
+ return fogDensity / 500;
937
+ },
938
+ }
939
+ });
940
+
941
+ Object.defineProperties(stage, {
942
+ properties: {
943
+ get: function () {
944
+ return properties;
945
+ }
946
+ },
947
+ enable: {
948
+ set: function (value) {
949
+ Check.typeOf.bool('enable', value);
950
+ fogEnable = value;
951
+ },
952
+ get: function () {
953
+ return fogEnable;
954
+ }
955
+ },
956
+ color: {
957
+ set: function (value) {
958
+ value = parseToColor(value);
959
+ Color.clone(value, fogColor);
960
+ },
961
+ get: function () {
962
+ return fogColor;
963
+ }
964
+ },
965
+ density: {
966
+ set: function (value) {
967
+ value = parseNumber(value);
968
+ fogDensity = value;
969
+ },
970
+ get: function () {
971
+ return fogDensity;
972
+ }
973
+ },
974
+ });
975
+
976
+ stage.setOptions(options);
977
+ return stage;
978
+ };
979
+
980
+ /**
981
+ * 迷雾类型枚举。
982
+ * @type {object}
983
+ * @constant
984
+ */
985
+ const FogType = Object.freeze({
986
+ NearFarScalar: 'NearFarScalar',
987
+ Exp2: 'Exp2',
988
+ });
989
+
990
+ /**
991
+ * 根据类型创建迷雾后处理阶段。
992
+ * @param {object} [options={}] 配置项。
993
+ * @param {string} [options.type=FogType.NearFarScalar] 迷雾类型,取值见 FogType。
994
+ * @returns {PostProcessStage} 生成的迷雾后处理阶段。
995
+ * @memberof PostProcessStageLibrary
996
+ * @static
997
+ */
998
+ PostProcessStageLibrary.createFogStage = function (options = {}) {
999
+ const type = (options.type ?? FogType.NearFarScalar).toLocaleString();
1000
+ switch (type) {
1001
+ case FogType.Exp2:
1002
+ return PostProcessStageLibrary.createExp2FogStage(options);
1003
+ default:
1004
+ return PostProcessStageLibrary.createNearFarScalarFogStage(options);
1005
+ }
1006
+ };
1007
+
1008
+ const HighlightFragmentShaderSource =
1009
+ "uniform sampler2D colorTexture;\n" +
1010
+ "in vec2 v_textureCoordinates;\n" +
1011
+ "uniform vec4 highlight;\n" +
1012
+ "void main() {\n" +
1013
+ " vec4 color = texture(colorTexture, v_textureCoordinates);\n" +
1014
+ " if (czm_selected()) {\n" +
1015
+ " vec3 highlighted = highlight.a * highlight.rgb + (1.0 - highlight.a) * color.rgb;\n" +
1016
+ " out_FragColor = vec4(highlighted, color.a);\n" +
1017
+ " } else { \n" +
1018
+ " out_FragColor = color;\n" +
1019
+ " }\n" +
1020
+ "}\n";
1021
+
1022
+ /**
1023
+ * 创建高亮后处理阶段。
1024
+ * @param {object} [options={}] 配置项。
1025
+ * @param {Color|string} [options.color] 高亮颜色。
1026
+ * @param {number} [options.intensity] 高亮强度,取值 0 到 1。
1027
+ * @returns {PostProcessStage} 生成的高亮后处理阶段。
1028
+ * @memberof PostProcessStageLibrary
1029
+ * @static
1030
+ */
1031
+ PostProcessStageLibrary.createHighlightStage = function (options = {}) {
1032
+ const guid = createGuid();
1033
+
1034
+ const highlight = new Color(1.0, 1.0, 1.0, 0.5);
1035
+
1036
+ const stage = new PostProcessStage({
1037
+ name: "czm_highlight_" + guid,
1038
+ fragmentShader: HighlightFragmentShaderSource,
1039
+ uniforms: {
1040
+ highlight: function () {
1041
+ return highlight;
1042
+ },
1043
+ },
1044
+ });
1045
+
1046
+ Object.defineProperties(stage, {
1047
+ color: {
1048
+ set: function (value) {
1049
+ value = parseToColor(value);
1050
+ Color.cloneRgb(value, highlight);
1051
+ },
1052
+ get: function () {
1053
+ return highlight;
1054
+ }
1055
+ },
1056
+ intensity: {
1057
+ set: function (value) {
1058
+ Check.typeOf.number.greaterThanOrEquals('intensity', 0);
1059
+ Check.typeOf.number.lessThanOrEquals('intensity', 1);
1060
+ highlight.alpha = value;
1061
+ },
1062
+ get: function () {
1063
+ return highlight.alpha;
1064
+ }
1065
+ }
1066
+ });
1067
+
1068
+ stage.setOptions(options);
1069
+ return stage;
1070
+ };
1071
+
1072
+ const SkylineFragmentShaderSource =
1073
+ "uniform sampler2D colorTexture;\n" +
1074
+ "uniform sampler2D depthTexture;\n" +
1075
+ "uniform sampler2D silhouetteTexture;\n" +
1076
+ "in vec2 v_textureCoordinates;\n" +
1077
+ "void main() {\n" +
1078
+ " float depth = czm_readDepth(depthTexture, v_textureCoordinates);" +
1079
+ " vec4 silhouetteColor = texture(silhouetteTexture, v_textureCoordinates);" +
1080
+ " vec4 color = texture(colorTexture, v_textureCoordinates);\n" +
1081
+ " if(depth >= 1.0 - 0.000001) {\n" +
1082
+ " out_FragColor = mix(color, silhouetteColor, silhouetteColor.a);\n" +
1083
+ " } else { \n" +
1084
+ " out_FragColor = color;\n" +
1085
+ " }\n" +
1086
+ "}\n";
1087
+
1088
+ /**
1089
+ * 创建天际线(轮廓线)检测的后处理阶段组合。
1090
+ * @param {object} [options={}] 配置项。
1091
+ * @param {boolean} [options.enabled=true] 是否启用。
1092
+ * @param {Color|string} [options.color=Color.RED] 轮廓线颜色。
1093
+ * @param {number} [options.lineWidth=1.0] 轮廓线宽度,须大于 0。
1094
+ * @returns {PostProcessStageComposite} 生成的天际线后处理阶段组合。
1095
+ * @memberof PostProcessStageLibrary
1096
+ * @static
1097
+ */
1098
+ PostProcessStageLibrary.createSkylineState = function (options = {}) {
1099
+ const edgeDetection = PostProcessStageLibrary.createEdgeDetectionStage();
1100
+ const skilneStage = new PostProcessStage({
1101
+ fragmentShader: SkylineFragmentShaderSource,
1102
+ uniforms: {
1103
+ silhouetteTexture: edgeDetection.name
1104
+ }
1105
+ });
1106
+
1107
+ const composite = new PostProcessStageComposite({
1108
+ //PostProcessStage要按顺序执行 的stage或组合的数组。
1109
+ stages: [edgeDetection, skilneStage],
1110
+ //是否执行每个后处理阶段,其中一个阶段的输入是前一个阶段的输出。否则每个包含阶段的输入是组合之前执行的阶段的输出
1111
+ inputPreviousStageTexture: false,
1112
+ });
1113
+
1114
+ Object.defineProperties(composite, {
1115
+ lineWidth: {
1116
+ get: function () {
1117
+ return edgeDetection.uniforms.lineWidth;
1118
+ },
1119
+ set: function (value) {
1120
+ Check.typeOf.number.greaterThan('lineWidth', value, 0);
1121
+ edgeDetection.uniforms.lineWidth = value;
1122
+ }
1123
+ },
1124
+ color: {
1125
+ get: function () {
1126
+ return edgeDetection.uniforms.color;
1127
+ },
1128
+ set: function (value) {
1129
+ value = parseToColor(value);
1130
+ Color.cloneRgb(value, edgeDetection.uniforms.color);
1131
+ }
1132
+ },
1133
+ });
1134
+
1135
+ composite.enabled = options.enabled ?? true;
1136
+ composite.color = options.color ?? Color.RED;
1137
+ composite.lineWidth = options.lineWidth ?? 1.0;
1138
+
1139
+ return composite;
1140
+ };
1141
+
1142
+ export default PostProcessStageLibrary;
1143
+ export { FogType, PostProcessStage, PostProcessStageLibrary };