系列博文-Three.js入門指南(張雯莉)-照相機


照相機就是這樣一個抽象,它定義了三維空間到二維屏幕的投影方式,用“照相機”這樣一個類比,可以使我們直觀地理解這一投影方式。
而針對投影方式的不同,照相機又分為正交投影照相機與透視投影照相機。我們需要為自己的程序選擇合適的照相機。

2.2 正交投影vs透視投影

舉個簡單的例子來說明正交投影與透視投影照相機的區別。使用透視投影照相機獲得的結果是類似人眼在真實世界中看到的有“近大遠小”的效果(如下圖中的(a));而使用正交投影照相機獲得的結果就像我們在數學幾何學課上老師教我們畫的效果,對於在三維空間內平行的線,投影到二維空間中也一定是平行的(如下圖中的(b))。

那么,你的程序需要正交投影還是透視投影的照相機呢?
一般說來,對於制圖、建模軟件通常使用正交投影,這樣不會因為投影而改變物體比例;而對於其他大多數應用,通常使用透視投影,因為這更接近人眼的觀察效果。

2.3 正交投影照相機

參數介紹
正交投影照相機(Orthographic Camera)設置起來較為直觀,它的構造函數是:

THREE.OrthographicCamera(left, right, top, bottom, near, far) 

這六個參數分別代表正交投影照相機拍攝到的空間的六個面的位置,這六個面圍成一個長方體,我們稱其為視景體(Frustum)。只有在視景體內部(下圖中的灰色部分)的物體才可能顯示在屏幕上,而視景體外的物體會在顯示之前被裁減掉。

為了保持照相機的橫豎比例,需要保證(right - left)與(top - bottom)的比例與Canvas寬度與高度的比例一致。
near與far都是指到照相機位置在深度平面的位置,而照相機不應該拍攝到其后方的物體,因此這兩個值應該均為正值。為了保證場景中的物體不會因為太近或太遠而被照相機忽略,一般near的值設置得較小,far的值設置得較大,具體值視場景中物體的位置等決定。
實例說明
下面,我們通過一個具體的例子來解釋正交投影照相機的設置。
例2.3.1
基本設置
設置照相機:

var camera = new THREE.OrthographicCamera(-2, 2, 1.5, -1.5, 1, 10);
camera.position.set(0, 0, 5);
scene.add(camera); 

在原點處創建一個邊長為1的正方體,為了和透視效果做對比,這里我們使用wireframe而不是實心的材質,以便看到正方體后方的邊:

var cube = new THREE.Mesh(new THREE.CubeGeometry(1, 1, 1),
        new THREE.MeshBasicMaterial({
            color: 0xff0000,
            wireframe: true
        })
);
scene.add(cube); 

得到的效果是:

我們看到正交投影的結果是一個正方形,后面的邊與前面完全重合了,這也就是正交投影與透視投影的區別所在。
長寬比例
這里,我們的Canvas寬度是400px,高度是300px,照相機水平方向距離4,垂直方向距離3,因此長寬比例保持不變。為了試驗長寬比例變化時的效果,我們將照相機水平方向的距離減小為2:

var camera = new THREE.OrthographicCamera(-1, 1, 1.5, -1.5, 1, 10); 

得到的結果是水平方向被拉長了:

照相機位置
接下來,我們來看看照相機位置對渲染結果的影響。在之前的例子中,我們將照相機設置在(0, 0, 5)位置,而由於照相機默認是面向z軸負方向放置的,所以能看到在原點處的正方體。現在,如果我們將照相機向右移動1個單位:

var camera = new THREE.OrthographicCamera(-2, 2, 1.5, -1.5, 1, 10);
camera.position.set(1, 0, 5); 

得到的效果是物體看上去向左移動了:

仔細想一下的話,這也不難理解。就好比你人往右站了,看起來物體就相對往左移動了。
那么,正交投影照相機在設置時,是否需要保證left和right是相反數呢?如果不是,那么會產生什么效果呢?下面,我們將原本的參數(-2, 2, 1.5, -1.5, 1, 10)改為(-1, 3, 1.5, -1.5, 1, 10),即,將視景體設置得更靠右:

var camera = new THREE.OrthographicCamera(-1, 3, 1.5, -1.5, 1, 10);
camera.position.set(0, 0, 5); 

得到的結果是:

這與之前向右移動照相機得到的效果是等價的。

換個角度看世界
到現在為止,我們使用照相機都是沿z軸負方向觀察的,因此看到的都是一個正方形。現在,我們想嘗試一下仰望這個正方體。我們已經學會設置照相機的位置,不妨將其設置在(4, -3, 5)處:

camera.position.set(4, -3, 5);

是現在照相機沿z軸負方向觀察的,因此觀察不到正方體,只看到一片黑。我們可以通過lookAt函數指定它看着原點方向:

camera.lookAt(new THREE.Vector3(0, 0, 0)); 

這樣我們就能過仰望正方體啦:

不過一定要注意,lookAt函數接受的是一個THREE.Vector3的實例,因此千萬別寫成camera.lookAt(0, 0, 0),否則非但不能得到理想的效果,而且不會報錯,使你很難找到問題所在。
現在,恭喜你學會設置正交照相機了!雖然它看起來較為簡單,但是加入動畫、交互等因素后,可以為你的應用程序增色不少的!


2.4 透視投影照相機

參數介紹
透視投影照相機(Perspective Camera)的構造函數是:

THREE.PerspectiveCamera(fov, aspect, near, far) 

讓我們通過一張透視照相機投影的圖來了解這些參數。

透視圖中,灰色的部分是視景體,是可能被渲染的物體所在的區域。fov是視景體豎直方向上的張角(是角度制而非弧度制),如側視圖所示。
aspect等於width / height,是照相機水平方向和豎直方向長度的比值,通常設為Canvas的橫縱比例。
near和far分別是照相機到視景體最近、最遠的距離,均為正值,且far應大於near。
實例說明
下面,我們從一個最簡單的例子學習設置透視投影照相機。
基本設置
例2.4.1
設置透視投影照相機,這里Canvas長400px,寬300px,所以aspect設為400 / 300:

var camera = new THREE.PerspectiveCamera(45, 400 / 300, 1, 10);
camera.position.set(0, 0, 5);
scene.add(camera); 

和例2.3.1一樣,設置一個在原點處的邊長為1的正方體:

var cube = new THREE.Mesh(new THREE.CubeGeometry(1, 1, 1),
        new THREE.MeshBasicMaterial({
            color: 0xff0000,
            wireframe: true
        })
);
scene.add(cube); 

得到的結果是:

對比例2.3.1正方形的效果,透視投影可以看到全部的12條邊,而且有近大遠小的效果,這也就是與正交投影的區別。
豎直張角
接下來,我們來看下fov的改變對渲染效果的影響。我們將原來的45改為60,得到這樣的效果:

為什么正方體顯得更小了呢?我們從下面的側視圖來看,雖然正方體的實際大小並未改變,但是將照相機的豎直張角設置得更大時,視景體變大了,因而正方體相對於整個視景體的大小就變小了,看起來正方形就顯得變小了。

注意,改變fov並不會引起畫面橫豎比例的變化,而改變aspect則會改變橫豎比例。這一效果類似2.3節,此處不再重復說明。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM