效果图放前面
- 符合你预期效果往下看,不符合出门右转,不耽搁大家时间。
流光线
这个流光线网上其实都有很多案例
- 第一步绘制抛物线
里面有些配置参数已经添加了说明。
//抛物线绘制
function parabola(twoPoints: number[]) {let s: number[] = []let startPoint = [twoPoints[0], twoPoints[1], 0]; //起点的经度、纬度s = s.concat(startPoint)let step = 80; //线的多少,越多则越平滑(但过多浏览器缓存也会占用越多)let heightProportion = 0.125; //最高点和总距离的比值let dLon = (twoPoints[2] - startPoint[0]) / step; //经度差值let dLat = (twoPoints[3] - startPoint[1]) / step; //纬度差值let deltaLon = dLon * Math.abs(111000 * Math.cos(twoPoints[1])); //经度差(米级)let deltaLat = dLat * 111000; //纬度差(米),1纬度相差约111000米let endPoint = [0, 0, 0]; //定义一个端点(后面将进行startPoint和endPoint两点画线)let heigh: number = step * Math.sqrt(deltaLon * deltaLon + deltaLat * deltaLat) * heightProportion * 2let x2 = (10000 * Math.sqrt(dLon * dLon + dLat * dLat)); //小数点扩大10000倍,提高精确度let a = (heigh / (x2 * x2));function y(x: number, height: number) { return height - a * x * x; }for (var i = 1; i <= step; i++) { //逐“帧”画线endPoint[0] = startPoint[0] + dLon; //更新end点经度endPoint[1] = startPoint[1] + dLat; //更新end点纬度let x = x2 * (2 * i / step - 1); //求抛物线函数xendPoint[2] = y(x, heigh) * 1; //求end点高度s = s.concat(endPoint)// end点变为start点startPoint[0] = endPoint[0];startPoint[1] = endPoint[1];startPoint[2] = endPoint[2];}return Cesium.Cartesian3.fromDegreesArrayHeights(s)
}
- 第二步添加曲线
就是cesium常用的primitive方式
let mm = parabola(i)const polyline = new Cesium.PolylineGeometry({positions: mm,width: 2});const instance = new Cesium.GeometryInstance({geometry: polyline,id: 'flyline',
})const pi = viewer.scene.primitives.add(new Cesium.Primitive({geometryInstances: [instance],appearance: getFlylineMaterial1(),releaseGeometryInstances: false,compressVertices: false,}))
- 第三步添加材质
重点来了
变量或函数解释:
czm_frameNumber:cesium内置变量,随时间变化的帧数
mix:混合函数
smoothstep:样条插值
纹理坐标st.s纵向,st.t横向,随着时间不断移动材质的位置
function getFlylineMaterial1() {return new Cesium.PolylineMaterialAppearance({material: new Cesium.Material({fabric: {type: 'test',uniforms: {speed: 20,repeat: 1,color: Cesium.Color.fromCssColorString('rgba(0, 209, 237,.1)'), // 线段颜色flowColor: Cesium.Color.fromCssColorString('rgba(0, 181, 255,1)'), // 流光颜色flowSpeed: 0.01, // 流光速度flowIntensity: 1.0, // 流光强度startTime: Math.random()},source: /* glsl */ `uniform vec4 color;uniform vec4 flowColor;uniform float speed;uniform float repeat;uniform float startTime;czm_material czm_getMaterial(czm_materialInput materialInput){czm_material material = czm_getDefaultMaterial(materialInput);//st.s纵向 st.t横向vec2 st = materialInput.st;float time = fract(czm_frameNumber * speed / 1000.0 + startTime);float offset = fract(st.s*repeat - time);//mix混合 smoothstep样条插值vec4 ackColor = mix(color, flowColor, smoothstep(1.0 - offset, 1.0 + offset, st.s));material.diffuse = ackColor.rgb;material.alpha = ackColor.a;material.emission = ackColor.rgb * 0.5;return material;}`}})})
}
动态扩散圆
逻辑是和上面一致的
着色器中的材质代码:
discard:用于丢弃当前片段(像素)的渲染。当在片段着色器中遇到 discard 关键字时,当前片段将被丢弃,不会参与后续的渲染过程。白话(不渲染)
viewer.scene.groundPrimitives.add(new Cesium.GroundPrimitive({geometryInstances: new Cesium.GeometryInstance({geometry: new Cesium.EllipseGeometry({center: Cesium.Cartesian3.fromDegrees(i[2], i[3]),semiMajorAxis: 30000.0,semiMinorAxis: 30000.0,}),attributes: {color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.WHITE)}}),appearance: new Cesium.MaterialAppearance({vertexShaderSource: ``,material: new Cesium.Material({fabric: {type: 'dynamics point',uniforms: {color: new Cesium.Color(1, 1, 0, 0.7),speed: 12.0,count: 2,gradient: 0.2,},source: /* glsl */ `uniform vec4 color;uniform float speed;uniform float count;uniform float gradient;czm_material czm_getMaterial(czm_materialInput materialInput){czm_material material = czm_getDefaultMaterial(materialInput);material.diffuse = 1.5 * color.rgb;vec2 st = materialInput.st;float dis = distance(st, vec2(0.5, 0.5));float per = fract(czm_frameNumber * speed / 1000.0);if(count == 1.0){if(dis > per * 0.5){discard;}else {material.alpha = color.a * dis / per / 2.0;}} else {vec3 str = materialInput.str;if(abs(str.z) > 0.001){discard;}if(dis > 0.5){discard;} else {float perDis = 0.5 / count;float disNum;float bl = 0.0;// for (int i = 0; i < 5; i++) {// 在循环中执行操作// }for(int i = 0; i <= 5; i++){if(float(i) <= count) {disNum = perDis * float(i) - dis + per / count;if(disNum > 0.0) {if(disNum < perDis){bl = 1.0 - disNum / perDis;}else if(disNum - perDis < perDis){bl = 1.0 - abs(1.0 - disNum / perDis);}material.alpha = pow(bl,(1.0 + 10.0 * (1.0 - gradient)));}}}}}return material;}`},}),})}))