顏色模擬

上面寫到我們需要展示 [公式] 的顏色,那麼 [公式] 都顏色究竟應該是怎樣的?應該就是它自身的顏色和光相互作用的結果,我們這裡命事物本身顏色為c, P點處光的強度為i(這裡我們只考慮白光), 那麼比如 [公式] 就會是最終的顏色,一般來說 0 < i < 1,比如 i 是 0.5,那麼物體就會變成原來的一半亮。

以下的模擬,有些會用到自然界中可能事物的真實樣子,有些就是純粹的數學模型。

1.光源

1.1 環境光

環境光很簡單,我們直接給一個數字 [公式] 這樣就代表了周圍環境的光

1.2 點光源

點光源就像電燈泡一樣,固定於一個點,然後發出光線於四周,對於點光源,我們只需它的位置Q和強度 [公式] .

1.3 方向光

方向光就類似於自然界中的太陽光,我們需要知道它的方向 [公式] 和強度 [公式] .

2 光與物體

2.1 漫反射

漫反射是這樣,達到物體表面的表面的光實際上只有 [公式][公式] 方向的投影,實際上P點得到的強度是 [公式] .

注意我們只考慮 [公式] 大於0的狀況,因為如果小於零,它是到達了物體的背面。

[公式]

為了計算方便,[公式] 表示我們指向光源的方向[公式] 為物體表面的法向量:

[公式]

當然我們也可以為了計算方便,選擇

可以得到光疊加的效果是:

[公式]

至此,我們就可以畫出空間中很好看的效果了。注意再次提醒這裡後面的疊加部分只需要算大於0的部分,因為小於0的光疊加是沒有物理意義的。

至此の偽碼

跟蹤光線與球相交 IntersectRaySphere

跟之前寫的一樣

t1 處的光ComputeLighting

在以下的偽碼中,P是物體表面的位置,N是物體表面的法向量。

ComputeLighting(P, N) {
i = 0.0
for light in scene.Lights {
if light.type == ambient {
i += light.intensity
} else {
if light.type == point
L = P - light.position //指向光的方向
else
L = -light.direction //指向光的方向

n_dot_l = dot(N, L)
if n_dot_l > 0
i += light.intensity*n_dot_l/(length(N)*length(L))
}
}
return i
}

t1 的顏色TraceRay

這裡我們在空間里放入好幾個球體,然後計算t1處的顏色偽碼如下:

TraceRay(O, D, t_min, t_max){
closest_t = inf
closest_sphere = NULL
for sphere in scene.Spheres {
t1, t2 = IntersectRaySphere(O, D, sphere)
if t1 in [t_min, t_max] and t1 < closest_t
closest_t = t1
closest_sphere = sphere
if t2 in [t_min, t_max] and t2 < closest_t
closest_t = t2
closest_sphere = sphere
}

if closest_sphere == NULL
return BACKGROUND_COLOR

P = O + closest_t * D #交點P的位置
N = P - closest_sphere.center #計算P處的法向量
N = N / length(N) #normalize 法向量
return closest_sphere.color * ComputeLighting(P, N)
}

畫到畫布上

看結果:

效果已經比之前好很多了。

KrisYu/computer-graphics-from-scratch-Notes?

github.com
圖標

推薦閱讀:
相关文章