1. 程式人生 > >深入理解Three.js中正交攝像機OrthographicCamera

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

前言

在深入理解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()建構函式用於建立一個正交攝像機,該建構函式中有六個引數,分別是left,right,top,bottom,near,far。

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

其中,left的值不能夠大於right的值,而且left和right設定的值必須位於攝像機position中x座標的兩側,否則將看不到影像。對應的top和bottom也一樣,bottom值不能大於top值,且位於攝像機position座標y值兩邊,否則也會看不到投影影像。near和far分別用來設定攝像機近端面和遠端面,也就是通常說的最近距離和最遠距離。near設定越小,投影的影像就越大,反之則越小。但是near值並不是影響投影物體大小最大的,影響投影物體尺寸最大的還是left,right,top,bottom四個引數,而且也影響投影物體的形狀,所以在設定這四個引數的時候,left與right之間的距離和top與bottom之間的距離的比例一定要和原始的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 正交投影中left,right距離與top,bottom距離比例與原始canvas畫布比例關係。

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

                              

3 正交攝像機中left,right相加,top與bottom相加值與攝像機position中x,y座標關係。

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

                                                 

4 正交攝像機中left,right,top,bottom值與攝像機座標關係。

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

正交攝像機例項

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

例項示意圖如下:

 

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

後話

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