three.js中正交與透視投影相機(jī)的實(shí)戰(zhàn)應(yīng)用指南
前言
一個(gè)場(chǎng)景之所以會(huì)呈現(xiàn)在我們眼前是因?yàn)槲覀兙哂醒劬?,眼睛提供了視覺。換句話說,如果three.js場(chǎng)景中沒有這雙眼睛,就像電影沒有攝像機(jī)一樣,場(chǎng)景就無法呈現(xiàn)在我們面前?這雙眼睛就是相機(jī),可見相機(jī)是Three.js場(chǎng)景中不可或缺的一個(gè)組件。Three.js庫提供了兩種不同的相機(jī):正交投影相機(jī)和透視投影相機(jī),接下來分別講解這兩種相機(jī)以及結(jié)合實(shí)例的應(yīng)用。
1 正交投影相機(jī)
我們先來看一張示意圖:
由圖可知正交透視相機(jī)總共有6個(gè)面,其具備的特點(diǎn)是:場(chǎng)景中遠(yuǎn)處的物體和近處的物體是一樣大的,它并不像我們現(xiàn)實(shí)生活中看場(chǎng)景那樣,遠(yuǎn)小近大,而是遠(yuǎn)近皆一樣大;6個(gè)面分別為left(左面),right(右面),top(頂面),bottom(底面),near(近面),near(遠(yuǎn)面),右這六個(gè)面組成一個(gè)封閉的矩形空間,在這個(gè)空間內(nèi)的一切物體都可見。在設(shè)置其參數(shù)的時(shí)候,下面的關(guān)系式一定要成立:
| left / right | = 1,| top / buttom | = 1
正交相機(jī)的代碼實(shí)現(xiàn)為:
var camera = new THREE.OrthographicCamera(left, right, top, bottom, near, far);
2 投射投影相機(jī)
投射投影相機(jī)才是現(xiàn)實(shí)世界中我們看到的場(chǎng)景的體現(xiàn):遠(yuǎn)小近大,即我們所說的透視效果。先來看一張示意圖:
如圖中所示,透視投影相機(jī)一共有4個(gè)參數(shù):fov(視場(chǎng),一個(gè)角度值), Horizonta Field of View(橫向視場(chǎng)),Vertical
Field of View(縱向視場(chǎng)),Near plane(近面), Far plane(遠(yuǎn)面);由這幾個(gè)因素,構(gòu)成一個(gè)六面體的封閉空間,在這個(gè)空間內(nèi)的一切物體可見。在設(shè)置參數(shù)時(shí),需滿足:
橫向視場(chǎng) / 縱向視場(chǎng) = 瀏覽器窗口的寬/瀏覽器窗口的高。
其代碼實(shí)現(xiàn)為:
var camera = new THREE.PerspectiveCamera(fov, width / height, near, far);
3 實(shí)例
這里實(shí)現(xiàn)兩種相機(jī)的應(yīng)用,里面添加了一個(gè)簡單的交互條,實(shí)現(xiàn)的效果如下圖:
本例代碼如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>threejs-camera</title> <style> body{ font-family: Monospace; backgroud: #f0f0f0; margin: 0px; overflow: hidden; } </style> </head> <body> <script type="text/javascript" src="build/three.js"></script> <script type="text/javascript" src="js/Detector.js"></script> <script type="text/javascript" src="js/libs/dat.gui.min.js"></script> <script type="text/javascript"> //檢測(cè)webgl的支持情況 if(!Detector.webgl) {Detector.addGetWebGLMessage();} var container; var scene, camera, renderer; window.onload = function main(){ //添加一個(gè)div元素 container = document.createElement('div'); document.body.appendChild(container); //創(chuàng)建新場(chǎng)景 scene = new THREE.Scene(); //渲染 //antialias:true增加抗鋸齒效果 renderer = new THREE.WebGLRenderer({antialias:true}); renderer.setClearColor(new THREE.Color(0x3399CC));//設(shè)置窗口背景顏色為黑 renderer.setSize(window.innerWidth, window.innerHeight);//設(shè)置窗口尺寸 //將renderer關(guān)聯(lián)到container,這個(gè)過程類似于獲取canvas元素 container.appendChild(renderer.domElement); perCamera(); light(); myScene(); render(); }; //創(chuàng)建一個(gè)透視相機(jī) function perCamera(){ camera = new THREE.PerspectiveCamera(25, window.innerWidth/window.innerHeight, 1, 1000); camera.position.set(150, 180, 100);//設(shè)置相機(jī)位置 camera.lookAt(scene.position);//讓相機(jī)指向場(chǎng)景中心 } //創(chuàng)建一個(gè)正交投影相機(jī) function orthCamera(){ camera = new THREE.OrthographicCamera(window.innerWidth/-14.5,window.innerWidth/14.5, window.innerHeight/14.5,window.innerHeight/-14.5,-100,400); camera.position.set(150,180, 100);//設(shè)置相機(jī)坐標(biāo) camera.lookAt(scene.position);//讓相機(jī)指向場(chǎng)景中心 } //燈光 function light(){ //自然光 var ambientLight = new THREE.AmbientLight( 0x606060 ); scene.add( ambientLight ); //平行光源 var directionalLight = new THREE.DirectionalLight( 0xffffff ); directionalLight.position.set( 1, 1.75, 0.5 ).normalize(); scene.add( directionalLight ); } //創(chuàng)建一個(gè)立體場(chǎng)景 function myScene(){ //創(chuàng)建平面 var planeGeo = new THREE.PlaneGeometry(100,100,10,10);//創(chuàng)建平面 var planeMat = new THREE.MeshLambertMaterial({ //創(chuàng)建材料 color:0x999999, wireframe:false }); var planeMesh = new THREE.Mesh(planeGeo, planeMat);//創(chuàng)建網(wǎng)格模型 planeMesh.position.set(0, 0, -20);//設(shè)置平面的坐標(biāo) planeMesh.rotation.x = -0.5 * Math.PI;//將平面繞X軸逆時(shí)針旋轉(zhuǎn)90度 scene.add(planeMesh);//將平面添加到場(chǎng)景中 //創(chuàng)建立方體 var cubeGeo1 = new THREE.CubeGeometry(20, 40, 20, 5, 5, 5);//創(chuàng)建立方體 var cubeMat1 = new THREE.MeshLambertMaterial({//創(chuàng)建材料 color:0x333333, wireframe:false }); var cubeMesh1 = new THREE.Mesh(cubeGeo1, cubeMat1);//創(chuàng)建立方體網(wǎng)格模型 cubeMesh1.position.set(15, 10, 0);//設(shè)置立方體的坐標(biāo) scene.add(cubeMesh1);//將立方體添加到場(chǎng)景中 var cubeGeo2 = new THREE.CubeGeometry(20, 40, 20, 5, 5, 5);//創(chuàng)建立方體 var cubeMat2 = new THREE.MeshLambertMaterial({//創(chuàng)建材料 color:0x333333, wireframe:false }); var cubeMesh2 = new THREE.Mesh(cubeGeo2, cubeMat2);//創(chuàng)建立方體網(wǎng)格模型 cubeMesh2.position.set(-25, 16, 0);//設(shè)置立方體的坐標(biāo) scene.add(cubeMesh2);//將立方體添加到場(chǎng)景中 var cubeGeo3 = new THREE.CubeGeometry(20, 40, 20, 5, 5, 5);//創(chuàng)建立方體 var cubeMat3 = new THREE.MeshLambertMaterial({//創(chuàng)建材料 color:0x333333, wireframe:false }); var cubeMesh3 = new THREE.Mesh(cubeGeo3, cubeMat3);//創(chuàng)建立方體網(wǎng)格模型 cubeMesh3.position.set(10, 20, -40);//設(shè)置立方體的坐標(biāo) scene.add(cubeMesh3);//將立方體添加到場(chǎng)景中 } //添加交互工具條 var controls = new function(){ this.相機(jī) = false; }; var gui = new dat.GUI(); gui.add(controls, '相機(jī)', ["透視投影相機(jī)","正交投影相機(jī)"]).onChange(function(e){ switch (e) { case "正交投影相機(jī)": orthCamera(); break; case "透視投影相機(jī)": perCamera(); break; } }); function render(){ renderer.render(scene, camera); requestAnimationFrame(render); } </script> </body> </html>
總結(jié)
到此這篇關(guān)于three.js中正交與透視投影相機(jī)的文章就介紹到這了,更多相關(guān)three.js正交與透視投影相機(jī)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
低門檻開發(fā)iOS、Android、小程序應(yīng)用的前端框架詳解
結(jié)合AVM官網(wǎng)的介紹和我自己的一些實(shí)踐經(jīng)驗(yàn),我總結(jié)了一系列AVM的特性,我想這些內(nèi)容足以讓你主動(dòng)去學(xué)習(xí)AVM框架了2021-10-10微信小程序swiper使用網(wǎng)絡(luò)圖片不顯示問題解決
這篇文章主要介紹了微信小程序swiper使用網(wǎng)絡(luò)圖片不顯示問題解決,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12詳解Javascript如何通過async/await優(yōu)雅地使用FileReader
這篇文章主要為大家詳細(xì)介紹了Javascript和Typescript如何通過async/await優(yōu)雅地使用FileReader,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-04-04非常不錯(cuò)的三種簡潔的Tab導(dǎo)航(網(wǎng)頁選項(xiàng)卡)簡析
非常不錯(cuò)的三種簡潔的Tab導(dǎo)航(網(wǎng)頁選項(xiàng)卡)簡析...2007-08-08js中獲取鍵盤按下鍵值event.keyCode、event.charCode和event.which的兼容性詳解
這篇文章主要給大家介紹了關(guān)于Javascript中獲取鍵盤按下鍵值event.keyCode、event.charCode和event.which的兼容性的相關(guān)資料,文中介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來一起看看吧。2017-03-03JavaScript為事件句柄綁定監(jiān)聽函數(shù)實(shí)例詳解
這篇文章主要介紹了JavaScript為事件句柄綁定監(jiān)聽函數(shù)的方法,結(jié)合實(shí)例詳細(xì)分析了常見的事件句柄綁定監(jiān)聽函數(shù)的實(shí)現(xiàn)技巧,并實(shí)例講解了跨瀏覽器的實(shí)現(xiàn)方法,需要的朋友可以參考下2015-12-12