☰
第46篇:三维特效-动态围墙——让条纹顺着墙往上爬,只认高度不认长度
2026/10/10 9:12:23 网站建设 项目流程

面板上有一个滑块,标签写"流动速度",值是 3。

3 什么?3 米每秒?3 圈每秒?3 个像素每秒?滑块旁边没有单位,源码里也没有注释。

上一回我们在空气里发射线数云,这回回到地面上来——往地上立一堵墙,让条纹沿着墙面往上爬。看着简单,但"往上爬"这三个字背后藏着三个数:爬多快、条纹多粗、沿哪个方向爬。这三个数本猿一个都没猜对。

三维特效这条线从今天开篇。它跟前面几条线不太一样:缓冲区、插值、可视域量的是"结论对不对",特效这条线量的是"画面跟你以为的是不是同一回事"——面板调出来的观感,和着色器里真正算出来的东西,中间往往隔着一层。

我是 Cesium酱,一只在 WebGIS 领域摸爬滚打多年的前端猿。这个系列写到第 46 篇,本猿的规矩还是那句:只要面板上有数字,就得拿进 GPU 里对一遍账。牛马不易,忙忙停停,但每次量出"原来你算的是这个",那点兴奋劲还在。

本文目标:从一堵会流动的围墙出发,把WallGeometry的st坐标、czm_frameNumber驱动的时间、以及MaterialAppearance的半透明状态,三笔账一次算清。💪

💡 本文涉及的全部代码均已开源,完整的仓库地址见文末,可自行取用、随意魔改。


一、痛点与场景:为什么"围墙"值得单写一篇?

🎯 背景现状:在三维场景里画一圈"墙",是电子围栏、工地围挡、管控区边界、淹没范围立面、管线迁改红线这些需求的第一反应。它比面多一个高度维度,比线多一个可见的侧立面——看一眼就知道"边界在哪、有多高"。

典型场景:

  • 🏗️工地围挡:沿征地红线立一圈 2 米高的蓝皮围挡,还要能看出"这是一圈"而不是一条线
  • 🚧电子围栏:重点区域画一圈发光边界,越界报警时整圈变色
  • 🌊淹没立面:水位面抬到 15 米,给水体加一圈侧壁,才看得出"水深"是多少
  • 🛡️管控区:疫情防控、安保封控的边界,要求远远就能看见一道流动的光墙

🤦 传统痛点:

方案问题
Entity+WallGraphics材质只能用内置那几种,想做"流动"得上MaterialProperty自己写回调,改一个参数整圈重建
PolylineVolume有粗细有截面,但st是沿截面周长 + 沿线长,条纹方向跟墙体对不上
贴地Polygon+ 图片材质只有"顶面",没有立面;墙根本不存在
直接改Primitive的modelMatrix那是整墙平移旋转,不是纹理流动

💡 本文方案:

1️⃣WallGeometry出几何:maximumHeights/minimumHeights两个数组决定墙顶墙底,想把墙抬离地面只要改后者

2️⃣自定义Material写流动:fabric.source里 12 行 GLSL,靠czm_frameNumber推进相位,零 JS 开销

3️⃣MaterialAppearance上屏:translucent: true开混合,closed: false保留双面

✨ 一句话总结:把墙当成一张竖着的画布,把时间当成一个计数器,让纹理坐标自己减下去——流动就成了。


二、核心技术原理:WallGeometry的st到底怎么排

2.1 一面墙是怎么"长"出来的

WallGeometry的输入特别朴素:一串经纬度折点 + 每个折点的顶高和底高。但输出的顶点排布有个反直觉的地方——每一段墙的 4 个顶点是独立的,不跟邻段共享。

本猿拿WallGeometry.createGeometry()实测了一遍(@cesium/engine,一条正东西向直线,墙高 0→100 m):

折点数 N顶点数index 数三角面数
2462
38124
412186
516248

规律是顶点 = 4×(N−1)、index = 6×(N−1)、三角面 = 2×(N−1)。3 个折点本该 6 个顶点,实测 8 个——中间那个折点被拆成了两份(v2/v3 与 v4/v5 坐标完全相同),因为第 1 段和第 2 段各自要一份自己的顶点。

这么做的好处是每段可以独立设置顶底高度,坏处是顶点数约为"共享顶点"版本的 2 倍。对围墙这点量来说无所谓。

2.2 完整流程

核心亮点:第 4 步"每帧推进相位"是本文的杀手锏 🔪——整条时间链路上没有任何 JS 参与,全靠一个 GPU 自动 uniform 自增。

2.3 为什么用 Primitive 而不是 Entity

方案原理灵活性复杂度
Entity+WallGraphics由GeometryVisualizer代管,走MaterialProperty🐢 材质受限于MaterialProperty体系⚡ 低,几行搞定
Primitive+GeometryInstance自己管生命周期,直接吃Material实例🚀 任意 GLSL,任意 uniform🔧 中,要自己处理重建

简单说:想要"改一行 GLSL 就换一种观感",就得绕过MaterialProperty,直接持有Material。


三、代码实战:三个函数撑起一堵墙

⚠️ 温馨提示:为了方便,本篇只拆"几何 → 材质 → 回刷"这条主链路,绘制交互(左键加点 / 右键或双击收尾)沿用第 40 篇量过的同一套机制,不再重复。

3.1 造几何 + 造材质

functionbuildWall(lonLats:number[]):Primitive{constpositions=Cartesian3.fromDegreesArray(lonLats)constcount=lonLats.length

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询