照相机就是这样一个抽象,它定义了三维空间到二维屏幕的投影方式,用“照相机”这样一个类比,可以使我们直观地理解这一投影方式。
而针对投影方式的不同,照相机又分为正交投影照相机与透视投影照相机。我们需要为自己的程序选择合适的照相机。

2.2 正交投影vs透视投影

举个简单的例子来说明正交投影与透视投影照相机的区别。使用透视投影照相机获得的结果是类似人眼在真实世界中看到的有“近大远小”的效果(如下图中的(a));而使用正交投影照相机获得的结果就像我们在数学几何学课上老师教我们画的效果,对于在三维空间内平行的线,投影到二维空间中也一定是平行的(如下图中的(b))。

那么,你的程序需要正交投影还是透视投影的照相机呢?
一般说来,对于制图、建模软件通常使用正交投影,这样不会因为投影而改变物体比例;而对于其他大多数应用,通常使用透视投影,因为这更接近人眼的观察效果。

2.3 正交投影照相机

参数介绍
正交投影照相机(Orthographic Camera)设置起来较为直观,它的构造函数是:

THREE.OrthographicCamera(left, right, top, bottom, near, far) 

这六个参数分别代表正交投影照相机拍摄到的空间的六个面的位置,这六个面围成一个长方体,我们称其为视景体(Frustum)。只有在视景体内部(下图中的灰色部分)的物体才可能显示在屏幕上,而视景体外的物体会在显示之前被裁减掉。

为了保持照相机的横竖比例,需要保证(right - left)与(top - bottom)的比例与Canvas宽度与高度的比例一致。
near与far都是指到照相机位置在深度平面的位置,而照相机不应该拍摄到其后方的物体,因此这两个值应该均为正值。为了保证场景中的物体不会因为太近或太远而被照相机忽略,一般near的值设置得较小,far的值设置得较大,具体值视场景中物体的位置等决定。
实例说明
下面,我们通过一个具体的例子来解释正交投影照相机的设置。
例2.3.1
基本设置
设置照相机:

var camera = new THREE.OrthographicCamera(-2, 2, 1.5, -1.5, 1, 10);
camera.position.set(0, 0, 5);
scene.add(camera);

在原点处创建一个边长为1的正方体,为了和透视效果做对比,这里我们使用wireframe而不是实心的材质,以便看到正方体后方的边:

var cube = new THREE.Mesh(new THREE.CubeGeometry(1, 1, 1),
new THREE.MeshBasicMaterial({
color: 0xff0000,
wireframe: true
})
);
scene.add(cube);

得到的效果是:

我们看到正交投影的结果是一个正方形,后面的边与前面完全重合了,这也就是正交投影与透视投影的区别所在。
长宽比例
这里,我们的Canvas宽度是400px,高度是300px,照相机水平方向距离4,垂直方向距离3,因此长宽比例保持不变。为了试验长宽比例变化时的效果,我们将照相机水平方向的距离减小为2:

var camera = new THREE.OrthographicCamera(-1, 1, 1.5, -1.5, 1, 10); 

得到的结果是水平方向被拉长了:

照相机位置
接下来,我们来看看照相机位置对渲染结果的影响。在之前的例子中,我们将照相机设置在(0, 0, 5)位置,而由于照相机默认是面向z轴负方向放置的,所以能看到在原点处的正方体。现在,如果我们将照相机向右移动1个单位:

var camera = new THREE.OrthographicCamera(-2, 2, 1.5, -1.5, 1, 10);
camera.position.set(1, 0, 5);

得到的效果是物体看上去向左移动了:

仔细想一下的话,这也不难理解。就好比你人往右站了,看起来物体就相对往左移动了。
那么,正交投影照相机在设置时,是否需要保证left和right是相反数呢?如果不是,那么会产生什么效果呢?下面,我们将原本的参数(-2, 2, 1.5, -1.5, 1, 10)改为(-1, 3, 1.5, -1.5, 1, 10),即,将视景体设置得更靠右:

var camera = new THREE.OrthographicCamera(-1, 3, 1.5, -1.5, 1, 10);
camera.position.set(0, 0, 5);

得到的结果是:

这与之前向右移动照相机得到的效果是等价的。

