光線追蹤技術 - 第二章 – Phone光照模型、鏡像和陰影


光線追蹤技術 - 第二章 – Phone光照模型、鏡像和陰影

Raytracing Topics & Techniques - Part 2 - Phong, Mirrors and Shadows

原作者:Jacco Bikker

原文地址:

http://www.flipcode.com/archives/Raytracing_Topics_Techniques-Part_2_Phong_Mirrors_and_Shadows.shtml

翻譯日期:2012年5月24日

引言

在第一章中,我介紹了光線追蹤的基礎知識:從攝像機發射一系列穿過屏幕到達場景的射線,找出每條射線最近的交點,然后用交點的法線點乘指向光源的向量得出一個簡單的漫反射陰影。

在第二章中,我將介紹Phone先生,他的衛生間的鏡子和他的背光面:)

主射線 VS 二級射線

考慮下面的這張圖:

clip_image002

圖一:主射線

這張圖展示了第一章中的簡單光線跟蹤器的射線發射到場景中的情形。一條射線可以與光源或一個物體碰撞,或者什么都沒有碰到。這些射線沒有反射和折射,它們被稱為“主射線”。

除主射線外,你可以使用“二級射線”。下面圖片展示了此種情況:

clip_image004

圖2:各種各樣的二級射線

圖中藍色的線是反射光線。對於反射來說,它簡單的從一個平面彈回來。稍后會介紹如何計算它。

綠色的線是折射光線。它比反射光線要難計算一些,但也是可以計算的。計算它需要知道折射率和一個由Snell先生(Willebrord Snellius)制定的公式。

紅色的線用來探測光源。簡單來說,當計算漫反射光照時,如果光源對交點可見,則將點積乘以1,如果被阻擋則乘以0,如果有一般光源可見,則乘以0.5。(譯者注:這段話是要解決光源不是一個點的情況。當光源具有一定體積時,就可能出現光源被遮擋不完全的狀況。此時,用第一章中講的點乘的方式計算出來的這一點的光照強度,需要根據遮擋的情況做調整,需要將計算結果乘以光源沒有被遮擋的部分所占的百分比。)

如果你從攝像機開始,沿着一條黃色線出發,你會注意到每條射線都產生了一整套二級射線:一條反射射線、一條折射射線和每個光源的陰影射線。當生成以后,每條二級射線(除了陰影射線)都被看作是一條普通射線。這意味着一條反射射線可以被再次反射、第三次反射、第四次反生......這種技術被稱為“遞歸光線跟蹤”。每一條新的射線都會講它的顏色匯集到它上一級的射線中去,這樣,每條射線都會影響到主射線穿過的這個像素點(屏幕上的一個像素)的最終顏色。

為使遞歸循環可以結束和避免花費過多渲染時間,通常我們會設置一個值來限制遞歸的深度。

反射

通過法線計算反射射線,可以使用下面的公式:

R = V - 2 * DOT( V, N ) * N;

(R是反射射線,V是入射射線,N是平面法線)

下面的代碼可以添加到光線追蹤器中為每個光源計算漫反射光照的循環中去。

// calculate reflection

float refl = prim->GetMaterial()->GetReflection();

if (refl > 0.0f)

{

vector3 N = prim->GetNormal( pi );

vector3 R = a_Ray.GetDirection() - 2.0f * DOT( a_Ray.GetDirection(), N ) * N;

if (a_Depth < TRACEDEPTH)

{

Color rcol( 0, 0, 0 );

float dist;

Raytrace( Ray( pi + R * EPSILON, R ), rcol, a_Depth + 1, a_RIndex, dist );

a_Acc += refl * rcol * prim->GetMaterial()->GetColor();

}

}

 

如果你沒有更改光線追蹤器的場景,你會看到下面的圖像:

clip_image006

這是一個很大的進步。球體間互相映現,此外,球體也映現出地面。

Phone光照模型

創建一個“完美的”光照模型是非常復雜的,所以我們取真實光照的近似值。到目前為止,我們使用的漫反射光照模型很好的表現了看起來比較柔和的物體,但是對於有光澤的物體的表現還不夠。換言之,現在的光照模型除了光強之外,我們什么都控制不了。

clip_image010clip_image008看一下下面的圖:

圖3:漫反射與鏡面反射對比

左側圖片展示了我們目前使用的光照模型:光源向量與法線的點積。它從黑到白是線性變換的。

右側圖片展示的也是同樣的點積,但是這次將冪指數提高到50。這次,在兩個向量夾角很小的時候,會出現亮斑。隨着角度增大,亮度快速下降到零。

