深入理解Three.js中正交攝像機OrthographicCamera

  • 2019 年 10 月 3 日
  • 筆記

前言

深入理解Three.js中透視投影照相機PerspectiveCamera那篇文章中講解了透視投影攝像機的工作原理以及對應一些參數的解答,那篇文章中也說了會單獨講解Three.js中另一種常用的攝像機正交攝像機OrthographicCamera,這篇文章將會詳細的講解正交攝像機的工作原理和其對應參數的用法,當然,為了能夠讓讀者更加直觀的理解正交攝像機,我會製作一個與正交攝像機相關的demo來直觀的讓讀者感受正交攝像機的魅力。

原理說明

深入理解Three.js中透視投影照相機PerspectiveCamera文章中提到過正交攝像機和透視投影攝像機最大的區別是投影到的物體大小不受距離的影響,說直白點就是透視投影攝像機投影物體是通過點(下圖a),相當於我們的眼睛,距離越遠,能夠看到的部分也就越小。正交攝像機投影物體是通過平面(下圖b),無論距離有多遠,投射到二維平面的線始終的是平行的,所以看上去就會感覺物體的大小沒有受到任何影響。

 

正交攝像機參數說明

實現一個簡單正交攝像機的程式碼如下:

1 var camera = new THREE.OrthographicCamera( width / - 2, width / 2, height / 2, height / - 2, 1, 1000 );  2 scene.add( camera );

new THREE.OrthographicCamera()構造函數用於創建一個正交攝像機,該構造函數中有六個參數,分別是leftrighttopbottomnearfar

left — 攝像機視錐體左側面。
right — 攝像機視錐體右側面。
top — 攝像機視錐體上側面。
bottom — 攝像機視錐體下側面。
near — 攝像機視錐體近端面。
far — 攝像機視錐體遠端面。

其中,left的值不能夠大於right的值,而且leftright設置的值必須位於攝像機position中x坐標的兩側,否則將看不到影像。對應的topbottom也一樣,bottom值不能大於top值,且位於攝像機position坐標y值兩邊,否則也會看不到投影影像。nearfar分別用來設置攝像機近端面和遠端面,也就是通常說的最近距離和最遠距離。near設置越小,投影的影像就越大,反之則越小。但是near值並不是影響投影物體大小最大的,影響投影物體尺寸最大的還是leftrighttopbottom四個參數,而且也影響投影物體的形狀,所以在設置這四個參數的時候,leftright之間的距離和topbottom之間的距離的比例一定要和原始的canvas畫布比例相等,不然會導致投影的物體形狀變形。

為了能夠更好的理解正交攝像機,寫了一個小demo,程式碼如下,程式碼中我們統一設置攝像機的位置對應xyz坐標為0,15,70。為了能夠有比對性,在場景中我創建了一個網格,在網格上創建了一個黃色的球體。接下來我們依次比較下不同情況下的投影。

 1 var scene = new THREE.Scene();   2 console.log(scene)   3 var dom = document.getElementById('starry-frame');   4 //var camera = new THREE.OrthographicCamera( dom.clientWidth / - 15, dom.clientWidth / 15, dom.clientHeight / 15, dom.clientHeight / - 15, 1, 1000 );   5 var camera = new THREE.PerspectiveCamera( 45, dom.clientWidth / dom.clientHeight, 0.1, 1000 );   6 camera.position.set(0,15,70);   7 var renderer = new THREE.WebGLRenderer();   8 renderer.setSize( dom.clientWidth, dom.clientHeight );   9 dom.appendChild( renderer.domElement );  10 var geometry = new THREE.SphereGeometry( 5, 32, 32 );  11 var material = new THREE.MeshBasicMaterial( {color: 0xffff00} );  12 var sphere = new THREE.Mesh( geometry, material );  13 sphere.position.set(0,5,0)  14 scene.add( sphere );  15 var gridHelper = new THREE.GridHelper(50, 60);  16 gridHelper.rotation.y = -Math.PI / 2;  17 scene.add(gridHelper);  18 function render() {  19   renderer.render(scene,camera)  20   requestAnimationFrame(render)  21 }  22 render()

1 透視投影攝像機模式

其中,第一張圖是設置了球體position為0,5,0;第二張圖圖是設置球體position為0,5,-30。可以看出,在透視投影模式下,物體的大小隨著物體距離攝像機的距離而變化,距離越大物體大小越小。

                     

2 正交投影中leftright距離與topbottom距離比例與原始canvas畫布比例關係。

第一張圖為leftright距離與topbottom距離比例與原始canvas畫布比例相等;第二張圖為leftright距離與topbottom距離比例比原始canvas比例大;第三張圖為leftright距離與topbottom距離比例小於原始canvas畫布比例。從中可以得出我們在使用正交攝像機的時候比例必須要和原始的比例一致,防止映射出的圖形變形。

                              

3 正交攝像機中leftright相加,topbottom相加值與攝像機positionxy坐標關係。

第一張圖表示leftright相加值小於攝像機x坐標;第二張圖表示leftright值相加大於攝像機x坐標值;第三張圖為topbottom相加值大於攝像機y坐標值;第四張圖為topbottom相加值小於攝像機y坐標值。可以看出leftrighttopbottom相加值與攝像機中心點坐標有便宜的時候物體的影像和位置都會出現較大誤差。

                                                 

4 正交攝像機中leftrighttopbottom值與攝像機坐標關係。

left值大於攝像機x坐標值,right小於攝像機x坐標值,top大於攝像機y坐標值,bottom小於攝像機y坐標值都將會導致攝像機映射不出物體影像,如下圖,可以看到場景中一片漆黑。

正交攝像機實例

說一說做這個實例的初衷,單純為了理解正交攝像機的原理通過上面講述的那個例子就可以了,所以下面的這個實例不僅僅是為了能夠讓讀者更好的理解正交攝像機才去寫的。為了能夠更好的理解Three.js中正交攝像機,所以就在官網中瀏覽對應的案例,感覺無論是場景,還是視覺都挺不錯的,再加上當時我女兒特別喜歡Three.js中實例中的那隻鳥,所以我就決定將兩個實力合併在一起,純粹是為了討女兒喜歡,要知道女兒高興了才能不打攪我學習,還望讀者海涵。實例中移動的山使用的就是正交攝像機,所以可以看到無論如何移動,對應的山的高度和大小都是不會發生變化的,空中飛翔的鳥通過透視投影攝像機。

實例示意圖如下:

 

實例預覽地址:深入理解Three.js中的正交攝像機OrthographicCamera

後話

希望上述講解能夠幫助到閱讀這篇博文的讀者!!!