在 p5.js 中繪製 3D 物件,若物件很大,你會發現 z 正方向那面看來較大,負方向那面看來較小,構成一種遠近感,例如:
這是因為 p5.js 預設套用透視投影(Perspective projection),這跟在紙面上繪畫時會採用透視法是相同的原理,為描繪的對象找個消失點,邊繪製時往消失點方向進行,這會使得近面看來較大,遠面看來較小:
在紙面上繪畫運用透視技法時,實際上觀察點在哪呢?其實是與消失點相反的方向:
在上圖中,若中間的軸線代表畫面,離觀察點較遠的頂點投射至畫面時,是會低於離觀察點較近的頂點,因此才會造成近面看來較大,遠面看來較小的視覺效果。
計算時就可以基於觀察點,而在自定義空間時,〈正交投影〉 會是個立方體,然而透視投影時,會是個錐形體,或稱為視體(Viewing frustum),也就是觀察範圍:
觀察點的近面距離(near)、遠面距離(far),以及觀察點的視場角(fov)、近面寬高比(aspect)(也就是畫布寬高比例),決定了要觀察的範圍,也就是模型必須位於圖中藍色部份,才會被繪製出來,計算時視場角,可以使用近面上下兩個邊的角度(fovy):
p5.js 提供了 perspective
,可以讓你指定 fovy
、aspect
、near
、far
等參數,p5.js 預設會使用 PI / 3.0
, width / height
, eyeZ / 10.0
, eyeZ * 10.0
,eyeZ
是 (height / 2.0) / tan(PI * 60.0 / 360.0)
。
增加 fovy
、減少 near
、增加 far
等,都會讓觀察範圍變大:
觀察的範圍變大,然而還是要畫進同尺寸畫布,最後看到的 3D 物件就會變小。例如:
perspective
也可以跟 camera
結合使用(底層也是兩個轉換矩陣的運算),同樣地,這時可以想像,相機與觀察範圍的近面是連動的:
如果你移動相機,觀察範圍也會跟著一起動:
除了透過 perspective
來進行透視投影之外,p5.js 也提供了 frustum
,可指定 left
、right
、bottom
、top
、near
、far
來定義視體,其中 left
、right
、bottom
、top
是近面的邊界:
使用哪個,就看你的需求,底下是個 frustum
示範: