2016-06-13 144 views
1

我寫了一個光線追蹤程序(目前)有兩個表面照明選項:環境和反射。環境照明覆制自然表面如何散射光線。反射明顯地重現了鏡子如何反射光線。一切工作正常,但我無法弄清楚如何混合顏色與光澤反射。Java:光線追蹤:光澤反射着色

反射算法返回一個顏色並遞歸地工作。光線是以參數化線的形式「投射」的。當他們擊中反射表面時,他們完美地反彈(以及我的工作方法)。然後將這些反射光線用作再次調用反射算法的參數。這一直持續下去,直到當前光線遇到環境(非反射)表面或者當前光線根本沒有碰到表面。

我現在計算顏色的方式是我平均反射表面的顏色和從後到前新打的表面。因此,光線早期點擊的表面上的顏色比以後的表面顏色更多。

如果顏色A是它遇到的第一個(反射)表面的顏色,則顏色B是它碰到的第二個表面的顏色,C是第三個表面的顏色,依此類推。所以在最終的顏色返回將是50%A,25%B,12.5%C ...

我用於此的方法實際上支持加權平均值,以便鏡像表面對最終顏色影響較小。它是:

public void addColor(Color b, double dimFac) { 
    double red = c.getRed() * (1 - dimFac) + b.getRed() * dimFac; 
    double green = c.getGreen() * (1 - dimFac) + b.getGreen() * dimFac; 
    double blue = c.getBlue() * (1 - dimFac) + b.getBlue() * dimFac; 
    c = new Color((int) red, 
        (int) green, 
        (int) blue); 
} 

下面是該程序的截圖。有三種環境球體懸停在一個光滑的反射面,隨着a的0.5「dimFac」:

enter image description here

這裏是相同的模擬用的1,使得反射鏡對最終顏色沒有影響一個dimFac:

enter image description here

這裏dimFac是0.8

enter image description here

這裏,它是0.1

enter image description here

也許這只是我,但沒有這些反射看起來驚人的逼真的。我用作指南的是康奈爾的一個簡報,其中除了別的以外,還提到了有關添加顏色的任何內容。鏡子確實有一定的顏色,我不知道混合顏色的正確方法。我在做什麼錯了?

所以我從光線中獲取顏色的方式如下。射線追蹤器的每次迭代都以形狀的初始化開始。該程序支持三種形狀:平面,球體和直角棱鏡(最終只有6個平面)。我有一個每個形狀的類,和一個類(稱爲形狀),可以存儲每種類型的形狀(但每個對象只有一個)。

形狀形成後,一個類(稱爲投影儀)通過稱爲MasterLight的另一個類(實際上包含用於基本光線追蹤,陰影,反射和(現在)折射的方法)投射光線。

爲了得到一個交點的顏色,我調用getColor()方法,該方法使用交點的向量(我如何存儲3d點)。我用它來確定表面的無陰影顏色。如果曲面是無紋理的並且只是一個空白顏色(如上面的形狀),那麼將返回一個無陰影的顏色(它只存儲在每個形狀類「Color c = Color.RED」中)。一個例子是Color.RED

我採取了這種顏色,遞歸地插回到MasterLight作爲基礎顏色來獲得陰影,就好像表面是正常的和環境的。這個過程返回形狀通常會有的陰影。現在RGB值可能是(128,0,0);

public Color getColor(Vector v) { 
    if (texturing) { 
     return texturingAlgorithm; 
    } 
    else { 
     return c; 
    } 
} 

DimFac它被使用的方式有可能是0到1之間的任何值;現在在我的程序中,它是0.8(這是普遍的陰影常數,在環境陰影中,我把我調暗的值乘以0.8並加上0.2(1 - 0.8),這樣最暗的a顏色可以是其原始亮度的0.2)。

addColor在另一個類中(我現在有17個,其中一個是一個枚舉)稱爲Intersection。這存儲了有關光線交點與形狀(顏色,位置,擊中表面的法向矢量以及與物體材質有關的其他常數)的所有重要信息。顏色c是計算中當前的顏色。

反射的每次迭代調用addColor與最新的表面顏色。詳細說明一下,如果(在上圖中)一條光線剛剛從平面反射回來,撞到一個球體並跳入空白區域,我首先在球反射點處發現球體表面的顏色,這就是'c ' 被設定爲。然後我在交叉點(第一次)使用平面顏色調用addColor。

只要我回溯了所有的反射,我就留下了一種顏色,這是我用來對該特定光線的像素着色的顏色。

告訴我是否錯過了任何東西或者不清楚。

+0

您能否提供您正在使用的獲取光線顏色的方法的副本?另外,你可以提供一些你的'addColor()'方法的上下文:dimFac是一個per-object屬性,就像在一個材質中一樣?還是全球價值?你能解釋你如何使用'Color''c'嗎? –

回答

3

您應該使用由Phong-Bui Tong於1975年創建的Phong Shading方法。Phong方程將照明簡化爲三個部分:環境,漫反射和鏡面反射。

環境光是在完全黑暗中物體的光照。環境照明不受光源的影響。

漫射光是基於交叉點的表面法線與交叉點的光矢量之間的角度的光亮度。

鏡面光是我相信你正在尋找。它基於從交叉角度到相機位置的矢量與表面周圍光矢量的反射矢量之間的角度。

以下是我通常使用Phong光照:

  • 有關場景的任何對象,定義了三個常量:嘉(環境照明),KD(漫射照明)和堪薩斯(高光)。我們還將定義一個恆定的「n」來表示物體的光澤。我會將此值保持在3以上。
  • 找到法向量和光向量的點積,現在我們稱這個量爲「dF」。
  • 現在讓我們來計算反射向量:它是法向量,乘以法向量和光向量的點積乘以2。減去光矢量,如果正常和光矢量做的話,它應該有1的幅度。
  • 從交叉點中查找反射向量和向量的點積,我們稱之爲「sF」。
  • 最後,我們將調用對象「clr」的顏色,最終的顏色將被稱爲「fClr」。
  • 要獲得的最終顏色,使用以下公式: FCLR = KA(CLR)+ KD(因子)(CLR)+堪薩斯(specularFactor^N)(CLR)
  • 最後,我檢查是否有任何你的R ,G或B值超出範圍。如果是這種情況,則使R,G或B值等於最接近的界限。

**如果您使用RGB,請對每個RGB值執行公式。

**我想指出,所有的RGB值應該是標量爲0.0 - 1.0。如果您使用的是8位RGB(0-255),請在將值分成255之前將其除以255,然後將輸出值乘以255.

**任何時候我指的是矢量是一個單位矢量,也就是說,它的幅度應該是1.

我希望這有助於!祝你好運!