既然是通过相机来渲染场景,那么没有相机,我们也就什么看不到了。THREE.js中提供了Camera类对相机这个角色进行抽象。相机将三维的场景投影到二维的屏幕,根据投影的方式不同,THREE.js中提供了几种不同类型的相机。
正交投影与透视投影
我们先从上面的两种图来理解正交投影与透视投影,我觉得我们可以把正交投影理解为到面的投影,投影线垂直于投影面进行投影,因此物体投影之后的比例是保持不变的。而对于透视
投影我们可以理解为到点的投影,所有的投影线最后都将汇聚于一点,透视投影的特点就是近大远小。
学习Camera之前我们先了解一下THREE.js中使用的坐标系。THREE.js使用的是右手坐标系,想象一下右手握空心拳,手指完全的方向就是从x轴到y轴的方向,而z轴则垂直于手指弯曲的方向从
拳头中心穿过。
正交投影相机OrthographicCamera
构造函数
OrthographicCamera(left, right, top, bottom, near, far)
在上面正交投影的图中,我们想象一样,相机所在的地方有个平面,而相机所在的地点默认是平面的中心点。
那么:left就是视锥左侧面,right就是视锥右侧面,top就是视锥上侧面,而bottom就是视锥下侧面。
near是到距离相机较近的那一面的距离,far是离距离相机较远的那一面的距离,这六个投影面围成的区域就是相机投影的可见区域。
三维空间内,只有在这个区域内的物体才会被相机看到。
实例说明
camera = new THREE.OrthographicCamera(-2, 2, 1.5, -1.5, 1, 10);
camera.position.set(0, 0, 5);
var cubeGeometry = new THREE.CubeGeometry(1,1,1);
var material = new THREE.MeshBasicMaterial({
color : 0xff0000,
wireframe : true
})
var cube = new THREE.Mesh(cubeGeometry, material);
scene.add(cube);
renderer.render(scene, camera);
首先我们实例化一个相机正交相机对象,相机的默认坐标是原点,和立方体重叠无法看到立方体,这里我们设置一下相机的坐标(x,y,z)=(0,0,5)。
采用正交投影的时候,我们发现立方体的前端完全被后端遮盖了,这就是正交投影和透视投影的区别,如果使用透视投影,那么根据近大远小的原则,靠近摄像机的一端的投影面积小于远离相机一端的投影面积。
长宽比例
但是这里有一个很奇怪的问题,命名创建的是一个长度为1的正方体,为啥投影是长方体?这里canvas面板的长宽比是2:1,但是相机的(right-left)/(top-bottom)比例是4:3,因此
垂直方向上面被压缩了,所以显示的是一个长方体。
将(right-left)/(top-bottom)的比例同样调整为2:1
camera = new THREE.OrthographicCamera(-2, 2, 1, -1, 1, 10)
相机位置
相机默认的坐标位置是(0,0,0),上面的例子中我们把相机的坐标设置为(0,0,5),即z轴上面。现在我们来移动相机的位置看看投影出来的立方是什么样子的。
camera.position.set(1, 0, 5)
在x轴方向把相机右移1个单位
发现相对于画面中心,立方体往左移动了一个单位,很容易理解这里的主体是相机,相机右移,那么立方体相对于相机不就是左移了么?
camera.position.set(2, -2, 5);
把相机挪动到立方体的下方?这个时候镜头里面一片漆黑,看不到立方体了。因为镜头默认的方向是朝着z轴的负方向,我们让它朝着原点即可。
camera.lookAt(new THREE.Vector3(0,0,0));
透视投影相机(PerspectiveCamera)
构造函数
PerspectiveCamera(fov, aspect, near, far)
- fov 可视角度
- aspect 为width/height,通常设置为canvas元素的高宽比。
- near近端距离
- far远端距离
只有离相机的距离大于near值,小于far值,且在相机的可视角度之内,才能被相机投影到。
实例说明
renderer = new THREE.WebGLRenderer();
renderer.setSize(400,300);
document.body.appendChild(renderer.domElement);
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(45, 4/3, 1, 10000);
camera.position.set(0,0,5);
var mess = new THREE.Mesh(new THREE.CubeGeometry(1,1,1), new THREE.MeshBasicMaterial({
color : 0xff0000,
wireframe : true
}));
scene.add(mess);
renderer.render(mess, camera);
改变视角大小
camera = new THREE.PerspectiveCamera(60, 4/3, 1, 10000);
我们把视角由45度变为60度,发现立方体变小了,很容易理解,视角变大之后,可以看到的范围变大了,但是立方体本身的大小没有变,那么相对于整个投影来说,立方体就变小了,不信你把眼睛睁大最大试试( ̄▽ ̄)”。