組合這些改進是很重要的:我們得到了想當的靈活性。一個材質可以具有漫反射陰影和鏡面反射陰影;我們可以通過調整冪指數來改變高光區域的大小。

這還不是很正確。

漫反射陰影是正確的:漫反射材質在所有方向上散射光線,所以最亮的區域應該是在面對光源的地方。可以通過法線與光源方向的向量做點乘來計算這個結果。

鏡面反射則有一些不同:簡單來說,鏡面反射是對光源的反射。你可以在真實世界中檢查這個現象:找一個有光澤的物體,把它放到在一個燈光下的桌子上,然后移動你的頭。你會注意到當你移動的時候高光區域並不是停留在物體的同一個區域:高光區域就是對光源的反射,它隨着視角的變化而變化。Phone建議下面的光照模型,這個模型將反射向量包括在其中:

intensity = diffuse * (L.N) + specular * (V.R)n

(L是從交點到光源的向量,N是交點的法線,V是觀察的方向向量, R是L在交點上的反射向量)(譯者注:上式中最后的n為n次冪,n是冪指數)

注意這個公式包含了漫反射和鏡面反射光照模型。

下面是代碼實現:

vector3 V = a_Ray.GetDirection();

vector3 R = L - 2.0f * DOT( L, N ) * N;

float dot = DOT( V, R );

if (dot > 0)

{

float spec = powf( dot, 20 ) * prim->GetMaterial()->GetSpecular() * shade;

// add specular component to ray color

a_Acc += spec * light->GetMaterial()->GetColor();

}

 

將這些代碼加入光照計算中后,光線渲染器會渲染出如下效果的圖片:

clip_image012

畫面又是一個很大的進步。

陰影

最后一種二級射線是陰影射線。這跟其它的射線有一些不同:它們不直接向產生他們的射線提供顏色信息;它們是用來檢測一個光源是否可以“看到”這個交點。這個測試的結果被用在漫反射和鏡面反射的計算中。

下面的代碼為每個光源創建一條陰影射線,然后把這些射線與場景中的其他物體做相交測試。

// handle point light source

float shade = 1.0f;

if (light->GetType() == Primitive::SPHERE)

{

vector3 L = ((Sphere*)light)->GetCentre() - pi;

float tdist = LENGTH( L );

L *= (1.0f / tdist);

Ray r = Ray( pi + L * EPSILON, L );

for ( int s = 0; s < m_Scene->GetNrPrimitives(); s++ )

{

Primitive* pr = m_Scene->GetPrimitive( s );

if ((pr != light) && (pr->Intersect( r, tdist )))

{

shade = 0;

break;

}

}

}

 

大部分的代碼應該很熟悉了。測試的結果存儲在一個浮點型的變量“shade”中:值為1表示一個可見的光源,0表示不可見。用一個浮點型來表示看起來很奇怪;我們以后將會加入區域光源,它們通常只有一部分是可見的。在那種情況下,“shade”就會在0-1之間取值了。

另外,上面的代碼沒有檢測在陰影射線上與其交點最近的物體。因為不需要這樣做:只要檢測到比光源近的任意一個交點就可以。這是一個很重要的優化,這樣做可以盡快結束交點檢測部分的循環。

圖片:

clip_image014

這是最終效果。兩個球體,鏡像,漫反射和鏡面反射,兩個光源引起的陰影。平面上的光照小時在遠方,是因為遠處的漫反射點積越來越小,球體的光照很好。所有這些在一秒鍾就可以渲染完成。

注意觀察平面上的陰影的表示,陰影是怎樣使平面的謀一部分變為全黑的。還要注意觀察球體的顏色是怎樣影響被鏡像到球體表面的平面的顏色。

結尾

光線追蹤的一個有意思的地方是,你可以向其中插入新東西,其他的東西照常運行。例如,添加陰影和Phong光照模型的同時加入了鏡像和高光。這跟光線追蹤的平行性質有關:每個射線之間是沒有關聯的,這使得遞歸光線追蹤非常適合在多處理器上渲染,同時也非常適合組合多種多樣的算法。

另外,在目前的光線追蹤器中有一個錯誤,我會在第三版本中修正:陰影射線測試的結果被同時使用在漫反射和鏡面反射上。這顯然是錯誤的。:)

這就是第二章的全部了。下一章:折射、貝爾定律和動態超級采樣。

第二版本的光線渲染器可以通過以下鏈接下載:

http://115.com/file/c2ct7jke#raytracer2.zip


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM