three.js正交与透视投影相机
coder_路远 人气:0前言
一个场景之所以会呈现在我们眼前是因为我们具有眼睛,眼睛提供了视觉。换句话说,如果three.js场景中没有这双眼睛,就像电影没有摄像机一样,场景就无法呈现在我们面前?这双眼睛就是相机,可见相机是Three.js场景中不可或缺的一个组件。Three.js库提供了两种不同的相机:正交投影相机和透视投影相机,接下来分别讲解这两种相机以及结合实例的应用。
1 正交投影相机
我们先来看一张示意图:
由图可知正交透视相机总共有6个面,其具备的特点是:场景中远处的物体和近处的物体是一样大的,它并不像我们现实生活中看场景那样,远小近大,而是远近皆一样大;6个面分别为left(左面),right(右面),top(顶面),bottom(底面),near(近面),near(远面),右这六个面组成一个封闭的矩形空间,在这个空间内的一切物体都可见。在设置其参数的时候,下面的关系式一定要成立:
| left / right | = 1,| top / buttom | = 1
正交相机的代码实现为:
var camera = new THREE.OrthographicCamera(left, right, top, bottom, near, far);
2 投射投影相机
投射投影相机才是现实世界中我们看到的场景的体现:远小近大,即我们所说的透视效果。先来看一张示意图:
如图中所示,透视投影相机一共有4个参数:fov(视场,一个角度值), Horizonta Field of View(横向视场),Vertical
Field of View(纵向视场),Near plane(近面), Far plane(远面);由这几个因素,构成一个六面体的封闭空间,在这个空间内的一切物体可见。在设置参数时,需满足:
横向视场 / 纵向视场 = 浏览器窗口的宽/浏览器窗口的高。
其代码实现为:
var camera = new THREE.PerspectiveCamera(fov, width / height, near, far);
3 实例
这里实现两种相机的应用,里面添加了一个简单的交互条,实现的效果如下图:
本例代码如下:
<!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"> //检测webgl的支持情况 if(!Detector.webgl) {Detector.addGetWebGLMessage();} var container; var scene, camera, renderer; window.onload = function main(){ //添加一个div元素 container = document.createElement('div'); document.body.appendChild(container); //创建新场景 scene = new THREE.Scene(); //渲染 //antialias:true增加抗锯齿效果 renderer = new THREE.WebGLRenderer({antialias:true}); renderer.setClearColor(new THREE.Color(0x3399CC));//设置窗口背景颜色为黑 renderer.setSize(window.innerWidth, window.innerHeight);//设置窗口尺寸 //将renderer关联到container,这个过程类似于获取canvas元素 container.appendChild(renderer.domElement); perCamera(); light(); myScene(); render(); }; //创建一个透视相机 function perCamera(){ camera = new THREE.PerspectiveCamera(25, window.innerWidth/window.innerHeight, 1, 1000); camera.position.set(150, 180, 100);//设置相机位置 camera.lookAt(scene.position);//让相机指向场景中心 } //创建一个正交投影相机 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);//设置相机坐标 camera.lookAt(scene.position);//让相机指向场景中心 } //灯光 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 ); } //创建一个立体场景 function myScene(){ //创建平面 var planeGeo = new THREE.PlaneGeometry(100,100,10,10);//创建平面 var planeMat = new THREE.MeshLambertMaterial({ //创建材料 color:0x999999, wireframe:false }); var planeMesh = new THREE.Mesh(planeGeo, planeMat);//创建网格模型 planeMesh.position.set(0, 0, -20);//设置平面的坐标 planeMesh.rotation.x = -0.5 * Math.PI;//将平面绕X轴逆时针旋转90度 scene.add(planeMesh);//将平面添加到场景中 //创建立方体 var cubeGeo1 = new THREE.CubeGeometry(20, 40, 20, 5, 5, 5);//创建立方体 var cubeMat1 = new THREE.MeshLambertMaterial({//创建材料 color:0x333333, wireframe:false }); var cubeMesh1 = new THREE.Mesh(cubeGeo1, cubeMat1);//创建立方体网格模型 cubeMesh1.position.set(15, 10, 0);//设置立方体的坐标 scene.add(cubeMesh1);//将立方体添加到场景中 var cubeGeo2 = new THREE.CubeGeometry(20, 40, 20, 5, 5, 5);//创建立方体 var cubeMat2 = new THREE.MeshLambertMaterial({//创建材料 color:0x333333, wireframe:false }); var cubeMesh2 = new THREE.Mesh(cubeGeo2, cubeMat2);//创建立方体网格模型 cubeMesh2.position.set(-25, 16, 0);//设置立方体的坐标 scene.add(cubeMesh2);//将立方体添加到场景中 var cubeGeo3 = new THREE.CubeGeometry(20, 40, 20, 5, 5, 5);//创建立方体 var cubeMat3 = new THREE.MeshLambertMaterial({//创建材料 color:0x333333, wireframe:false }); var cubeMesh3 = new THREE.Mesh(cubeGeo3, cubeMat3);//创建立方体网格模型 cubeMesh3.position.set(10, 20, -40);//设置立方体的坐标 scene.add(cubeMesh3);//将立方体添加到场景中 } //添加交互工具条 var controls = new function(){ this.相机 = false; }; var gui = new dat.GUI(); gui.add(controls, '相机', ["透视投影相机","正交投影相机"]).onChange(function(e){ switch (e) { case "正交投影相机": orthCamera(); break; case "透视投影相机": perCamera(); break; } }); function render(){ renderer.render(scene, camera); requestAnimationFrame(render); } </script> </body> </html>
总结
加载全部内容