正投影相機OrthographicCamera和透視投影相機PerspectiveCamera
本文是Three.js電子書的9.1節
針對不同應用的三維場景需要使用不同的投影方式,比如機械、工業設計領域常常採用正投影(平行投影), 大型遊戲場景往往採用透視投影(中心投影)。爲了完成三維場景不同的投影方式,three.js封裝WebGL API和相關算法,提供了正投影相機OrthographicCamera和透視投影相機PerspectiveCamera。
正投影和透視投影簡單解釋
下面對正投影相機和透視投影相機的投影算法進行簡單介紹,對於初學者你有一個印象就可以,如果想深入瞭解,可以學習圖形學或者閱讀threejs官方源碼src目錄下文件OrthographicCamera.js
和PerspectiveCamera.js
生活中的物體都是三維的,但是人的眼睛只能看到正面,不能看到被遮擋的背面,三維幾何體在人眼睛中的效果就像一張相機拍攝的二維照片,你看到的是一個2D的投影圖。 空間幾何體轉化爲一個二維圖的過程就是投影,不同的投影方式意味着投影尺寸不同的算法。
對於正投影而言,一條直線放置的角度不同,投影在投影面上面的長短不同;對於透視投影而言,投影的結果除了與幾何體的角度有關,還和距離相關, 人的眼睛觀察世界就是透視投影,比如你觀察一條鐵路距離越遠你會感到兩條軌道之間的寬度越小。無論正投影還是透視投影,three.js都對相關的投影算法進行了封裝, 大家只需要根據不同的應用場景自行選擇不同的投影方式。使用OrthographicCamera
相機對象的時候,three.js會按照正投影算法自動計算幾何體的投影結果; 使用PerspectiveCamera
相機對象的時候,three.js會按照透視投影算法自動計算幾何體的投影結果。
正投影相機對象OrthographicCamera
/**
* 正投影相機設置
*/
var width = window.innerWidth; //窗口寬度
var height = window.innerHeight; //窗口高度
var k = width / height; //窗口寬高比
var s = 150; //三維場景顯示範圍控制係數,係數越大,顯示的範圍越大
//創建相機對象
var camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
camera.position.set(200, 300, 200); //設置相機位置
camera.lookAt(scene.position); //設置相機方向(指向的場景對象)
// 構造函數格式
OrthographicCamera( left, right, top, bottom, near, far )
參數(屬性) | 含義 |
---|---|
left | 渲染空間的左邊界 |
right | 渲染空間的右邊界 |
top | 渲染空間的上邊界 |
bottom | 渲染空間的下邊界 |
near | near屬性表示的是從距離相機多遠的位置開始渲染,一般情況會設置一個很小的值。 默認值0.1 |
far | far屬性表示的是距離相機多遠的位置截止渲染,如果設置的值偏小小,會有部分場景看不到。 默認值1000 |
三維場景中座標值不在三維空間中的網格模型不會被渲染出來,會被剪裁掉,比如你把上面代碼中far參數的值從1000更改爲420,你會發現長方體的一部分無法顯示。
注意
左右邊界的距離與上下邊界的距離比值與畫布的渲染窗口的寬高比例要一致,否則三維模型的顯示效果會被單方向不等比例拉伸
構造函數OrthographicCamera
的參數( left,right,top,bottom,near,far)
本質上是對WebGL投影矩陣的封裝,寬度width
、高度height
越大,三維模型頂點的位置座標就會越大,超出可視區域的網格模型就會被剪裁掉, 不會再顯示在屏幕上,大家還可以看到參數left
與right
、參數top
與bottom
互爲相反數,這樣做的目的是lookAt
指向的對象能夠顯示在canvas畫布的中間位置。
透視投影相機PerspectiveCamera
/**
* 透視投影相機設置
*/
var width = window.innerWidth; //窗口寬度
var height = window.innerHeight; //窗口高度
/**透視投影相機對象*/
var camera = new THREE.PerspectiveCamera(60, width / height, 1, 1000);
camera.position.set(200, 300, 200); //設置相機位置
camera.lookAt(scene.position); //設置相機方向(指向的場景對象)
構造函數PerspectiveCamera
格式
PerspectiveCamera( fov, aspect, near, far )
參數 | 含義 | 默認值 |
---|---|---|
fov | fov表示視場,所謂視場就是能夠看到的角度範圍,人的眼睛大約能夠看到180度的視場,視角大小設置要根據具體應用,一般遊戲會設置60~90度 | 45 |
aspect | aspect表示渲染窗口的長寬比,如果一個網頁上只有一個全屏的canvas畫布且畫布上只有一個窗口,那麼aspect的值就是網頁窗口客戶區的寬高比 | window.innerWidth/window.innerHeight |
near | near屬性表示的是從距離相機多遠的位置開始渲染,一般情況會設置一個很小的值。 | 0.1 |
far | far屬性表示的是距離相機多遠的位置截止渲染,如果設置的值偏小小,會有部分場景看不到 | 1000 |
相機位置.posiiotn
和.lookAt(相機拍攝目標位置)
相機Camera的基類是Object3D,相機對象Camera
具有位置屬性.posiiotn
,通過位置屬性.posiiotn
可以設置相機的位置。
.lookAt()
方法用來指定相機拍攝對象的座標位置,.lookAt()
方法的參數是表示位置座標的三維向量對象Vector3,所以.lookAt()
方法的參數可以通過代碼new THREE.Vector3(x,y,z)
設置。實際開發的時候,你希望相機對準哪個對象,就返回那個對象的位置屬性.posiiotn
,比如上面代碼中的scene.position
, 就表示返回場景scene的位置座標,如果把scene.position
換成某個網格模型對象的位置就是mesh.position
,mesh.position
表示網格模型mesh的本地位置座標。通過相機觀察點的位置和.lookAt()
方法指向的位置就可以計算出相機的拍攝角度,本質上就是計算出相機對象的視圖矩陣.matrixWorldInverse
。
對於透視投影而言,相機位置與lookAt
指向的觀察目標位置間隔距離越小,場景中的三維模型放大倍數越大,準確地說是透視投影相機可以拍攝的範圍更小,同時場景Scene
中超出的相機參數約束範圍的部分會被剪裁掉, 比如更改上面代碼camera.position.set(100,200,200);
爲(20,20,20)
,測試結果你會發現立方體幾何體放大顯示,超出區域被剪裁。
相機位置放置
如果是觀察一個產品外觀效果,相機就位於幾何體的外面,如果是室內漫遊預覽,就把相機放在房間三維模型的內部。