效果图放前面
- 符合你预期效果往下看,不符合出门右转,不耽搁大家时间。
流光线
这个流光线网上其实都有很多案例
- 第一步绘制抛物线
里面有些配置参数已经添加了说明。
//抛物线绘制
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 * 2
let 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); //求抛物线函数x
endPoint[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;
}
`
},
}),
})
}))