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

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

前言

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

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

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

思路

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

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

绘制几何体

先用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参数的四个点要怎么获取,具体描述如下:

再画一张意象图:

有的小伙伴说,我理解了这个范围取值,但是我要怎么在地球上去获取具体的坐标点位呢?这也难不倒我们,我们可以直接在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,也欢迎数字孪生可视化领域的交流合作。

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

骋天淹没分析系统 骋天淹没分析系统是以三维地理信息系统为基础平台,基于数字高程模型(DEM)格网模型,通过改进迭代种子蔓延算法将淹没分析结果直观在三维地理系统系统上呈现出来。 骋天淹没分析系统应用于水库的库区淹没分析时,设置好起止水位和终止水位,以三维的形式呈现库区淹没区域,根据不同是水深来计算库容量,移民数量、直接经济影响和间接经济影响。可将数据制作成柱状图、饼状图、曲线图等多种多样的统计图;能够根据业务流程和用户要求定制各类表格,进行业务报表输出;还能按某一要素生成范围图、点密度图、分级符号图等,进行专题图分析,形象直观地反映防洪要素的时空变化规律。 骋天淹没分析系统亦可应用于洪水淹没分析时,根据洪水演进过程,配合数字化地图,利用三维模型,计算洪水淹没范围和淹没水深,并动态显示淹没区域并动态显示淹没区域,计算人口、家庭财产、工商、企业、农业、林业、渔业和畜牧业等淹没信息。并可根据预报调度、实时调度和历史调度等不同洪水下泻过程,计算分析洪水淹没损失,显示淹没分布状况,从而得出最佳洪水调度预案,提供泄洪区域内人员撤退、避灾转移和救灾物资供应等最佳行动路线。 广西骋天信息科技有限公司 网站 www.gxchengtian.com
当然可以,以下是一个更加浪漫的版本,它可以生成一张浪漫的夜空背景和星空,同时在背景中绘制一个闪烁的心形图案,并且可以根据输入的文字自动调整字体大小和位置。 ```python import turtle import time import random # 定义颜色列表和字体列表 colors = ['red', 'orange', 'yellow', 'green', 'blue', 'purple'] fonts = ['Arial', 'Helvetica', 'Verdana', 'Comic Sans MS', 'Times New Roman'] # 获取屏幕大小 width, height = turtle.screensize() # 计算字体大小和位置 font_size = min(width, height) // 10 text_x = 0 text_y = -height // 3 # 设置画笔 turtle.speed(0) turtle.bgcolor('black') turtle.penup() # 绘制夜空背景 for i in range(200): x = random.randint(-width, width) y = random.randint(-height, height) turtle.goto(x, y) turtle.dot(2, 'white') # 绘制星空 for i in range(50): x = random.randint(-width, width) y = random.randint(-height, height) turtle.goto(x, y) turtle.pencolor('white') turtle.write('*', font=(fonts[0], 20, 'bold')) # 画闪烁的心形 for i in range(30): turtle.color(colors[i % len(colors)]) turtle.pendown() turtle.begin_fill() turtle.setheading(0) turtle.forward(50) turtle.circle(25, 180) turtle.forward(50) turtle.left(180) turtle.circle(25, 180) turtle.end_fill() turtle.penup() # 写入文字 turtle.goto(text_x, text_y) turtle.color('white') turtle.write('I love you', font=(fonts[0], font_size, 'bold'), align='center') # 自动调整字体大小和位置,保证文字不超出屏幕 while turtle.window_width() * 0.9 < turtle.screensize()[0] or turtle.window_height() * 0.9 < turtle.screensize()[1]: font_size -= 1 turtle.clear() turtle.write('I love you', font=(fonts[0], font_size, 'bold'), align='center') text_y -= font_size turtle.goto(text_x, text_y) turtle.color('white') turtle.write('I love you', font=(fonts[0], font_size, 'bold'), align='center') turtle.hideturtle() turtle.done() ``` 你可以将这段代码保存为 `romantic.py` 文件,然后在终端中运行 `python romantic.py` 命令即可看到浪漫的夜空背景和星空,以及闪烁的心形图案和自适应文字。你也可以根据自己的需要自定义颜色和文字,或者修改字体列表和颜色列表。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值