用Cesium打造沉浸式雨天涟漪的真实感!

大家好,我是日拱一卒的攻城师不浪,致力于前沿科技探索,摸索小而美工作室,这是2025年输出的第46/100篇原创文章。

效果预览

www.bilibili.com/video/BV1jX...

在智慧城市或者智慧园区的项目开发过程中,一般都会涉及到天气效果的开发。简单的雨雪雾可能大家也都看腻了吧,如果下雨下雪的时候,能够增添一些场景的修饰,例如积雪、雨滴涟漪,会不会提升场景的真实感呢?

所以,今天我们就用Cesium实现一个雨天特效 ------ 雨滴涟漪。话不多说了,直接上代码!

涟漪效果实现

涟漪效果主要通过CustomShader自定义着色器去实现:

javascript 复制代码
let tileset;
let timer;
const customShader = new Cesium.CustomShader({
    uniforms: {
        u_lightColor: {
            type: Cesium.UniformType.VEC3,
            value: new Cesium.Cartesian3(1, 1, 1),
        },
        u_rainAlpha: {
            type: Cesium.UniformType.FLOAT,
            value: 0,
        },
    },
    fragmentShaderText: `
        // 着色器代码,在下边讲
    `,
});

着色器中定义了两个主要的uniform变量:

  • u_lightColor:控制光照颜色

  • u_rainAlpha:控制涟漪效果的强度,这是一个会随时间变化的参数

着色器算法解析

哈希函数

glsl 复制代码
float hash12(vec2 p)
{
    vec3 p3  = fract(vec3(p.xyx) * HASHSCALE1);
    p3 += dot(p3, p3.yzx + 19.19);
    return fract((p3.x + p3.y) * p3.z);
}

这个函数用于生成伪随机数,确保涟漪出现的位置看起来是随机的。

涟漪生成循环

glsl 复制代码
for (int j = -MAX_RADIUS; j <= MAX_RADIUS; ++j)
{
    for (int i = -MAX_RADIUS; i <= MAX_RADIUS; ++i)
    {
        // 循环内部代码
    }
}

这个双层循环遍历当前像素周围的一个区域,在这个区域内生成多个涟漪。

涟漪形状计算

glsl 复制代码
float t = fract(0.3*time + hash12(hsh));
vec2 v = p - uv;
float d = length(v) - (float(MAX_RADIUS) + 1.)*t;

这段代码计算了涟漪的形成扩散效果和传播距离。t表示时间因子,使涟漪随时间扩散。

法线扰动

glsl 复制代码
float p1 = sin(31.*d1) * smoothstep(-0.6, -0.3, d1) * smoothstep(0., -0.3, d1);
float p2 = sin(31.*d2) * smoothstep(-0.6, -0.3, d2) * smoothstep(0., -0.3, d2);
circles += 0.5 * normalize(v) * ((p2 - p1) / (2. * h) * (1. - t) * (1. - t));

这部分代码创建了实际的涟漪波形效果,通过正弦函数创建波纹,并使用smoothstep函数平滑过渡。

最终效果应用

glsl 复制代码
material.diffuse = mix(material.diffuse, vec3((n * vec3(1.2)).r) , u_rainAlpha * smoothstep(0., .5, dot(positionWC.xyz, normalWC)));

这行代码将计算出的涟漪效果与原始材质混合,并根据u_rainAlpha参数控制效果强度。

应用

javascript 复制代码
const initRipple = async () => {
    if (!tileset) {
        tileset = await Cesium.Cesium3DTileset.fromIonAssetId(69380);
        __viewer.flyTo(tileset);
        __viewer.scene.primitives.add(tileset);
    }

    tileset.customShader = customShader;
};

当加载完3dtiles模型后,直接将定义好的shader赋值给tileset,实现模型shader融合;

加载过程中,可以动态修改u_rainAlpha参数 实现涟漪渐进式的效果,可以带来更加自然的视觉体验,而不是突然出现的涟漪效果。

后期我们还可以加入声音效果,提升场景的沉浸式体验。

最后

这样的话,通过我们之前的积雪高度雾效果,再加上现在的雨滴涟漪,就可以给我们的项目增添一定的天气真实性,提升项目的观感体验。

【Cesium开源集合】:github.com/tingyuxuan2...

想系统学习Cesium的小伙伴儿,可以了解下不浪的教程《Cesium从入门到实战》,将Cesium的知识点进行串联,让不了解Cesium的小伙伴拥有一个完整的学习路线,并最终完成一个智慧城市的完整项目,课程最近也更新了很多进阶内容,想了解课程大纲,+作者:brown_7778(备注来意)。
有需要进可视化&Webgis交流群可以加我:brown_7778(备注来意)。

相关推荐
郝学胜-神的一滴8 天前
[简化版 GAMES 101] 计算机图形学 04:二维变换上
c++·算法·unity·godot·图形渲染·unreal engine·cesium
duansamve11 天前
Cesium快速入门到精通系列教程二十五:以较长经纬度跨度为基准,将多边形充满屏幕,返回此时的中心点坐标及相机高度
cesium
阿琳a_17 天前
在github上部署个人的vitepress文档网站
前端·vue.js·github·网站搭建·cesium
云上飞4763696218 天前
glb模型在Cesium中发黑的机理分析
cesium·glb模型发黑
ct97820 天前
Cesium的Primitive API
gis·webgl·cesium
Irene199121 天前
OpenLayers 和 Cesium 都是流行的开源 JavaScript 库,用于在网页上构建地图和地理空间应用
openlayers·cesium
fxshy21 天前
前端直连模型 vs 完整 MCP:大模型驱动地图的原理与实践(技术栈Vue + Cesium + Node.js + WebSocket + MCP)
前端·vue.js·node.js·cesium·mcp
棋鬼王21 天前
Cesium(十) 动态修改白模颜色、白模渐变色、白模光圈特效、白模动态扫描光效、白模着色器
前端·javascript·vue.js·智慧城市·数字孪生·cesium
duansamve22 天前
Cesium快速入门到精通系列教程二十四:限制相机在特定的Level之间展示地图
cesium
duansamve24 天前
Vue3的Vite项目中直接引入的方式使用Cesium
cesium