2012-12-25 61 views
3

因此,在我正在建造的射線追蹤器中,我已經獲得折射以便與球體效應一起工作,但玻璃球體看起來並不特別好。我相信被折射的數學是正確的,因爲光看起來是按照你期望的方式反轉,但它看起來不像玻璃,它看起來像紙或其他東西。射線痕跡折射看起來「假」

我已經讀過全內反射是造成玻璃看起來像它的大部分原因,然而當我測試了我的折射光線是否超出臨界角度時,它們都沒有,所以我的玻璃球沒有全內反射。我不確定這是否正常,或者我做錯了什麼。我已經在下面張貼了我的折射代碼,所以如果有人有任何建議,我很樂意聽到他們。

/* 
* Parameter 'dir' lets you know whether the ray is starting 
* from outside the sphere going in (0) or from in the sphere 
* going back out (1). 
*/ 
void Ray::Refract(Intersection *hit, int dir) 
{ 

    float n1, n2; 
    if(dir == 0){ n1 = 1.0; n2 = hit->mat->GetRefract(); } 
    if(dir == 1){ n1 = hit->mat->GetRefract(); n2 = 1.0; } 

    STVector3 N = hit->normal/hit->normal.Length(); 
    if(dir == 1) N = -N; 
    STVector3 V = D/D.Length(); 
    double c1 = -STVector3::Dot(N, V); 
    double n = n1/n2; 

    double c2 = sqrt(1.0f - (n*n)*(1.0f - (c1*c1))); 

    STVector3 Rr = (n * V) + (n * c1 - c2) * N; 

    /*These are the parameters of the current ray being updated*/ 
    E = hit->point; //Starting point 
    D = Rr;   //Direction 
} 

我的主要射線追蹤法光線追跡()它運行遞歸過程中,此方法被調用。下面是它的一小部分低於負責折射:

if (hit->mat->IsRefractive()) 
    {  
     temp.Refract(hit, dir); //Temp is my ray that is being refracted 
     dir++; 
     result += RayTrace(temp, dir); //Result is the return RGB value. 
    } 

回答

5

你說的沒錯,你永遠不會在一個領域(從外面看)全內反射。這是因爲對稱性:球體內的射線會在兩端以相同的角度撞擊表面,這意味着如果超過一端的臨界角,則必須超過另一端的臨界角(所以從一開始就無法從外部進入球體)。

但是,你仍然會得到很多部分反射根據Fresnel's law。它看起來並不像你的代碼所說的那樣,這可能是你玻璃看起來很假的原因。嘗試包括這一點,看看是否有幫助。 (是的,這意味着當你的光線到達折射表面時,它們會分裂成兩部分,這是現實中發生的,所以你只需要忍受它,你可以追蹤兩條路徑,或者,如果你無論如何,我們都是使用隨機光線追蹤算法,只是用適當的權重對其中一個隨機抽樣。)

Ps。如果你不想處理光偏振等問題,你可能需要使用Schlick's approximation到菲涅耳方程。

+0

謝謝!我嘗試實施施裏克的逼近,我仍然有錯誤,但即使如此,我的球體看起來更像玻璃! =) – user1855952