我想寫一個簡單的光線追蹤器作爲一個業餘愛好項目,它現在都工作正常,除了我不能得到軟陰影工作。我對軟陰影的想法是光源被認爲具有位置和半徑。爲了對這個光線進行陰影測試,我把主光線照射到場景中的一個物體上,並向光源投射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
}
}
看起來好多了。其他需要注意的事項:隨機數生成器質量和蒙特卡洛採樣,在這裏您可以採集樣本,直到統計數據顯示您的估算值很好。請記住,這種多抽樣方法永遠不會很快(否則他們不會發明光能)。 – timday 2009-02-05 13:12:42