Ray Marching Ocean

最早在GPU Gem 1[1]中看到一篇文章介紹水體實時渲染, 那個時代的水面基本就是簡單的半透明平板, 後來有使用Normal模擬光照計算, 但其實模型本身還是平板. 再接著有比較大創新的就是Valve的FlowMap[2], 使得水的流向更加貼近環境並且基本沒增加性能消耗. 同一時期, Crytek的Sousa[3]劃時代的在遊戲內運用了基於頂點變換的真3D海面渲染. Sousa使用的方法主要來自Tessendorf[4]的一篇經典教科書式海面渲染必讀paper. CryEngine那時變換水面是在CPU端計算一個64x64大小的網格, 然後利用Tessellation在GPU端完成最終的海面細節處理. 隨著顯卡性能不斷提升, 今天我們可以把整個過程放在GPU完成.

完全的GPU渲染, 除了不需要在CPU端計算任何數據, 也不需要預先製作,烘焙任何數據貼圖. Render by UE4.

建模

Finch在文章中解釋過,水面的波形其實可以用多個周期波疊加而成:

Finch,GPU Gems 1.

多個正弦波疊加後,GPU Gems 1.

關於水面的起伏, 我們可以使用Gerstner Waves作為基本計算方程:

x=x_0-(K/kappa)Asin(Kcdot x_0 - omega t) 	ag{1}

y=Acos(Kcdot x_0-omega t) 	ag{2}

k=2pi/lambda 	ag{3}

其中x0指對應的模擬點的坐標, 這一點初始的高度值y0 = 0. K是一個表示該點水平運動方向的向量, λ是波長, A是振幅, w是頻率. 為了做多個波疊加把上述的(1),(2)累加即可, 但是需要注意每次疊加改變下相位.

3個Gerstner waves疊加, Tessendorf.

只疊加,波峰比較圓潤.

增加Choppy係數後.

有了波面數據, 我們依舊可以使用Ray Marching的方法去渲染光照.

光照

光照用的Normal可以使用塑造波的方法加些許擾動完成波光細節. 使用Normal可以計算大致的光影效果. 但是水跟雲一樣, 也需要模擬散射效果. 關於水面反射, 可以使用常規IBL的方法, 但是海面不是室內, 通常就是天空, 所以我直接使用一個參數控制方便調效果. 另外為了真實, 使用Fresnel係數來做相關計算. 我用的是Schlick[5]模型:

R(	heta)=R_0+(1-R_0)(1-cos	heta)^5 	ag{4}

此外還需要模擬一下次表面反射, 由於是海面, 相對簡單的平方衰減即可.

材質藍圖

水面高光+散射

https://www.zhihu.com/video/960686726432342016


[1]Mark Finch,Effective Water Simulation from Physical Models, 2004.

[2]Alex Vlachos, Valve, Water Flow in PORTAL 2, 2010.

[3]Sousa, T, Crytek, Crysis Next Gen Effects, 2008.

[4]Jerry Tessendorf, Simulating Ocean Water, 2004.

[5]Schlicks approximation


推薦閱讀:

圖靈宇宙漫遊指南
走樣與反走樣(Aliasing/Anti-Aliasing):Graphics Cases
拓幻圖形學工程師教學手冊(第三講)|一字一字敲出OpenGL學習教程
計算機圖形學常用術語整理

TAG:計算機圖形學 | 虛幻引擎 | 實時渲染 |