Cesium中,提供了粒子效果,也能够实现下雨效果。但我个人觉得整体效果不是很满意:
1、粒子是局部的,如果覆盖范围过小,相机移动后,下雨效果就会移出屏幕。
2、下雨效果不是很明显(可能是我的参数设置的不是很准确)
偶然阅读了其他大佬的文章,发现用后处理特效可以实现很好的下雨效果。直接粘代码:
export function setRainEffect(viewer:Cesium.Viewer){
const fs = `//【内置变量】颜色纹理,用于在片元着色器中访问各个像素的颜色
uniform sampler2D colorTexture;
//【内置变量】纹理坐标,是从顶点着色器中传递下来的。
varying vec2 v_textureCoordinates;
float hash(float x){
//取小数部分
return fract(sin(x*23.3)*13.13);
}
void main(){
//将当前帧数转换为以秒为单位的时间
//在Cesium中,czm_frameNumber是一个递增整数值
//且一秒钟内,平均会渲染大约60帧,因此除以60可以得到近似的秒数
float time = czm_frameNumber / 60.0;
//窗口分辨率
vec2 resolution = czm_viewport.zw;
//转换为uv坐标(-1,1)
//gl_FragCoord.xy 表示当前片段的屏幕坐标(或窗口坐标)的X和Y分量。
//resolution.xy 表示屏幕或窗口的宽度和高度
//gl_FragCoord.xy * 2.0 - resolution.xy 将屏幕坐标扩大两倍,然后减去屏幕的宽度和高度。这样处理可以将坐标原点移至屏幕中心。
vec2 uv=(gl_FragCoord.xy*2.-resolution.xy)/min(resolution.x,resolution.y);
//雨颜色值(153,178,204),并做归一化处理(除以255)
vec3 c=vec3(0.6,0.7,0.8);
//定义雨滴的倾角0.4弧度,转为角度约为23度
float a=0.4;
float si=sin(a),co=cos(a);
//将纹理坐标uv角度a旋转
uv*=mat2(co,-si,si,co);
//将纹理坐标进行缩放变换(变形)
uv*=length(uv+vec2(0,4.9))*0.3+1.0;
//加入时间time,基础雨滴颜色,及变换后的uv坐标和一系列随机值运算
//得到每一个像素的雨滴颜色
float v=1.0-sin(hash(floor(uv.x*100.0))*2.0);
float b=clamp(abs(sin(20.0*time*v+uv.y*(5.0/(2.0+v))))-0.95,0.0,1.0)*20.;
c*=v*b;
//将雨与场景颜色混合
//texture2D(colorTexture, v_textureCoordinates)是获取场景原始颜色值
gl_FragColor = mix(texture2D(colorTexture, v_textureCoordinates), vec4(c, 1),0.4);
}
`;
viewer.scene.postProcessStages.add(new PostProcessStage({
name:'rainEffect',
fragmentShader:fs,
}))
}
因为我也是小白,所以对每一句代码都做了注释说明。
但对于形成雨滴的关键算法,还是没有太懂是什么原理。还希望看到的大佬能够指点迷津。
版权声明:本文为lying_19原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。