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完成.
建模
Finch在文章中解釋過,水面的波形其實可以用多個周期波疊加而成:
關於水面的起伏, 我們可以使用Gerstner Waves作為基本計算方程:
其中x0指對應的模擬點的坐標, 這一點初始的高度值y0 = 0. K是一個表示該點水平運動方向的向量, λ是波長, A是振幅, w是頻率. 為了做多個波疊加把上述的(1),(2)累加即可, 但是需要注意每次疊加改變下相位.
有了波面數據, 我們依舊可以使用Ray Marching的方法去渲染光照.
光照
光照用的Normal可以使用塑造波的方法加些許擾動完成波光細節. 使用Normal可以計算大致的光影效果. 但是水跟雲一樣, 也需要模擬散射效果. 關於水面反射, 可以使用常規IBL的方法, 但是海面不是室內, 通常就是天空, 所以我直接使用一個參數控制方便調效果. 另外為了真實, 使用Fresnel係數來做相關計算. 我用的是Schlick[5]模型:
此外還需要模擬一下次表面反射, 由於是海面, 相對簡單的平方衰減即可.
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學習教程
※計算機圖形學常用術語整理