three.js透视投影照相机
透视投影照相机(Perspective Camera)的构造函数是:
THREE.PerspectiveCamera(fov, aspect, near, far)
让我们通过一张透视照相机投影的图来了解这些参数。
透视图中,灰色的部分是视景体,是可能被渲染的物体所在的区域。fov
是视景体竖直方向上的张角(是角度制而非弧度制),如侧视图所示。
aspect
等于width / height
,是照相机水平方向和竖直方向长度的比值,通常设为Canvas的横纵比例。
near
和far
分别是照相机到视景体最近、最远的距离,均为正值,且far
应大于near
。
实例说明
下面,我们从一个最简单的例子学习设置透视投影照相机。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head> <script type="text/javascript" src="libs/three.js"></script> <script type="text/javascript"> function init() { var renderer = new THREE.WebGLRenderer({ canvas: document.getElementById('mainCanvas') }); renderer.setClearColor(0x000000); var scene = new THREE.Scene(); // camera // canvas size is 400x300 var camera = new THREE.PerspectiveCamera(45, 400 / 300, 1, 10); camera.position.set(0, 0, 5); scene.add(camera); // a cube in the scene // a cube in the scene var cube = new THREE.Mesh(new THREE.CubeGeometry(1, 1, 1), new THREE.MeshBasicMaterial({ color: 0xff0000, wireframe: true }) ); scene.add(cube); // render renderer.render(scene, camera); } </script> </head> <body onload="init()"> <canvas id="mainCanvas" width="400px" height="300px" ></canvas> </body> </html>
接下来,我们来看下fov
的改变对渲染效果的影响。我们将原来的45
改为60
,得到这样的效果:
为什么正方体显得更小了呢?我们从下面的侧视图来看,虽然正方体的实际大小并未改变,但是将照相机的竖直张角设置得更大时,视景体变大了,因而正方体相对于整个视景体的大小就变小了,看起来正方形就显得变小了。
注意,改变fov
并不会引起画面横竖比例的变化,而改变aspect
则会改变横竖比例。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Three框架</title> <script src="libs/Three.js"></script> <style type="text/css"> div#canvas-frame { border: none; cursor: pointer; width: 100%; height: 600px; background-color: #EEEEEE; } </style> <script> var renderer; function initThree() { width = document.getElementById('canvas-frame').clientWidth; height = document.getElementById('canvas-frame').clientHeight; renderer = new THREE.WebGLRenderer({ antialias : true }); renderer.setSize(width, height); document.getElementById('canvas-frame').appendChild(renderer.domElement); renderer.setClearColor(0xFFFFFF, 1.0); } var camera; function initCamera() { //camera = new THREE.PerspectiveCamera(45, width / height, 1, 10000); camera = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, 10, 1000 ); camera.position.x = 0; camera.position.y = 0; camera.position.z = 600; camera.up.x = 0; camera.up.y = 1; camera.up.z = 0; camera.lookAt({ x : 0, y : 0, z : 0 }); } var scene; function initScene() { scene = new THREE.Scene(); } var light; function initLight() { light = new THREE.AmbientLight(0xFF0000); light.position.set(100, 100, 200); scene.add(light); light = new THREE.PointLight(0x00FF00); light.position.set(0, 0,300); scene.add(light); } var cube; function initObject() { var geometry = new THREE.CylinderGeometry( 70,100,200); var material = new THREE.MeshLambertMaterial( { color:0xFFFFFF} ); var mesh = new THREE.Mesh( geometry,material); mesh.position = new THREE.Vector3(0,0,0); scene.add(mesh); } function threeStart() { initThree(); initCamera(); initScene(); initLight(); initObject(); animation(); } function animation() { changeFov(); renderer.render(scene, camera); requestAnimationFrame(animation); } function setCameraFov(fov) { camera.fov = fov; camera.updateProjectionMatrix(); } function changeFov() { var txtFov = document.getElementById("txtFov").value; var val = parseFloat(txtFov); setCameraFov(val); } </script> </head> <body onload="threeStart();"> <div id="canvas-frame"></div> <div> Fov:<input type="text" value="45" id="txtFov"/>(0到180的值) </div> </body> </html>