高光

有些物體表面是不光滑的,但是它們具有高光。比如拋光的瓷磚地面、光澤塗料和白板等。高光在表面上會隨著視點的移動而移動。

比如下圖:

圖中白色的部分就是高光,並且我們在不同的角度看它,它會在不同的位置高光。

模擬

高光依靠的就是純粹的一個數學模擬。它其實就是一個反射光。

L依舊指向光射入光線,N依舊為法向量,R為反射形成的光,它有著這樣的特別之處,那就是我們從觀察方向V來看,隨著 alpha 角度的增大,這個光會銳減的很快。

看函數 cos alpha ,當 alpha 為0的時候,這個值剛好為1,當 alpha 增加到90°時候,這個值剛好減少到0.

所以我們可以用函數 cos^s alpha 來模擬物體的鏡面指數。

那麼高光將會造成的 overrightarrow{R} 在觀看角度 overrightarrow{V} 的值的計算如下:

overrightarrow{L_N} =overrightarrow{N} (overrightarrow{L} cdot overrightarrow{N})

 overrightarrow{L_p} = overrightarrow{L} - overrightarrow{L_N}

 overrightarrow{R} = overrightarrow{L_N} + (overrightarrow{-L_P})

代入可得  overrightarrow{R} = 2 cdot overrightarrow{N} (overrightarrow{L} cdot overrightarrow{N})- overrightarrow{L}

所以從 overrightarrow{V} 方向得到的高光強度是:

I_s = I_L(frac{overrightarrow{N} cdot overrightarrow{V}}{|overrightarrow{N}| |overrightarrow{V}|})^s

依舊記住我們只需要考慮大於0的狀況.

至此の偽碼

之前的偽碼依舊適用,我們需要考慮的是:

  1. 增加高光指數s
  2. 調整計算光的部分

我們首先給每個小球添加s,s越大會越閃亮(s = -1 表示物體並沒有),按照作者的邏輯,同時我們添加一個巨大的小球,這樣它就會像一個平面一樣。

在計算高光的時候我們使用上方的公式,我們已經有 overrightarrow{N},overrightarrow{L},I_L , s是小球本身的性質,我們也已經添加,需要的還有 overrightarrow{V} ,這是我們觀察的方向,view direction,記住我們光線追蹤的初衷,是從眼睛看出來,所以view direction特別簡單,就是 -overrightarrow{D} .

所以調整計算光的部分如下

ComputeLighting

ComputeLighting(P, N, V, s) {
i = 0.0
for light in scene.Lights {
if light.type == ambient {
i += light.intensity
} else {
if light.type == point
L = light.position - P
else
L = -light.direction

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

# specular
if s!= -1 {
R = 2*N*dot(N,L) -L
r_dot_v = dot(R, V)
if r_dot_v > 0
i += light.intensity*pow(r_dot_v/length(R)*length(V)),s)
}
}
}
return i
}

TraceRay

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, -D, sphere.specular)
}

畫到畫布上

看結果:

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

github.com
圖標

推薦閱讀:
相关文章