天天看點

關于Wrap Lighting與皮膚SSS

最近在弄手機上的SSS皮膚,查資料的時候碰到Wrap Lighting這個概念,這裡簡單總結一下。

這個說白了就是Half Lambert的進階版,或者說Half Lambert是Wrap Lighting的一個特例。Wrap Light直譯的話就是用光包裹住整個物體,讓原來黑暗(即N*L<=0)的部分亮起來的意思。如果是标準Lambert的話,有很大一部分地方是黑的,讓整個物體顯得比較平,而Wrap Light會有一個光的過度,并且"soft“整個物體的感覺。如下圖:

關于Wrap Lighting與皮膚SSS

圖檔引用自Valve的Half Life 2引擎技術分享,最右邊的上下兩張圖可以看出來,使用Half Lambert效果更好一點。

Wrap Light公式為:

float diffuse = max(0, dot(L, N));
float wrap_diffuse = max(0, (dot(L, N) + wrap) / (1 + wrap));      

是以Half Lambert相當于wrap值為1的情況,具體項目中,wrap值會按照美術的感覺來走。

早期的皮膚材質就是用這樣的方法來制作的,并沒有什麼道理可講,就是粗暴的覺得這樣很好看而已。其中還包括,使用wrap後的N*L來去采樣一個一維的貼圖,類似下面的圖:

關于Wrap Lighting與皮膚SSS

下面的圖是使用效果,C圖就是用了這樣的采樣貼圖:

關于Wrap Lighting與皮膚SSS

在黑白交接的地方給一點紅色,用于模拟皮膚的感覺,這個也是現實中出現的情況。是以最後diffuse的公式變成了wrap後的N*L再加上這個采樣過後的Scatter數值,或者直接是用采樣後的數值作為diffuse數值(當然這個采樣貼圖本身需要好好制作)。具體公式每個遊戲都不一樣,但是原理就是這樣:使用Wrap Light的Diffuse。

這樣的算法還是很實用的,但是在現在,已經有點不夠用了,其中原因有:在PBR大行其道的今天,這種完全沒有能量守恒的算法會讓整個物體過于明亮,是以有大牛就據此修改了Wrap Light,讓其保證能量守恒:

http://blog.stevemcauley.com/2011/12/03/energy-conserving-wrapped-diffuse/

并且,在現如今都使用SH作為環境光的情況下,環境光如何使用Wrap Light呢:

http://blog.selfshadow.com/2011/12/31/righting-wrap-part-1/

還有,如果這個算法是用于模拟皮膚的SSS效果的話,并沒有考慮到真正的skin diffusion profiles和皮膚表面的curvature,僅僅是看起來有點像的樣子,這些都需要進行修改:

http://advances.realtimerendering.com/s2011/Penner%20-%20Pre-Integrated%20Skin%20Rendering%20%28Siggraph%202011%20Advances%20in%20Real-Time%20Rendering%20Course%29.pptx

上面這篇文章是在Forward Rendering的情況下如何做皮膚SSS的,和大行其道的後處理SSSSS并不一樣,效果也還不錯,Order 1886,NV的Facework插件均使用了這個算法。

引用:

1. https://developer.nvidia.com/gpugems/GPUGems/gpugems_ch16.html

2. http://www.valvesoftware.com/publications/2006/SIGGRAPH06_Course_ShadingInValvesSourceEngine.pdf

繼續閱讀