UnityShader 挺進體積光

2021-08-07 07:57:55 字數 3273 閱讀 2615

原本是想找找體積霧的,無意中發現了 gpu gems 3上的一篇螢幕特效實現體積光散射的文章,實現了一波發現文章裡公式列的很高大上,結果具體實現卻出乎意料的簡單,只是通過畫素的螢幕位置和光源的螢幕位置計算光線方向,然後在乙個迴圈中沿光線方向將上乙個畫素的顏色衰減後疊加到下乙個畫素,具體可參考 gpu gems 原文,在 unity 中效果如下:

週末又在github發現乙個500多星星的體積光,專案主要參考了 gpu pro 5 上的乙個體積光實現方法,效果很棒,忍不住下下來研究了一下

我們從最簡單並具有代表性的一種情況入手,即當相機在點光源範圍外的時候,效果如上圖所示,通過繪製乙個和點光源範圍一樣的球,通過raytrace的方法遍歷球中的位置並計算其光照,raytrace 路徑如圖所示,我們只需要遍歷光線在球內部的位置:

實際用使用的**如下:

float3 raystart = _worldspacecamerapos;

float3 rayend = i.wpos;

float3 raydir = (rayend - raystart);

float raylength = length(raydir);

raydir /= raylength;

float3 lighttocamera = _worldspacecamerapos - _lightpos;

float b = dot(raydir, lighttocamera);

float c = dot(lighttocamera, lighttocamera) - (_volumetriclight.z * _volumetriclight.z);

float d = sqrt((b*b) - c);

float start = -b - d;

float end = -b + d;

光看**有點不好理解,示意圖如下:

我們以

c 表示相機所在點,

l表示點光源所在點,根據上面**我們可以看出, −b

=ca

, c=c

l2−d

l2 ,

d2=b

2−c=

ca2−

cl2+

dl2=

dl2−

(cl2

−ca2

)=dl

2−la

2=bl

2−la

2=ab

2 故d

=ab (上面的計算完全就當高中幾何算了就沒管方向了)

因此,在點光源範圍內沒有遮擋物的情況下 -b-d 和 -b+d 分別就是raytrace的起點和終點,再通過 _cameradepthtexture 計算遮擋物位置並與當前的 end 做比較取最小值,然後,我們就可以做 raytrace了,對於點光源,光照計算較為簡單,光線的衰減 unity 已經幫我們算好了,其具體實現在 wiki 中也有,然後是陰影,對於點光源,其 shadowmap 以 texcube 的形式儲存, unityshadowlibrary.cginc 檔案中,我們可以看到其實現:

#if defined (shadows_cube)

samplercube_float _shadowmaptexture;

inline float samplecubedistance (float3 vec)

inline half unitysampleshadowmap (float3 vec)

#endif // #if defined (shadows_cube)

github 中的專案選擇了手動計算衰減,而實際上我們直接使用 unity_light_attenuation 巨集也可以達到一樣的效果,在這個衰減的基礎上,我們可以再手動加上乙個衰減係數方便效果調整。

然後是散射,我們之所以能看見「體積光」就是因為光線在介質中發生了散射,在點光源中,我們可以簡單的設定乙個係數來決定raytrace的每一步有多少光源散射到了攝像機方向,到了這一步,我們便可以得到下面的結果:

圖中的結果是直接在光源位置放置了乙個等大小的 sphere,但實際上還存在乙個很大的問題,要產生陰影,我們則不能將其渲染佇列設定為透明,但在 geometry 的渲染佇列繪製,如果我們渲染天空盒,則體積光便會被天空盒覆蓋掉,如圖所示:

把渲染佇列調整至 transparent 之後則是這樣的:

因此,github 中的專案使用了 commandbuffer 在 unity 渲染完 shadowmap 後,繪製不透明物體之前繪製體積光的sphere 並將rendertarget 設定為自定義的 rendertexture,最後再通過imageeffect的方式,將體積光混合到當前的 framebuffer 中

當然,上面提到的都是專案中比較基礎的部分,github 專案中還使用了 deithered offset 的方法來使 raytrace 的取樣更加均勻,可以在使用更少的步數的情況下,達到更好的效果

以及先降取樣再通過模糊和超取樣還原的方法來減少運算量

這裡不再一一分析,有興趣的可以檢視 gpu pro 原文或者閱讀 github 的專案原始碼

to be continue… or not

UltraEdit挺進linux世界

如果ultraedit能夠挺進linux世界,其實是開源社群的福音。乙個作業系統如果要求它的使用者都是中高階使用者,它必然滅亡。別人ultraedit,抓住的就是初級使用者和中級使用者。比如乙個幾g的檔案吧,有人說還開啟它幹嘛,的確,有經驗的使用者用awk sed grep more less能處理...

2023年 Ubuntu挺進中國

至今,ubuntu 進入中國已經 5 年多了,但是,實際應用的廣度和深度都不甚理想,沒有達到預期。今年將會有明顯的變化。此話當真?有何根據?今年 4 月,ubuntu 發行版的第三個 lts 長期支援 版本 ubuntu 10.04 將要正式發布。實際上,這是乙個具有歷史標誌性的 ubuntu 重要...

再次向逆向工程挺進

加密與解密買了半年了。剛開始的時候由於前期基礎積累不夠看的時候遇到很大的困難。前幾天尋思著現在有了windows程式設計的基礎再看應該容易不少,再加上現在時間很充裕,於是又開始了逆向工程的學習。才開始學習大概有一周的時間,熟悉了幾款常用的逆向工程的軟體像peid,ollydbg,ida.ollydb...