地图是对真实地理空间的图形化表达,地图基于独特的符号化方式、严格的数学法则及综合方法来表达地理世界复杂的空间结构和空间关系。
然而传统的符号化地图虽然具备一定的科学性,却缺失了地理环境的一些细节和真实感,比如环境中的光影效果、真实感水面效果等。
场景基于Mapmost SDK制作
水面倒影作为一种极具视觉冲击力的元素,能显著提升地图的沉浸感和逼真度。
Mapmost SDK for WebGL作为一款轻量化二三维一体化渲染GIS引擎,不仅具备丰富的地图表达和地图交互能力,还致力于提升地图场景的真实感渲染效果。SDK具有丰富的三维场景设置效果,以及矢量动态水面、地图天空设置等提升场景真实感的能力。
场景基于Mapmost SDK制作
今天就带大家一起了解一下,Mapmost是如何在地图引擎中实现水面倒影的~
一、倒影的概念
倒影是自然界的一种物理现象。我们都知道,眼睛之所以能够看到物体,是因为物体本身能发光,或物体能够反射光,这些光进入到我们的眼中就形成了该物体的像。
倒影也是一种光学现象,其原理是物体发射或者反射的光经过倒影平面的反射后进入到我们的眼里,我们所看到的在倒影平面形成的虚像就是该物体的倒影。
镜面反射
二、地图引擎中实现倒影的基本思路
(1)倒影是在水面上的呈现,因此首先要有水面,本质上倒影是将物体的倒影成像绘制到水面上,所以可以明确我们需要实现的是水面材质。
(2)实现思路:对相机关于水面(反射平面)做镜面反射变换,得到倒影相机,用倒影相机对场景进行离屏渲染得到一张反射纹理,在水面着色阶段,以片元屏幕坐标为参考,对反射纹理进行采样取值,和原始水面材质进行颜色混合,得到水面反射场景的效果。
倒影相机
倒影渲染流程
具体可以通过three.js来体验一下:
- 首先,让我们构建一个三维场景,加入喜欢的小房子,并且构建一个平静的水面
图源:木一
- 然后,创建一个反射相机,先观察一下反射相机的视角。反射相机的位置计算可以参考这篇文章:https://juejin.cn/post/6962854912434634783
图源:木一
- 最后,根据上述流程,自定义水面着色器材质,实现水面倒影渲染
// 渲染流程
renderer.setRenderTarget(target);
renderer.render(reflectScene, reflectCamera);
reflectMaterial.uniforms.tDiffuse.value = target.texture;
renderer.setRenderTarget(null);
renderer.render(scene, camera);
// 片元着色器
vec3 coord = (vPos.xyz/vPos.w)/2.0 + 0.5;
vec2 uv = vec2(coord.x, 1.0 - coord.y);
vec4 reflectColor = texture2D(tDiffuse, uv);
gl_FragColor.rgb = mix(uColor.rgb, reflectColor.rgb, 0.6);
gl_FragColor.a = uOpacity;
图源:木一
- 看起来好像有点生硬,毕竟现实中难得有这种岁月静好的时刻,让我们来加点涟漪吧~
vec2 uv = coord.xy + coord.z * normal.xz * 0.05;
图源:木一
三、Mapmost中如何添加水面倒影
Mapmost SDK for WebGL实现了基于矢量瓦片地图的动态水面及水面倒影渲染,大家只要调用SDK接口,配置相关参数即可,具体可以参考官方文档
官方文档链接:https://www.mapmost.com/mapmost_docs/webgl/latest/docs/demo/2D_Vector_waterFlow/
map.addLayer({
"id": "waterFlow",
"type": "fill",
"source": "nature",
"source-layer": "water",
"paint": {
"fill-waterflow-normal": "./static/waterBump.png", // 动态水面法线贴图
"fill-waterflow-noise": "./static/waterNoise.png", // 动态水面噪声贴图
"fill-waterflow-speed": 1, // 动态水面水流速度
"fill-waterflow-reflect-sun": false, // 是否反射太阳光
"fill-waterflow-reflect": true, // 是否开启水面倒影
}
})
场景基于Mapmost SDK制作,作者@羊库库v