次表面散射(Subsurface Scattering),簡稱SSS,或3S,是光射入非金屬材質後在內部發生散射, git
最後射出物體並進入視野中產生的現象, github
即光從表面進入物體通過內部散射,而後又經過物體表面的其餘頂點出射的光線傳遞過程。 app
圖 次表面散射原理圖示 函數
圖 真實環境中的次表面散射 編碼
要產生令人信服的皮膚和其餘半透明材質的渲染效果,次表面散射(Subsurface Scattering)的 spa
渲染效果十分重要。 3d
圖 有無次表面散射的渲染對比圖(左圖:使用次表面散射 | 右圖:無次表面散射) orm
另外須要提出,在《神祕海域4》中皮膚的渲染效果,很使人驚豔。固然,《神祕海域4》中 blog
使人驚豔的,遠遠不止皮膚的渲染。 索引
圖 基於次表面散射的皮膚渲染 @《神祕海域4》
本章即描述了次表面散射的幾種實時近似方法,關於皮膚的渲染,也關於近似地去模擬透明材
質的幾種不一樣方法。
【核心內容提煉】
4.1 次表面散射的視覺特性(The Visual Effects of Subsurface Scattering)
要重現出任何視覺效果,常常的作法是考察這種效果的圖像,並把可視的外觀分解爲其組成要
素。在觀察半透明物體的相片和圖像時,能注意到以下幾點,即次表面散射(Subsurface Scattering)的視覺特性:
1、首先,次表面散射每每使照明的總體效果變得柔和。
2、一個區域的光線每每滲透到表面的周圍區域,而小的表面細節變得看不清了。
3、光線傳入物體越深,就衰減和散射得越嚴重。
4、對於皮膚來講,在照亮區到陰影區的銜接處,散射每每會引發微弱的傾向於紅色的顏色偏移。
這是因爲光線照亮表皮並進入皮膚,接着被皮下血管和組織散射和吸取,而後從陰影部分離開。
且散射在皮膚薄的部位更加明顯,好比鼻孔和耳朵周圍。
圖 次表面散射原理圖示
4.2 簡單的散射近似(Simple Scattering Approximations)
近似散射的比較簡單技巧是環繞照明(Warp Lighting)。正常狀況下,當表面的法線
對於光源方向垂直的時候,Lambert漫反射提供的照明度是0。而環繞光照修改漫反
射函數,使得光照環繞在物體的周圍,越過那些正常時會變黑變暗的點。這減小了漫
反射光照明的對比度,從而減小了環境光和所要求的填充光的量。環繞光照是對Oren-Nayar
光照模型的一個粗糙的近似。原模型力圖更精確地模擬粗糙的不光滑表面(Nayar and Oren 1995)。
下圖和代碼片斷顯示瞭如何將漫反射光照函數進行改造,使其包含環繞效果。
其中,wrap變量爲環繞值,是一個範圍爲0到1之間的浮點數,用於控制光照環繞物體周圍距離。
圖 環繞光照函數的圖表
float diffuse = max(0, dot(L, N));
float wrap_diffuse = max(0, (dot(L, N) + wrap) / (1 + wrap));
爲了在片元函數程序中的計算能夠更加高效,上述函數能夠直接編碼到紋理中,用光線
矢量和法線的點積爲索引。
而在照明度接近0時,能夠顯示出那種傾向於紅的微小顏色漂移,這是模擬皮膚散射的
一種廉價方法。而這種偏向於紅色的微小顏色漂移,也能夠直接加入到此紋理中。
另外也能夠在此紋理的alpha通道中加入鏡面反射高光光照的功率(power)函數。
能夠在示例代碼Example 16-1中的FX代碼展現瞭如何使用這種技術。對比的圖示以下。
圖 (a)沒有環繞光照的球體 (b)有環繞光照明的球體 (c)有環繞光照明和顏色漂移的球體
Example 16-1 摘錄歸入了環繞照明的皮膚Shader效果的代碼(Excerpt from the Skin Shader
Effect Incorporating Wrap Lighting)
// 爲皮膚着色生成2D查找表(Generate 2D lookup table for skin shading)
float4 GenerateSkinLUT(float2 P : POSITION) : COLOR
{
float wrap = 0.2;
float scatterWidth = 0.3;
float4 scatterColor = float4(0.15, 0.0, 0.0, 1.0);
float shininess = 40.0;
float NdotL = P.x * 2 - 1; // remap from [0, 1] to [-1, 1]
float NdotH = P.y * 2 - 1;
float NdotL_wrap = (NdotL + wrap) / (1 + wrap); // wrap lighting
float diffuse = max(NdotL_wrap, 0.0);
// 在從明到暗的轉換中添加顏色色調(add color tint at transition from light to
dark)
float scatter = smoothstep(0.0, scatterWidth, NdotL_wrap) *
smoothstep(scatterWidth * 2.0, scatterWidth,
NdotL_wrap);
float specular = pow(NdotH, shininess);
if (NdotL_wrap <= 0) specular = 0;
float4 C;
C.rgb = diffuse + scatter * scatterColor;
C.a = specular;
return C;
}
// 使用查找表着色皮膚(Shade skin using lookup table)
half3 ShadeSkin(sampler2D skinLUT,
half3 N,
half3 L,
half3 H,
half3 diffuseColor,
half3 specularColor) : COLOR
{
half2 s;
s.x = dot(N, L);
s.y = dot(N, H);
half4 light = tex2D(skinLUT, s * 0.5 + 0.5);
return diffuseColor * light.rgb + specularColor * light.a;
}
4.3 使用深度貼圖模擬吸取(Simulating Absorption Using Depth Maps)
吸取(Absorption)是模擬半透明材質的最重要特性之一。光線在物質中傳播得越遠,
它被散射和吸取得就越厲害。
爲了模擬這種效果,咱們須要測量光在物質中傳播的距離。
而估算這個距離可使用深度貼圖(Depth Maps)技術[Hery 2002],此技術很是相似
於陰影貼圖(Shadow Mapping),
並且可用於實時渲染。
圖 使用深度貼圖計算光在物體中的傳播的距離
深度貼圖(Depth Maps)技術的思路是:
在第一個通道(first pass)中,咱們從光源的視點處渲染場景,存儲從光源到某個紋理的距離。
而後使用標準的投射紋理貼圖(standard projective texture mapping),將該圖像投射回場景。
在渲染通道(rendering pass)中,給定一個須要着色的點,咱們能夠查詢這個紋理,來得到
從光線進入表面的點(d_i)到光源間距離,經過從光線到光線離開表面的距離(d_o)裏減去
這個值,咱們即可以得到光線轉過物體內部距離長度的一個估計值(S)。如上圖。
原文中詳細分析了此方法的實現過程,也附帶了完整的Shader源碼,具體細節能夠查看原文,
這裏由於篇幅緣由就不展開了。
圖 使用深度貼圖去近似散射,物體上薄的部位傳輸更多的光
也有一些更高端的模型試圖更精確地模擬介質內散射的累積效應。
一種模型是單次散射近似(Single Scattering Approximation),其假設光在材質中只
反彈一次,
沿着材質內的折射光線,能夠計算有多少光子會朝向攝像機散射。當光擊中一個粒子
的時候,
光散射方向的分佈用相位函數來描述。而考慮入射點和出射點的菲涅爾效應也很重要。
另外一種模型,是近似漫反射(Diffusion Approximation),其用來模擬高散射介質(如皮
膚)的屢次散射效果。
4.4 紋理空間的漫反射(Texture-Space Diffusion)
次表面散射最明顯的視覺特徵之一是模糊的光照效果。其實,3D美術時常在屏幕空間中
效仿這個現象,經過在Photoshop中執行Gaussian模糊,而後把模糊圖像少許地覆蓋在
原始圖像上,這種"輝光"技術使光照變得柔和。
而在紋理空間中模擬漫反射[Borshukov and Lewis 2003],即紋理空間漫反射(Texture-S
pace Diffusion)是可能的,咱們能夠用頂點程序展開物體的網格,程序使用紋理座標UV
做爲頂點的屏幕位置。程序簡單地把[0,1]範圍的紋理座標重映射爲[-1,1]的規範化的座標。
另外,爲了模擬吸取和散射與波長的相關的事實,能夠對每一個彩色通道分爲地改變濾波權重。
圖 (a)原始模型 (b)應用了紋理空間漫反射照明的模型,光照變得柔和
圖 基於紋理空間漫反射照明的效果
一樣,原文中詳細分析了此方法的實現過程,也附帶了完整的Shader源碼,具體細節
能夠查看原文,這裏由於篇幅緣由就不展開了。
再附幾張基於次表面散射的皮膚渲染效果圖,結束這一節。
圖 基於次表面散射的皮膚渲染
圖 基於次表面散射的皮膚渲染 @Unreal Engine 4
圖 基於次表面散射的皮膚渲染 @《神祕海域4》
圖 基於次表面散射的皮膚渲染 @《神祕海域4》
【核心要點總結】
文中提出的次表面散射的實時近似方法,總結起來有三個要點:
1) 基於環繞照明(Warp Lighting)的簡單散射近似,Oren-Nayar光照模型。
2) 使用深度貼圖來模擬半透明材質的最重要特性之一——吸取(Absorption)。
3)基於紋理空間中的漫反射模擬(Texture-Space Diffusion),來模擬次表面散
射最明顯的視覺特徵之一——模糊的光照效果。
【本章配套源代碼彙總表】
Example 16-1 摘錄歸入了環繞照明的皮膚Shader效果的代碼
(Excerpt from the Skin Shader Effect Incorporating Wrap Lighting)
Example 16-2 深度Pass的頂點Shader代碼
(The Vertex Program for the Depth Pass)
Example 16-3 深度Pass的片元Shader代碼
(The Fragment Program for the Depth Pass)
Example 16-4 使用深度貼圖來計算穿透深度的片元Shader代碼
(The Fragment Program Function for Calculating Penetration Depth Using Depth Map)
Example 16-5 用於展開模型和執行漫反射光照的頂點Shader代碼
(A Vertex Program to Unwrap a Model and Perform Diffuse Lighting)
Example 16-6 用於漫反射模糊的頂點Shader代碼
(The Vertex Program for Diffusion Blur)
Example 16-7 用於漫反射模糊的片元Shader代碼
(The Fragment Program for Diffusion Blur)
【關鍵詞提煉】
皮膚渲染(Skin Rendering)
次表面散射(Subsurface Scattering)
紋理空間漫反射(Texture-Space Diffusion)
環繞照明(Warp Lighting)
深度映射(Depth Maps)