乐趣区

Threejs相机对象正投影OrthographicCamera透视投影PerspectiveCamera

Three.js 相机对象(正投影OrthographicCamera、透视投影PerspectiveCamera)

针对不同应用的三维场景需要使用不同的投影方式,比如机械、工业设计领域常常采用正投影 (平行投影), 游戏场景往往采用透视投影(中心投影)。为了完成三维场景不同的投影方式,three.js 封装 WebGL API 和相关算法,提供了正投影OrthographicCamera、透视投影PerspectiveCamera 等相机对象。

个人 WebGL/Three.js 技术博客

正投影和透视投影简单解释

下面对正投影相机和透视投影相机的投影算法进行简单介绍,对于初学者你有一个印象就可以,如果想深入了解,可以学习图形学或者阅读 threejs 官方源码 src 目录下文件 OrthographicCamera.js 和 PerspectiveCamera.js

生活中的物体都是三维的,但是人的眼睛只能看到正面,不能看到被遮挡的背面,三维几何体在人眼睛中的效果就像一张相机拍摄的二维照片,你看到的是一个 2D 的投影图。空间几何体转化为一个二维图的过程就是投影,不同的投影方式意味着投影尺寸不同的算法。

生活中的物体都是三维的,但是人的眼睛只能看到正面,不能看到被遮挡的背面,三维几何体在人眼睛中的效果就像一张相机拍摄的二维照片,你看到的是一个 2D 的投影图。空间几何体转化为一个二维图的过程就是投影,不同的投影方式意味着不同的算法。

对于正投影而言,一条直线放置的角度不同,投影在投影面上面的长短不同;对于透视投影而言,投影的结果除了与几何体的角度有关,还和距离相关,人的眼睛观察世界就是透视投影,比如你观察一条铁路距离越远你会感到两条轨道之间的宽度越小。无论正投影还是透视投影,three.js 都对相关的投影算法进行了封装,大家只需要根据不同的应用场景自行选择不同的投影方式。使用 OrthographicCamera 相机对象的时候,three.js 会按照正投影算法自动计算几何体的投影结果;使用 PerspectiveCamera 相机对象的时候,three.js 会按照透视投影算法自动计算几何体的投影结果。

正投影相机对象OrthographicCamera

构造函数格式:OrthographicCamera(left, right, top, bottom, near, far)

OrthographicCamera 构造函数参数列表,参数的数据类型都是 number。

  • left——渲染空间的左边界
  • right——渲染空间的右边界
  • top——渲染空间的上边界
  • bottom——渲染空间的下边界
  • near——near 属性表示的是从距离相机多远的位置开始渲染,一般情况会设置一个很小的值。默认值 0.1
  • far——far 属性表示的是距离相机多远的位置截止渲染,如果设置的值偏小小,会有部分场景看不到。默认值 1000

三维场景中坐标值不在三维空间中的网格模型不会被渲染出来,会被剪裁掉,比如你把上面代码中 far 参数的值从 1000 更改为 420,你会发现长方体的一部分无法显示。

注意:左右边界的距离与上下边界的距离比值与画布的渲染窗口的宽高比例要一致,否则三维模型的显示效果会被单方向不等比例拉伸

OrthographicCamera 构造函数本质上是对 WebGL 投影矩阵的封装,宽度 width、高度 height 越大,三维模型顶点的位置坐标就会越大,超出可视区域的网格模型就会被剪裁掉,不会再显示在屏幕上,大家还可以看到参数 left 与 right、参数式 top 与 bottom 互为相反数,这样做的目的是能够是 lookAt 指向的对象能够显示在 canvas 画布的中间位置。

/**
 * 正投影相机设置
 */
var width = window.innerWidth; // 窗口宽度
var height = window.innerHeight; // 窗口高度
var k = width / height; // 窗口宽高比
var s = 200; // 三维场景显示范围控制系数,系数越大,显示的范围越大
// 创建相机对象
var camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
camera.position.set(200, 300, 200); // 设置相机位置
camera.lookAt(scene.position); // 设置相机方向(指向的场景对象)

透视投影相机对象PerspectiveCamera

构造函数格式:PerspectiveCamera(fov, aspect, near, far)

PerspectiveCamera 构造函数参数列表,参数的数据类型都是 number。

  • fov——fov 表示视场,所谓视场就是能够看到的角度范围,人的眼睛大约能够看到 180 度的视场,视角大小设置要根据具体应用,一般游戏会设置 60~90 度。默认值 45
  • aspect——aspect 表示渲染窗口的长宽比,如果一个网页上只有一个全屏的 canvas 画布且画布上只有一个窗口,那么 aspect 的值就是网页窗口客户区的宽高比 window.innerWidth/window.innerHeight
  • near——near 属性表示的是从距离相机多远的位置开始渲染,一般情况会设置一个很小的值。默认值 0.1
  • far——far 属性表示的是距离相机多远的位置截止渲染,如果设置的值偏小小,会有部分场景看不到。默认值 1000

/**
 * 透视投影相机设置
 */
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); // 设置相机方向(指向的场景对象)

camera 对象的基类是 Object3D, 具有.posiiotn 属性,通过 position 属性设置相机的位置。lookAt 方法用来指定相机拍摄对象的坐标位置,.lookAt()方法的参数是 Vector3 对象,可以手动定义new THREE.Vector3(x,y,z), 实际开发的时候,你希望相机对准那个对象,就返回那个对象的位置属性值,比如上面代码中的 scene.position,就表示返回 scene 的位置坐标,如果把 scene 换成网格模型对象就是 mesh.position,上面的网格模型是一个立方体,具体的 position 属性值就是立方体的几何中心。通过观察点的位置和 lookAt 方法指向的位置就可以计算出相机的拍摄角度。

对于的透视投影,相机位置与 lookAt 指向的观察目标位置越小,场景中的三维模型放大倍数越大,同时超出的部分会被剪裁掉,比如更改上面代码 camera.position.set(100,200,200); 为 (20,20,20),测试结果你会发现立方体几何体放大显示,超出区域被剪裁。

如果是观察一个产品外观效果,相机就位于几何体的外面,如果是室内漫游预览,就把相机放在房间三维模型的内部。

退出移动版