原文地址:http://filmicgames.com/archives/233
上篇文章講到所有物體都是有光澤的,那么這篇文章作者將展示如何從圖片中分離漫反射和高光信息。
你可能以為接下來的這些東西會比較困難,但是它實際上並沒有你想你的困難。我在家做的一件事情就是使用偏振光來把漫反射和高光從真實圖像中分離出來。美工(Artists)會花很多時間在看參照圖片,但是通過分離漫反射和高光能幫助你理解什么是材質。在上面的圖中,左邊是只有漫反射光照,中間是帶有漫反射和高光,右邊的是只有高光的。順便說一句,我並不是這方面的專家,但是這就是我如何理解它的。
-
原始圖像:
-
漫反射:
-
高光:
如果你想要自己去做分離這件事,那么你需要:
- 一個可以手動拍照的相機。比如單反。
- 一個遠程快門控制器,這樣你就可以不用碰相機就來拍攝多張照片。
- 一個光源,我使用了一個宜家的燈。
-
一些偏振片。我從 polarization.com購買。你需要"完全層疊線性偏振片"。確保你用的是線性偏振器,而不是圓偏振器。
在最基礎的以層面,在圖形學中我們假設物體都有漫反射的高光反射。下圖 是一個光源照射表面,旁邊有一個相機 。順便說一句,這個模型是一個非常大的簡化。
其中到達表面的一些光會離開表面。如果有一個白色光源和一個藍色的表面,那么反射的光還是白色的,我們稱它為高光。
其它的一些光會被 表面吸收,一些電子會被激活,並且一個新的光子會沿一個隨機方向發射。如果 我們有一個白色的光源和一個藍色的表面,那么出射的光會是藍色的,我們稱它為漫反射。
希望你已經理解這些。如果先前不了解,那么你現在應該了解了。特別酷的一件事情是光可以被偏振。你可以從你的好朋友wikipedia(國內請自行百度或者谷歌偏振)另外,高光會保持它進入時的偏振,但是漫反射不會。因為漫反射光在隨機方向重新傳播的,並且伴隨隨機偏振,我們可以說它是非偏振的。
下面是所需的設置:
很簡單,我把相機所有的全部調到手動模式,這意味着:
- 手動曝光
- 手動調節光圈
- 手動調節白平衡
- 手動調節ISO
- 關閉自動對焦
-
確保顏色配置是sRGB而不是Adobe 98
你還需要有一個遠程快門控制器。這樣就可以不碰相機來拍攝多張照片。如果 你必須碰相機來拍攝,那么我確信出現不對准的情況。並且我們需要一個光源,讓我們來瞧瞧它。
它就是一個宜家鹵素燈,但是前面放了一個偏振片。我使用磁帶來固定它。作為警告,燈會變得非常熱,因此偏振處已經有點變形了。
我們要做的就是拍攝兩張照片。但是我將需要把一個偏振片放到相機前面。注意我們的相機和光源上都有一個偏振片。如果你覺得我是一個從洛杉磯來的游戲程序員,那么你就錯了。它只是 我用來付房租的,在我追求成為一個手部模特夢想的時候(玩笑)。
注意到偏振片上的橙色膠帶沒有?我現在將要把它旋轉90度再拍另外一張。看這個橙色的膠帶已經移動了。
下面是我們第一張拍攝的照片的樣子。如果你的對齊完美的話,那么應該沒有高光信息。當然,多少會有一點,因為通過手動對齊偏振片是基本不可能的。
它是如何工作的?偏振光達到 表面,高光從表面反射並且射向相機。它到達跟偏振光垂直的偏振器,因此它完全被吸收。同時 ,漫被吸收並且重新傳輸的反射光是非偏振的。偏振光吸收了一半的漫反射光,余下的部分進入了相機。因此圖片中有一半的漫反射但沒有高光信息。現在來看第二圖。
在上面這張圖中,偏振的高光到達跟它平行的偏振器,因此所有的光都通過了。同時漫反射不是非偏振光,所有 它其中的一半被吸收。它有一半的漫反射和所有的高光信息。
如果 我們把第一張圖約定為A,第二張圖約定為B,那么漫反射就是2*A,而高光就是B-A。當然這些圖片是存儲在sRGB空間的。因此這里我們需要使用Shader代碼來比較這兩幅圖片,並且把它們 分開,並且把結果再存儲為一張sRGB圖片。跟往常一樣,代碼沒有被測試過。
1 float LinearToSrgb(float val) 2 { 3 float ret; 4 if (val <= 0.0) 5 ret = 0.0f; 6 else if (val <= 0.0031308f) 7 ret = 12.92f*val; 8 else if (val <= 1.0f) 9 ret = (pow(val, 0.41666)*1.055f)-0.055f; 10 else 11 ret = 1.0f; 12 return ret; 13 } 14 15 float SrgbToLinear(float val) 16 { 17 float ret; 18 if (val <= 0.0f) 19 ret = 0; 20 else if (val <= 0.04045f) 21 ret = val / 12.92f; 22 else if (val <= 1.0f) 23 ret = pow((val + 0.055f)/1.055f,2.4f); 24 else 25 ret = 1.0f; 26 return ret; 27 } 28 29 int g_bSpecOrDiff; 30 31 float4 ps_main( float2 texCoord : TEXCOORD0 ) : COLOR 32 { 33 float3 srcA = tex2D(Texture0, texCoord ).rgb; 34 float3 srcB = tex2D(Texture1, texCoord ).rgb; 35 float3 linA = SrgbToLinear(srcA); 36 float3 linB = SrgbToLinear(srcB); 37 float3 linDiff = linA*2; 38 float3 linSpec = linB-linA; 39 float3 texDiff = LinearToSrgb(linDiff); 40 float3 texSpec = LinearToSrgb(linSpec); 41 float3 ret = g_bSpecOrDiff ? texDiff : texSpec; 42 return ret; 43 }
如果你上面做的全部正確的族,那么漫反射圖片應該是看起來這個樣子的
高光圖片應該是這樣的:
正如你所看到的,這個過程並不完美。
- 在漫反射圖片中多少會有一些高光信息。
- 一些物體表現得不是很好 。在只有高光的圖片中,手柄處有一些偏藍。我覺得是手柄是非導體導致頻率有一些擾亂。
- 如果 高光或者漫反射被截斷到1.0,那么這些像素就不對了。最好是曝光不足而不是曝光過度。
- 確保你使用一個遠程快門控制器,否則你會有對齊的問題。
希望不是太麻煩,你可以自己來分離高光和漫反射了。