散射模型
看Ray Tracing in One Weekend的散射模型的時候,是這樣做的:
為了模擬散射效果,我們在光線入射點正上方取一個單位球體,在其內部隨機取一個點作為其反射的方向,然後從入射點方向再次發射一條射線進行採樣。
實際上這個散射模型應該是所謂的『郎伯』物體,它其實應該完全遵守郎伯餘弦定理( Lamberts cosine law),其實完全按照這個來實現也ok,但是我們go with the author.按照上述quote來模擬。
寫 Python 代碼:
def random_in_unit_sphere():
p = 2 * Vector3(random(), random(), random()) - Vector3(1, 1, 1)
p.normalize()
return p
def color(ray, world):
for item in world:
if item.hit(ray, 0, inf):
t, p, normal = item.hit(ray, 0, inf)
target = p + normal + random_in_unit_sphere()
return 0.5 * color(Ray(p, target - p), world)
unit_direction = ray.direction.normalize()
t = 0.5 * (unit_direction.y + 1)
return (1 - t) * Vector3(1, 1, 1) + t * Vector3(0.5 ,0.7, 1.0)
random_in_unit_sphere
首先明白函數 random_in_unit_sphere()
, 這個函數是隨機產生在一個單位球體中的矢量,之所以我們不能隨意用 Vector3(random(), random(), random())
是因為這樣只會產生三個屬於 $[0,1)$之間的隨機變數,這樣只會在『第一象限』?
color(ray, world)
之前我們的 color 函數是這樣:
def color(ray, world):
for item in world:
if item.hit(ray, 0, inf):
t, p, normal = item.hit(ray, 0, inf)
return 0.5 * Vector3(normal.x + 1, normal.y + 1, normal.z + 1)
unit_direction = ray.direction.normalize()
t = 0.5 * (unit_direction.y + 1)
return (1 - t) * Vector3(1, 1, 1) + t * Vector3(0.5 ,0.7, 1.0)
這裡我們採用的是當光線與物體相遇的時候,我們在物體表面繪製的是它『法線』的顏色。
而這裡我們做的主要更改是:
t, p, normal = item.hit(ray, 0, inf)
target = p + normal + random_in_unit_sphere()
return 0.5 * color(Ray(p, target - p), world)
這裡實際上長這樣: