就这?你模拟的这个水可太小儿科了!

攻城师不浪 2024-09-13 13:33:01 阅读 88

大家好,我是日拱一卒的攻城师不浪,专注可视化、数字孪生、前端提效、nodejs、AI学习、GIS等学习沉淀,这是2024年输出的第22/100篇文章。

交流合作:brown_7778。

前言

上次发了一篇水淹模拟的动画演示cesium中如何高性能渲染3D模型(附水淹分析模拟),其中的水就是简单的用<code>entity渲染了一个立方体并附着了颜色。

说句实话,这效果如果摆在甲方面前,他可能上来就会给我一个大逼斗!

所以我痛定思痛,决定认真努力工作,立马端正态度。

思路

要想让水体变得逼真,除了要用一个几何体去充当它的载体,更重要的是要有真实的<code>水体材质,把材质铺贴在几何体之上。

但是光有材质也不行,因为水是动态的,所以还要想办法让材质动起来。

绘制几何体

先用RectangleGeometry画一个矩形的几何体

const rectangleGeometry = new Cesium.RectangleGeometry({ -- -->

// fromDegrees接收西、南、东、北四个经纬线的具体坐标,从而框出一个矩形

rectangle: Cesium.Rectangle.fromDegrees(120.34, 36.06, 120.42, 36.13),

// 要计算的顶点属性

vertexFormat: Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT,

// 几何体的垂直高度

height: 1000,

})

可能有的小伙伴不知道Cesium.Rectangle.fromDegrees参数的四个点要怎么获取,具体描述如下:

再画一张意象图:

有的小伙伴说,我理解了这个范围取值,但是我要怎么在地球上去获取<code>具体的坐标点位呢?这也难不倒我们,我们可以直接在cesium初始化成功之后,开发一个辅助获取坐标点位的功能。

获取点击坐标

// 监听点击事件,拾取具体坐标点位

const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);

handler.setInputAction((e) => { -- -->

const clickPosition = viewer.scene.camera.pickEllipsoid(e.position);

const randiansPos = Cesium.Cartographic.fromCartesian(clickPosition);

console.log(

"经度:" +

Cesium.Math.toDegrees(randiansPos.longitude) +

", 纬度:" +

Cesium.Math.toDegrees(randiansPos.latitude)

);

}, Cesium.ScreenSpaceEventType.LEFT_CLICK);

以上代码就是通过监听鼠标左键点击,获取到屏幕坐标,再把屏幕坐标转换成投影坐标系

创建几何体实例

const geometryInstance = new Cesium.GeometryInstance({

geometry: rectangleGeometry

})

Primitive

创建图元几何图形,渲染几何体,并给几何体上材质。

const primitive = new Cesium.Primitive({

geometryInstances: geometryInstance,

// appearance用于渲染图元的外观

appearance: new Cesium.EllipsoidSurfaceAppearance({

// 材质参数

material: new Cesium.Material({

fabric: {

type: "Water",

uniforms: {

baseWaterColor: new Cesium.Color(

64 / 255.0,

157 / 255.0,

253 / 255.0,

0.5

),

normalMap: "/images/waterNormals.jpg",

frequency: 1000.0,

animationSpeed: 0.1,

amplitude: 10,

specularIntensity: 10,

},

},

}),

})

})

fabric:通过配置cesium提供的现有的一些参数组合,可以幕后生成并组装成 glsl 着色器代码

具体参数组合参考:http://cesium.xin/cesium/cn/Documentation1.95/Material.html?classFilter=Material

换句话说:cesium已经提前预置好了一些着色器代码,并可以通过fabric这个参数的配置去生成一些常见的效果,而省去我们需要写glsl代码的一些成本。

所以我们直接选择可以生成的代码片段,参数解析如下:

baseWaterColor : rgba 颜色对象水的基色。

blendColor :从水混合到非水区域时使用的 rgba 颜色对象。

specularMap :用于指示水域的单通道纹理。

normalMap :水法线扰动的法线贴图。

frequency :控制波数的数字。

animationSpeed : 控制水的动画速度的数字。

amplitude :控制水波振幅的数字。

specularIntensity :控制镜面反射强度的数字。

以上,然后对应我们的代码,我们就可以通过调整这些参数配置,去调整水的样式了,非常方便。

最后别忘记,把生成的primitive添加到场景当中。

viewer.scene.primitives.add(primitive)

就这样,一个真实的水体就通过cesium成功的渲染出来了。

请添加图片描述

甲方看了后直竖大拇指:这就叫专业!

【开源地址】:https://github.com/tingyuxuan2302/cesium-vue3-vite/blob/github/src/views/material/water.vue

有需要进技术产品开发交流群(可视化&GIS)可以加我:brown_7778,也欢迎<code>数字孪生可视化领域的交流合作。

最后,如果觉得文章对你有帮助,也希望可以一键三连👏👏👏,支持我持续开源和分享~



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。