换个角度看世界
到现在为止,我们使用照相机都是沿z轴负方向观察的,因此看到的都是一个正方形。现在,我们想尝试一下仰望这个正方体。我们已经学会设置照相机的位置,不妨将其设置在(4, -3, 5)处:

camera.position.set(4, -3, 5);

是现在照相机沿z轴负方向观察的,因此观察不到正方体,只看到一片黑。我们可以通过lookAt函数指定它看着原点方向:

camera.lookAt(new THREE.Vector3(0, 0, 0)); 

这样我们就能过仰望正方体啦:

不过一定要注意,lookAt函数接受的是一个THREE.Vector3的实例,因此千万别写成camera.lookAt(0, 0, 0),否则非但不能得到理想的效果,而且不会报错,使你很难找到问题所在。
现在,恭喜你学会设置正交照相机了!虽然它看起来较为简单,但是加入动画、交互等因素后,可以为你的应用程序增色不少的!


2.4 透视投影照相机

参数介绍
透视投影照相机(Perspective Camera)的构造函数是:

THREE.PerspectiveCamera(fov, aspect, near, far) 

让我们通过一张透视照相机投影的图来了解这些参数。

透视图中,灰色的部分是视景体,是可能被渲染的物体所在的区域。fov是视景体竖直方向上的张角(是角度制而非弧度制),如侧视图所示。
aspect等于width / height,是照相机水平方向和竖直方向长度的比值,通常设为Canvas的横纵比例。
near和far分别是照相机到视景体最近、最远的距离,均为正值,且far应大于near。
实例说明
下面,我们从一个最简单的例子学习设置透视投影照相机。
基本设置
例2.4.1
设置透视投影照相机,这里Canvas长400px,宽300px,所以aspect设为400 / 300:

var camera = new THREE.PerspectiveCamera(45, 400 / 300, 1, 10);
camera.position.set(0, 0, 5);
scene.add(camera);

和例2.3.1一样,设置一个在原点处的边长为1的正方体:

var cube = new THREE.Mesh(new THREE.CubeGeometry(1, 1, 1),
new THREE.MeshBasicMaterial({
color: 0xff0000,
wireframe: true
})
);
scene.add(cube);

得到的结果是:

对比例2.3.1正方形的效果,透视投影可以看到全部的12条边,而且有近大远小的效果,这也就是与正交投影的区别。
竖直张角
接下来,我们来看下fov的改变对渲染效果的影响。我们将原来的45改为60,得到这样的效果:

为什么正方体显得更小了呢?我们从下面的侧视图来看,虽然正方体的实际大小并未改变,但是将照相机的竖直张角设置得更大时,视景体变大了,因而正方体相对于整个视景体的大小就变小了,看起来正方形就显得变小了。

注意,改变fov并不会引起画面横竖比例的变化,而改变aspect则会改变横竖比例。这一效果类似2.3节,此处不再重复说明。

