经纬志
首页 / three.js / 使用示例

水面着色

一片一百二十米见方的水面,浪高与流速可调,七个浮标随波起伏。 整片水面没有任何贴图,深浅色、反射与高光全部在着色器里算。

three.js 0.160.0 · 更新 2026-10-28
源码与运行效果
运行效果

三组波叠加的原因

只用一组正弦波,水面会出现明显的平行条纹,像一块有规律的布。 两组方向不同的波叠加后条纹开始交错,再加一组高频小波, 波峰与波谷就不再重复,观感接近真实水面。

网格是 220 × 220 段,近五万个顶点。再稀一点,波长较短的波会被采样不足, 表现为水面出现锯齿状折线。

参数取值说明
网格220 × 220约五万顶点
浪高0.1 – 1.6顶点位移的幅度
流速0.2 – 2.4时间推进的倍率
高光指数120太阳反射的集中程度

菲涅尔是水面的关键

垂直向下看时水是深色,接近平视时反射天空变成亮色。 这一条由视角与法线的夹角决定,用 pow(1 - dot, 3) 就能近似。 缺了它,水面会像一块均匀的蓝色塑料。

示例用波的导数近似法线,省掉了逐帧重算法线的开销。 顶点位移与法线来自同一个函数,两者不会脱节。

浮标与水面必须同源。浮桥、船只、栈桥的起伏要和水面用同一套波形函数, 否则会出现「水面在动、浮标不动」的割裂感。 示例把波形抽成两份代码共用同一组系数,正是为了保证这种一致。