2009-02-05 18 views
3

我想寫一個簡單的光線追蹤器作爲一個業餘愛好項目,它現在都工作正常,除了我不能得到軟陰影工作。我對軟陰影的想法是光源被認爲具有位置和半徑。爲了對這個光線進行陰影測試,我把主光線照射到場景中的一個物體上,並向光源投射n個光線,其中每個新光線對每個軸具有隨機分量,其中隨機分量變化介於-radius和radius之間。我的軟陰影代碼有什麼問題?

如果這樣的光線照到場景中的物體,我增加了一個撞擊計數器(如果光線碰到多個物體,它仍然只會增加一個物體)。如果它使光源沒有碰撞,我將主光線相交點到光源中心的距離加到變量中。

當採樣n個樣本時,我計算出碰撞的光線的比例並乘以該比例的光的顏色(因此顏色1000,1000,1000的光將變爲500,500,500,比例爲0.5,一半的光線發生碰撞)。然後,我通過將早期的距離變量除以非碰撞射線的量來計算到光源的平均距離。我返回該變量並退出該函數。

問題是:它不起作用。至少不是。看起來像什麼可以看到here。你可以看到它有點像軟陰影,如果你真的很眯眼。

我不明白,我在這裏犯了某種根本性的缺陷,還是這是小事?我很確定問題在於這種方法,因爲當我計算直接由此方法生成的部分點亮像素的數量時,只有大約250個,此時應該有更多。當你仔細觀察圖片時,可以看到有一些部分點亮的像素,這表明剩下的代碼會處理部分點亮的像素。

下面是軟陰影類實際光:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace MyFirstRayTracer 
{ 
    public class AreaLight : ILight 
    { 
    private const int _radius = 5; 
    private const int _samples = 16; 
    public Color Color { get; set; } 
    public Vector Location { get; set; } 
    #region ILight Members 

    public float GetLightingInformation(Vector point, ISceneObject[] scene, out Color color) 
    { 
     int intersectCount = 0; 
     float distance = -1; 
     for(int i = 0; i < _samples; i++) 
     { 
    bool intersects = false; 
    float rand = 0; 
    rand = _radius - (float)(new Random().NextDouble()*(2*_radius)); 
    foreach (ISceneObject obj in scene) 
    { 
     Vector iPoint; 

     Vector loc = new Vector(Location.X + rand, Location.Y + rand, Location.Z + rand); 

     if (!obj.Intersect(new Ray(point, loc), out iPoint)) 
     { 
     distance += (Location - point).SqLength; 

     } 
     else 
     { 
     intersects = true; 
     distance -= (Location - point).SqLength; 
     } 
    } 
    if (intersects) 
     intersectCount++; 
     } 
     float factor = 1-((float)intersectCount/_samples); 

     color = new Color(factor*Color.R, factor*Color.G, factor*Color.B); 

     return (float)Math.Sqrt(distance/(_samples - intersectCount)); 
    } 


    #endregion 
    } 
} 

回答

3

嘗試爲「loc」的每個組件生成不同的「rand」。因爲,你的抖動點都在一條線上。

5

輕微點,但就是這個最好使用隨機類的..

for(int i = 0; i < _samples; i++) 
     { 
     bool intersects = false; 
     float rand = 0; 
     rand = _radius - (float)(new Random().NextDouble()*(2*_radius)); 

如果不是這種..

var rnd = new Random()  
    for(int i = 0; i < _samples; i++) 
       { 
       bool intersects = false; 
       float rand = 0; 
       rand = _radius - (float)(rnd.NextDouble()*(2*_radius)); 
1

您實際上在方向(1,1,1)的線上生成線上的點。光源是否真的線性?

另外,我幾乎無法看到你的例子中的任何東西。你能否讓你的相機更接近未來的陰影,而不是指向光的方向?

1

看,這就是我爲什麼來到這個網站:)

每個軸現在都有自己的隨機的,它看起來好了很多。這看起來還是有點奇怪,但增加樣本數量有所幫助。它現在看起來像this

你知道一個更有效的方法來減少圖案形成嗎?

儘管最大的幫助:沒有實例化每個樣本的隨機數。它使我的渲染速度與軟陰影嚴重增加了三倍!我從來不知道Random是如此昂貴的實例化。哇。

非常感謝。

+0

看起來好多了。其他需要注意的事項:隨機數生成器質量和蒙特卡洛採樣,在這裏您可以採集樣本,直到統計數據顯示您的估算值很好。請記住,這種多抽樣方法永遠不會很快(否則他們不會發明光能)。 – timday 2009-02-05 13:12:42

1

在您的回覆中,您要求改進方法來製作柔和陰影。一種改進可以是,不是隨機化來自同一點的所有光線,而是爲每條光線在所有軸上賦予不同的偏移量,以有效地給它們一個單獨的小窗口隨機化。這應該導致更均勻的分佈。我不知道這是否清楚,但另一種描述它的方式是與陰影射線垂直的網格。網格中的每個瓦片包含n條陰影射線之一,但網格中的位置是隨機的。 Here你可以找到一個教程的一部分,它描述瞭如何使用這個軟陰影。