(轉)GEM -次表面散射的實時近似

次表面散射(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變量爲環繞值,是一個範圍爲01之間的浮點數,用於控制光照環繞物體周圍距離。

環繞光照函數的圖表

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

做爲頂點的屏幕位置。程序簡單地把[01]範圍的紋理座標重映射爲[-11]的規範化的座標。

另外,爲了模擬吸取和散射與波長的相關的事實,能夠對每一個彩色通道分爲地改變濾波權重。

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

   

來自 <https://github.com/QianMo/Game-Programmer-Study-Notes/blob/master/Content/%E3%80%8AGPU%20Gems%201%E3%80%8B%E5%85%A8%E4%B9%A6%E6%8F%90%E7%82%BC%E6%80%BB%E7%BB%93/README.md#%E4%B8%80%E3%80%81-%E7%94%A8%E7%89%A9%E7%90%86%E6%A8%A1%E5%9E%8B%E8%BF%9B%E8%A1%8C%E9%AB%98%E6%95%88%E7%9A%84%E6%B0%B4%E6%A8%A1%E6%8B%9F%EF%BC%88effective-water-simulation-from-physical-models%EF%BC%89>

相關文章
相關標籤/搜索