GPU Gems1 - 2 水刻蚀的渲染
2.1 引言
光線從彎曲的表面反射或折射,因此只聚焦在受光面上的某些區(qū)域,于是就產(chǎn)生了刻蝕現(xiàn)象。本文從美學(xué)角度出發(fā),不以純物理的方式計算,使其很容易在大多數(shù)圖形硬件上實現(xiàn),效果又十分逼真。
2.2 刻蝕的計算
如果想正確地計算水下的刻蝕,是一個復(fù)雜的過程:這涉及到數(shù)目龐大的光線及其相互作用。為了模擬這一過程,必須從光源射出光子作為開始,一部分光子碰到海面,或者反射或者折射。對于折射部分,按照Snell折射定律:
用該公式編程很不容易,可以將公式變形為一個更容易編程的形式,例如Foley等人1996年提出的:
光子一旦入水后,即發(fā)生折射并繼續(xù)前進,隨著入水的深度增加光強度會衰減,最后一些光子會碰到海底并將其照亮。由于海面的波紋,經(jīng)過不同路徑入水的光線,可能最終照到海底相同的區(qū)域,每當(dāng)這個現(xiàn)象發(fā)生時,在刻蝕中的聚集光線就會形成明亮的光斑,類似于透鏡的聚光現(xiàn)象。
刻蝕其實可以通過正向或逆向光線跟蹤計算。在正向光線跟蹤中,要跟蹤從光源射出并穿過場景的光線,累計其在不連續(xù)地區(qū)的貢獻。逆向光線跟蹤,則以相反的過程工作。它從海底開始,按照與入射光線相反的順序逆向跟蹤光線,計算給定點的所有入射光線綜合。但是無論是正向光線跟蹤計算,還是逆向跟蹤計算,都非常費時,因為只有極小部分的計算對最終結(jié)果有實際意義。
2.3 方法
本文采用的方法,是逆向光線跟蹤的一個簡化。我們只計算到達海底光線的一個子集,該子集就是只計算垂直與地面的光線,因為那些從入水到碰上海底面,傳播距離最短的光線,才會最容易形成刻蝕。這種方法計算消耗非常少,盡管物理上不“”正確“”但是非常逼真。
我們的算法如下。從海底開始,繪制海底地面后,使用第二次混合疊加渲染來渲染刻蝕。為了這樣做,我們創(chuàng)建一個與水網(wǎng)格尺寸相同的海底網(wǎng)格,并且用刻蝕值對其逐頂點地著色。為了創(chuàng)建光照,采用逆向光線跟蹤:從海底網(wǎng)格的每個頂點,垂直地向上發(fā)射光線,一直到達正好位于哪個頂點之上的水波點。然后,使用有線差分計算那個點的海面波的法線。有了矢量和法線,使用Sneel公式,創(chuàng)建出從水波射向空氣的第二級光線。我們再計算每條光線和垂直線的夾角,愈靠近垂直的方向,那個方向進入大海的光線就越多。
2.4 使用OpenGL實現(xiàn)
使用兩個pass,第一次渲染使用一個普通紋理渲染還地面。然后第二個pass通過刻蝕算法,逐一照亮海底網(wǎng)格的頂點。
2.5 使用高級著色語言實現(xiàn)
先前OpenGL實現(xiàn)中,是在CPU上執(zhí)行的波函數(shù)。現(xiàn)在可以采用逐像素法代替逐頂點法,全面的提高了視覺質(zhì)量。
關(guān)于法線的計算,不像前面提到的使用有線差分方法,我們考慮了兩種方法,他們都使用波函數(shù)的偏導(dǎo)產(chǎn)生法線:
1.在屏幕空間可以渲染過程紋理,當(dāng)只有小部分像素看的見時,這個方法可以節(jié)省渲染時間,但是也意味著當(dāng)有很多像素看得見時,對每個像素都要做同樣多的工作,這些大量的工作顯然要減小幀率。
2.在紋理空間中渲染一個分辨率固定的渲染目標(biāo)貼圖,在紋理空間中渲染,能夠固定每幀的工作量,這是一個優(yōu)越性,但是卻丟掉了一個好處,不能只渲染看的見的像素了。另外,也很難決定使用多大分辨率對當(dāng)前場景合適。
我們可以進一步優(yōu)化運算,一是使用Snell定律對入射光線的折射,二是簡單的基于從水面到水底的距離,沿著波法線進行的環(huán)境映射。結(jié)果,穿過紋理中心的垂直光線是明亮的,而夾角光線則逐漸衰弱。而且,深度越大,環(huán)境反射貼圖的相對尺寸越小,因為刻蝕會隨距離而衰減,所以產(chǎn)生的刻蝕也約細(xì)。
核心點總結(jié)
- 簡化的反向光線追蹤
- 光照環(huán)境貼圖映射
總結(jié)
以上是生活随笔為你收集整理的GPU Gems1 - 2 水刻蚀的渲染的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: GPU Gems1 - 1 用物理模型进
- 下一篇: 微服务-高并发情况下接口降级和熔断策略