GPU Gems 2 · Chapter 18. Using Vertex Texture Displacement for Realistic Water Rendering

用顶点纹理位移把滚动高度场变成水面几何,再用邻域法线、反射和 LOD 控制真实感与 GPU 成本。

学习目标

  • 能解释 vertex texture displacement 如何把时间变化的高度场映射到水面顶点,并说明它受网格密度与纹理寻址的约束
  • 能实现两张滚动高度纹理的混合、位移后 normal reconstruction,并区分几何更新、光照更新和反射采样
  • 能调节 VertexWaterLab 的波形、网格密度与相机距离,定位法线滞后、边界接缝和远景顶点浪费

先把“水面动画”拆成几何、法线和采样

真实水面不是一张会移动的蓝色图片。镜头靠近时,波峰会改变轮廓;光线移动时,高光又会沿波面改变;镜头拉远后,屏幕上一个像素可能覆盖很多个波纹。要把这三个现象同时表达出来,需要让高度场参与顶点位置、让位移后的邻域参与法线,并让细节层级匹配屏幕覆盖率。

先打开实验,固定相机距离,分别改变 wave time、wave B mix 和 grid density。预测哪一个旋钮会改变几何轮廓,哪一个只改变相位;再切换 normal debug 与 LOD debug,观察水面是否“形状在动但高光不动”,或远景仍在处理近景级别的顶点。

Vertex texture displacement 水面实验

先改变高度场,再打开法线与 LOD 调试,观察几何、光照和带宽如何互相约束。

vertex displacement:高度场推动网格displaced surface · grid 18 × 18实验记录height min-0.66height max0.66vertex samples648camera distance4.5法线调试时绿色线 = Ntime 改变波相位;distance 变大后减少有效网格,避免远景顶点工作浪费

位移网格显示高度场的几何结果;时间变化只改变相位,不能替代索引/边界更新。

vertex texture displacement:在顶点阶段把高度变成几何输入状态height mapstime · wave mixmesh UV / LODvertex stagesample heightp.y += h(u, t)emit displaced prender resultcurved water meshreconstructed normalreflection / refraction关键边界:顶点纹理读取改变几何位置,但不会自动替你生成正确法线

把水面管线分成四段:CPU 或材质状态提供时间、波形参数和网格;顶点阶段通过 UV 读取 height field 并修改位置;几何之后重建或传递正确法线;像素阶段再进行反射、折射、雾和颜色合成。任何一段使用了不同的 UV、时间或坐标约定,都会出现“几何在动但光照不跟随”的错觉。

1. 用高度场推动规则网格

规则网格的每个顶点可以携带 (u,v)(u,v)。将 UV 映射到水面局部坐标 (x,z)(x,z),从一个或多个高度纹理读取 hh,再沿水面法线方向写入位置:

p(u,v,t)=p0(u,v)+hatnupAh(u,v,t), p'(u,v,t)=p_0(u,v)+hat{n}_{up}\,A\,h(u,v,t),

其中 AA 是世界单位中的位移幅度。关键是 hh 的采样和网格位置必须使用相同的空间尺度;如果纹理滚动速度以 texel 为单位而网格以米为单位,波速和波长会随着物体缩放悄悄改变。

从高度场到波面:采样、混合、位移height AUV + time · tile Aheight BUV + time · tile Bdisplaced meshp.y = mix(hA, hB, mix) · conservative bounds高度纹理是离散场;UV 滚动、边界寻址和幅度约定共同决定波面是否连续

两张或多张高度纹理可以用不同方向和速度滚动,再按 mix 权重叠加,以减少单张纹理的重复感。混合不应只叠颜色:高度、法线和用于反射的微表面方向必须来自一致的波场。高度纹理的 wrap 方式也会影响边界,周期 tile 可以无缝循环,但 clamp 会在边缘形成水平带。

如果采用解析波而不是纹理,Gerstner wave 可以直接给出位置和导数,便于得到更尖的波峰;但多个波相加时要限制总振幅,否则波面会穿过海床或产生不合理的自交。纹理高度场更适合把离线模拟或艺术家绘制的细节搬到 GPU,代价是纹理带宽、寻址和 mip 选择。

2. 位移后法线决定高光是否可信

位移几何改变了表面切线,原始平面法线不能继续代表水面。最直接的重建方法是对同一个时间和高度函数采样两个相邻点:

