真实感海洋的绘制(三):水面的渲染

less than 1 minute read

Published:

根据上述两篇博客,我们已经得到了真实感较高的水面波形和法向量。为了节省所需要的顶点数目,需要将高度场和法线制作成贴图传入着色器,以便从较少的顶点就能渲染很大面积的海面。之后的任务就是对这些波形进行真实感的渲染。

基本原理

首先,高度真实感的、基于真实物理的水面光照模型相当复杂,即使能够用计算机计算,也几乎不可能实时地完成。因此,现有的实时水面渲染方法基本不会使用此类模型。本文的方法将采用只计算一次反射和折射的简单模型。

首先我们先画出高中物理中的反射和折射模型:

A

其中,$\vec{v_i}$是入射光向量,$\theta_i$是入射角,$\vec{v_r}$是反射光向量,$\theta_r$是反射角,$\vec{v_t}$为折射光向量,$\theta_t$是折射角,$\vec{n}$是法线向量。其中,入射角和反射角相等。根据斯涅尔定律(Snell’s Law),入射角和折射角满足如下关系

\[n_i\sin\theta_i=n_t\sin\theta_t\]

其中,$n_i$和$n_t$分别为入射介质和折射介质的折射率,对于空气而言,$n_i=1.00$,对于水而言,$n_t=1.33$(近似值)。

以上讨论反映了在表面某一点的反射情况和折射情况。如果要知道这一点反射了哪里的光,可以从观察点开始做一层光线追踪,也就是假设摄像机在$\vec{v_r}$所指向的位置,反向计算出$\vec{v_i}$。之后我们必须计算出$\vec{v_i}$光的颜色。一般的实现方法是把四周的场景预计算,存储为环境贴图,然后就可以根据$\vec{v_i}$向量值来计算出这一点的入射光颜色。对于开阔的海面而言,被反射的自然就是天空了。如图所示。

A

当然,水面并不是一面完美的镜子。射入水面的入射光,一部分反射了回来,另一部分在折射后进入了水面,与此同时,在水面处也有从水面下经过折射后又反射回来的光。在无限大的水面中,我们可以不考虑水下反射光的复杂性,单纯将其假设为某种固定的颜色。

对于水面上任何一点,最终摄像机收到的颜色是反射环境的颜色和折射出的水下颜色之和。对于不同的入射角$\theta_i$,入射光反射的比例$R$和折射进入水面的比例$T$是不一样的,但是满足$R+T=1$。这在物理上被称作费舍尔效果(Fersnel Effect)。利用电磁学理论我们可以推导出$R$有如下的关系

\[R=\frac{1}{2}\{\frac{\sin^2(\theta_t-\theta_i)}{\sin^2(\theta_t+\theta_i)}+\frac{\tan^2(\theta_t-\theta_i)}{\tan^2(\theta_t+\theta_i)}\}\]

当从空气进入水的时候,入射角为0度时$R=0$,然后随着角度变大而变大,当入射角为90度时$R=1$。当从水进入空气时则存在全反射的现象,当入射角大于某个角度后就会全部反射,没有折射。

因此,对于水面任意一点,我们得到简单的颜色计算公式

\[Color = R * Color_{incident} + (1 - R) * Color_{deepWater}\]

就可以完成水面的着色。

一些美化

显然,由于计算资源的限制,我们是不可能高精度绘制无限大的海面的。为了节省计算资源,一种方法是使用LOD技术(Level Of Details),让近处的网格顶点密度高、远处的顶点密度低。如果有时间的话之后我会研究一下各种LOD技术。在这里,我们先使用一个偷懒的方法:加入薄雾。一方面可以遮挡住远处顶点网格的空缺,另一方面可以适当设置雾的颜色以便在远处和天空盒融为一体,最终能够获得足够好的视觉效果。

要在计算机中实现雾其实非常简单。雾可以视为一种叠加在已有物体上的颜色,这个颜色随着距离变远而加深,从而在有雾的场景中,一个像素点的颜色可以表示如下

\[Color = (1 - F(d)) * Color_{object} + F(d) * Color_{fog}\]

其中,$F(d)$是雾的参数函数,$d$是这个片元像素距离摄像机的距离,通过选取适当的参数函数,我们可以模拟出比较逼真的雾效果。我选取的参数函数如下

\[F(d)=1 - e^{-cd}\]

相信学过高中数学的读者都能画出这个函数的图像。其中,$c$是一个常量,其值越大,雾越浓,适当地调整参数可以获得我们想要的效果。

此外,为了和天空盒的远处相融合,我们需要利用摄像机到片元的方向来取值,从天空盒边缘取得适当的颜色来产生真实的雾效果。

实现结果

代码可见[https://github.com/hehao98/WaterRendering]

A A A A

参考文献

  1. Tessendorf, Jerry. Simulating Ocean Water. In SIGGRAPH 2002 Course Notes #9 (Simulating Nature: Realistic and Interactive Techniques), ACM Press.
  2. Johanson, Clase. Real-time water rendering - Introducing the projected grid concept. Master of Science Thesis. Lund University
  3. Toman, Wojciech. Rendering Water as a Post-process Effect. https://www.gamedev.net/articles/programming/graphics/rendering-water-as-a-post-process-effect-r2642/