系列博文-Three.js入门指南(张雯莉)-照相机的更多相关文章

  1. 系列博文-Three.js入门指南(张雯莉)-网格 setInterval方法 requestAnimationFrame方法 使用stat.js记录FPS

    第6章 动画 在本章之前,所有画面都是静止的,本章将介绍如果使用Three.js进行动态画面的渲染.此外,将会介绍一个Three.js作者写的另外一个库,用来观测每秒帧数(FPS). CSS3动画那么 ...

  2. 系列博文-Three.js入门指南(张雯莉)-静态demo和three.js功能概览

    一:一个最简单的静态DEMO //body加载完后触发init() //WebGL的渲染是需要HTML5 Canvas元素的,你可以手动在HTML的<body>部分中定义Canvas元素, ...

  3. 一起学微软Power BI系列-官方文档-入门指南(1)Power BI初步介绍

    我们在前一篇文章微软新神器-Power BI,一个简单易用,还用得起的BI产品中,我们初步介绍了Power BI的基本知识.由于Power BI是去年开始微软新发布的一个产品,虽然已经可以企业级应用, ...

  4. 一起学微软Power BI系列-官方文档-入门指南(2)获取源数据

    我们在文章: 一起学微软Power BI系列-官方文档-入门指南(1)Power BI初步介绍中,我们介绍了官方入门文档的第一章.今天继续给大家介绍官方文档中,如何获取数据源的相关内容.虽然是英文,但 ...

  5. 一起学微软Power BI系列-官方文档-入门指南(3)Power BI建模

    我们前2篇文章:一起学微软Power BI系列-官方文档-入门指南(1)Power BI初步介绍 和一起学微软Power BI系列-官方文档-入门指南(2)获取源数据 中,我们介绍了官方入门文档与获取 ...

  6. 一起学微软Power BI系列-官方文档-入门指南(4)Power BI的可视化

    在前面的系列文章中,我们介绍了官方有关获取数据,以及建模的原始文档和基本介绍.今天继续给大家介绍官方文档中,有关可视化的内容.实际上获获取数据和建模更注重业务关系的处理,而可视化则关注对数据的解读.这 ...

  7. 一起学微软Power BI系列-官方文档-入门指南(5)探索数据奥秘

    我们几篇系列文章中,我们介绍了官方入门文档与获取数据等基本知识.今天继续给大家另外一个重点,探索数据奥秘.有了数据源,有了模型,下一步就是如何解析数据了.解析数据的过程需要很多综合技能,不仅仅是需要掌 ...

  8. 一起学微软Power BI系列-官方文档-入门指南(6)Power BI与Excel

    今天介绍了官方入门文档中有关PowerBI和Excel的知识.前几篇入门文档有点仓促,加上最近时间的研究,会有更多技巧性和入门型的文章或者视频发布,最后2篇入门文档将更加详细一点,因为部分文章进行简单 ...

  9. 一起学微软Power BI系列-官方文档-入门指南(7)发布与共享-终结篇+完整PDF文档

    接触Power BI的时间也只有几个月,虽然花的时间不多,但通过各种渠道了解收集,谈不上精通,但对一些重要概念和细节还是有所了解.在整理官方文档的过程中,也熟悉和了解了很多概念.所以从前到后把微软官方 ...

随机推荐

  1. Android Data Binding语法解析(二)

    上篇我们知道了Data Binding的最简单的用法,那么Data Binding其中最为重要也是最复杂的其实就是在xml布局文件中给对应的控件进行数据绑定了,接下来就一一说明Data Binding ...

  2. C语言实现字符串中(10进制和16进制)转成十进制数

    如何将字符串中的10进制数和16进制数提取出来,看以下代码: #include <stdio.h> typedef char TUINT8 ; typedef int TUINT32; T ...

  3. CoordinatorLayout

    CoordinatorLayout作为"super-powered FrameLayout"基本实现两个功能:  1.作为顶层布局  2.调度协调子布局 CoordinatorLa ...

  4. Android逆向分析(2) APK的打包与安装背后的故事

    前言 上一次我们反编译了手Q,并遇到了Apktool反编译直接crash的问题,虽然笔者很想在这次解决这个问题,但在解决途中,发现该保护依赖于很多知识,所以本次先插入一下,正所谓知其然知其所以然,授之 ...

  5. ios的位置和方向(来自苹果官方文档,仅供简单参考)

    取得用户的当前位置 Core Location框架使您可以定位设备的当前位置,并将这个信息应用到程序中.该框架利用设备内置的硬件,在已有信号的基础上通过三角测量得到固定位置,然后将它报告给您的代码.在 ...

  6. orale中如何获取当前月份?

    就本人所知,在oracle中,有两种方式可以提取系统的当前月份: 1.使用extract 函数,具体用法看SQL语句: select extract(month from sysdate) as &q ...

  7. obj-c编程10:Foundation库中类的使用(6)[线程和操作队列]

    任何语言都不能避而不谈线程这个东东,虽然他是和平台相关的鸟,虽说unix哲学比较讨厌线程的说...线程不是万能灵药,但有些场合还是需要的.谈到线程就不得不考虑同步和死锁问题,见如下代码: #impor ...

  8. java 中 printf()语句的理解

    对print和println的理解很简单,今天突然接触到printf(),有点懵,整理了下也帮自己理一理 printf是格式化输出的形式 下在举个例子: package other; public c ...

  9. mysql之数据库的增删改查

    一.DDL 1.创建数据库 create database 数据库名 *数据库名不能中文, 不能数字正常英文 , 关键字会自动变大写 2.删除数据库 drop database 数据库名 3.使用数据 ...

  10. JTA 分布式事务

    什么是JTA - 2009-07-25 18:31:06|  分类: 技术文章|举报|字号 订阅     什么是JTA? Java Transaction API(Java事务API) (JTA)Ja ...