T=p(u+ϵ,v,t)p(u,v,t),B=p(u,v+ϵ,t)p(u,v,t),N=normalize(T×B). T=p'(u+\epsilon,v,t)-p'(u,v,t),\qquad B=p'(u,v+\epsilon,t)-p'(u,v,t),\qquad N=normalize(T\times B).
位移后法线:用邻域差分跟随真实波面T ≈ p(x + ε) − p(x)B ≈ p(z + ε) − p(z)N = normalize(T × B)只更新位置不更新法线 → 反射高光仍按旧平面计算,水面会显得“平滑但不对光”

这里的 epsilonepsilon 应与一个 texel 或网格边长相关,而不是永远使用一个随场景缩放失效的常数。若法线在顶点阶段重建,可以把结果随顶点传给像素阶段;若水面采用更密的像素级法线细节,也要保证低频几何法线与高频法线贴图的切线框架一致。两套法线使用不同时间或不同 UV,会让反射高光出现相位漂移。

水面材质通常还会使用 Fresnel 权重、反射环境和折射颜色。几何位移负责轮廓,法线负责局部方向,Fresnel 负责视角依赖的反射比例;不要用把蓝色加亮的方式代替这些证据。调试时可以先关闭雾和泡沫,只显示法线方向,再逐层恢复反射与折射。

3. 网格密度与 level of detail

本章的主题是 Using Vertex Texture Displacement for Realistic Water Rendering:把高度场送入顶点阶段,形成可被镜头观察到的波形轮廓,再用法线和反射完成水面外观。

顶点纹理位移只能移动已有顶点,不能凭空增加几何。若一个波峰在屏幕上覆盖多个像素但网格只有一条边,增加 height texture 分辨率也不会让轮廓变细;反过来,远处一个像素覆盖大量波纹时,仍使用近景密度会浪费 vertex fetch 和变换工作。

LOD:让网格密度匹配屏幕上的水面细节near cameramidfarhigh densityfine vertices · sharp detailbalancedfewer samples · stable motionlow densitywide footprint · low costLOD 不是简单删点:需要同时调整网格、height mip、法线邻域与位移幅度

LOD 需要同步考虑四项:网格顶点数量、height map 的 mip 或采样 footprint、法线重建邻域,以及位移幅度与包围盒。块状水面可以用环形网格或分块 LOD,让靠近相机的区域更密;相邻环之间要用共享边、裙边或约束采样消除裂缝。远景也可以把高频波纹转移到法线或反射扰动,但这改变的是表现层级,不是几何轮廓。

三步实验:从高度采样到可信光照

每一步只改变一个变量,并以“位置、法线、屏幕细节”三类证据记录结果。只要出现接缝或高光跳变,就先固定时间和相机,不要继续增加波形复杂度。

分步1 / 3

第一步:验证 height field 到位移位置

保持 grid density 不变,只改变 wave time 与 wave B mix。先预测水面轮廓和高度范围,再在位移网格模式中检查 UV 滚动、振幅和 tile 边界是否连续。

从高度场到波面:采样、混合、位移height AUV + time · tile Aheight BUV + time · tile Bdisplaced meshp.y = mix(hA, hB, mix) · conservative bounds高度纹理是离散场;UV 滚动、边界寻址和幅度约定共同决定波面是否连续

常见误区

本章小结

  • Using Vertex Texture Displacement for Realistic Water Rendering 的核心是:在顶点阶段从 height field 读取高度,把规则网格变成有轮廓的水面几何。
  • 多张滚动高度纹理或 Gerstner wave 可以降低重复感、表达传播方向,但 UV、时间、振幅和边界必须保持一致。
  • 位移后必须执行 normal reconstruction;位置改变、法线改变和 Fresnel 反射是不同层次的证据。
  • level of detail 要同时协调网格、height mip、法线邻域和块边界;纹理分辨率不能替代缺失的顶点。
  • 发布前用固定的边界、相机移动和时间回归检查接缝、裁剪、高光相位与远景成本,而不是只看静态近景截图。

练习

问题 1|定位平面水面。 高度纹理在调试视图中确实有波纹,但最终水面轮廓仍是平面。请给出排查顺序。

问题 2|诊断高光滞后。 水面轮廓已经随时间变化,但镜面高光方向几乎不变。请解释原因并提出修复。

问题 3|设计水面 LOD。 近景需要尖锐波峰,远景希望降低顶点和纹理成本。你会同步调整哪些量,如何验证不会出现裂缝?

名词解释

本章出现的专业名词,用大白话再讲一遍。

vertex texture displacement
height field
Gerstner wave
normal reconstruction
level of detail

讨论

评论区加载中…