深入理解three.js中正交摄像机OrthographicCamera

前言

深入理解Three.js中透视投影照相机PerspectiveCamera那篇 文章中讲解了透视投影摄像机的工作原理以及对应一些参数的解答, 那篇文章中也说了会单独讲解Three.js中另一种常用 的摄像机正交摄像机OrthographicCamera,这篇文章将 会详细的讲解正交摄像机的工作原理和其对应参数的用法, 当然,为了能够让读者更加直观的理解正交摄像机, 我会制作一个与正交摄像机相关的demo来直观的让读者感受正交摄像机的魅力。

院理说明

深入理解Three.js中透视投影照相机PerspectiveCamera文章中提到过正交摄像机 和透视投影摄像机最大的区别是投影到的物体大小不受距离的影响, 说直白点就是透视投影摄像机投影物体是通过点(下图a),相当于 我们的眼睛,距离越远,能够看到的部分也就越小。正交摄像 机投影物体是通过平面(下图b),无论距离有多远,投射到二维平面的线始终 的是平行的,所以看上去就会感觉物体的大小没有受到任何影响。

正交摄像机参数说明

实现一个简单正交摄像机的代码如下:

var camera = new THREE.OrthographicCamera( width / - 2, width / 2, height / 2, height / - 2, 1, 1000 );
scene.add( camera );

new THREE.OrthographicCamera()构造 函数用于创建一个正交摄像机,该构造函数中有六个参数, 分别是leftrighttopbottomnearfar

left — 摄像机视锥体左侧面。

right — 摄像机视锥体右侧面。

top — 摄像机视锥体上侧面。

bottom — 摄像机视锥体下侧面。

near — 摄像机视锥体近端面。

far — 摄像机视锥体远端面。

透视投影相机实例

其中,left的值不能够大于right的值, 而且leftright设置的值必须位于摄像机 position中x坐标的两侧,否则将看不到影像。 对应的topbottom也一样,bottom值不能大于 top值,且位于摄像机position坐标y值两边, 否则也会看不到投影影像。nearfar分别用 来设置摄像机近端面和远端面,也就是通常 说的最近距离和最远距离。near设置越小, 投影的影像就越大,反之则越小。但是near 值并不是影响投影物体大小最大的,影响 投影物体尺寸最大的还是leftrighttopbottom四个参数,而且也影响投影 物体的形状,所以在设置这四个参数的 时候,leftright之间的距离和topbottom之间的距离的比例一定要和原始 的canvas画布比例相等,不然会导致投 影的物体形状变形。

为了能够更好的理解正交摄像机, 写了一个小demo,代码如下,代码中我们统一 设置摄像机的位置对应xyz坐标为0,15,70。 为了能够有比对性,在场景中我创建了一个网格, 在网格上创建了一个黄色的球体。接下来我们依次比较下不同情况下的投影。

var scene = new THREE.Scene();
console.log(scene)
var dom = document.getElementById('starry-frame');
var camera = new THREE.PerspectiveCamera( 45, dom.clientWidth / dom.clientHeight, 0.1, 1000 );
camera.position.set(0,15,70);
var renderer = new THREE.WebGLRenderer();
renderer.setSize( dom.clientWidth, dom.clientHeight );
dom.appendChild( renderer.domElement );
var geometry = new THREE.SphereGeometry( 5, 32, 32 );
var material = new THREE.MeshBasicMaterial( {color: 0xffff00} );
var sphere = new THREE.Mesh( geometry, material );
sphere.position.set(0,5,0)
scene.add( sphere );
var gridHelper = new THREE.GridHelper(50, 60);
gridHelper.rotation.y = -Math.PI / 2;
scene.add(gridHelper);
function render() {
   renderer.render(scene,camera)
   requestAnimationFrame(render)
}
render()

1 透视投影摄像机模式

其中,第一张图是设置了球体position为0,5,0; 第二张图图是设置球体position为0,5,-30。 可以看出,在透视投影模式下,物体的大小 随着物体距离摄像机的距离而变化,距离越大物体大小越小。

2 正交投影中leftright距离与topbottom距离比例与原始canvas画布比例关系。

其中,第一张图是设置了球体position为0,5,0; 第二张图图是设置球体position为0,5,-30。 可以看出,在透视投影模式下,物体的大小 随着物体距离摄像机的距离而变化,距离越大物体大小越小。

3 正交摄像机中leftright相加,topbottom相加值与摄像机position中x,y坐标关系。

第一张图表示leftright相加值小于摄像机x坐标; 第二张图表示leftright值相加大于摄像机x坐标值; 第三张图为topbottom相加值大于摄像机y坐标值; 第四张图为topbottom相加值小于摄像机y坐标值。 可以看出leftrighttopbottom相加值与摄像机中心 点坐标有便宜的时候物体的图像和位置都会出现较大误差。

4 正交摄像机中leftrighttopbottom值与摄像机坐标关系。

left值大于摄像机x坐标值, right小于摄像机x坐标值, top大于摄像机y坐标值, bottom小于摄像机y坐标值都将会导致摄像机映射不出物体图像,如下图,可以看到场景中一片漆黑。

正交摄像机实例

说一说做这个实例的初衷,单纯为了理解正交摄像机的原理通过 上面讲述的那个例子就可以了,所以下面的这个实例不仅仅是为了能 够让读者更好的理解正交摄像机才去写的。为了能够更好的理解 Three.js中正交摄像机,所以就在官网中浏览对应的案例,感觉无论 是场景,还是视觉都挺不错的,再加上当时我女儿特别喜欢Three.js中 实例中的那只鸟,所以我就决定将两个实力合并在一起,纯粹是为了讨女 儿喜欢,要知道女儿高兴了才能不打搅我学习,还望读者海涵。实例中移 动的山使用的就是正交摄像机,所以可以看到无论如何移动,对应的山 的高度和大小都是不会发生变化的,空中飞翔的鸟通过透视投影摄像机。

实例示意图如下:

后话

希望上述讲解能够帮助到阅读这篇博文的读者!!!

预览地址:深入理解three.js中正交摄像机OrthographicCamera

下载地址:深入理解three.js中正交摄像机OrthographicCamera