2.1 相机
Three.js库里有两种不同的相机:正交投影相机和透视相机。
本例中的截图如下:

这是一个透视视图,也是最自然的视图。距离相视越远的方块,被渲染得越小。
如果使用右上方的按钮切换到正交投影相机,程序截图如下:

使用正交投影相机时,所有方块渲染出来的大小都一样;对象和相机之间的距离不会影响渲染结果。这种相机通常用在二维游戏中。
在三维游戏中,应尽量使用透视相机,因为它最贴近真实世界。切换相机的代码如下:
this.switchCamera = function() {
if (camera instanceof THREE.PerspectiveCamera) {
camera = new THREE.OrthographicCamera( window.innerWidth / - 16, window.innerWidth / 16,
window.innerHeight / 16, window.innerHeight / - 16, -200, 500 );
camera.position.x = 2;
camera.position.y = 1;
camera.position.z = 3;
camera.lookAt(scene.position);
this.perspective = "Orthographic";
} else {
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.x = 120;
camera.position.y = 60;
camera.position.z = 180;
camera.lookAt(scene.position);
this.perspective = "Perspective";
}
};
在上面这个代码片段里你可以看到,我们创建THREE.PerscpectiveCamera的方法跟创建THREE.OrthographicCamera的方法有些不一样的地方.我们先来看一下THREE.PerspectiveCamera。它接受如下这些参数:
|
参数 |
描述 |
|
fov(视场) |
fov表示视场(field of view)。这是从相机位置能够看到的部分场景。例如,人类有差不多180度的视场,而一些鸟类差不多会有一个完整的、360度的视场。 由于普通的显示器不能完全显示我们看到的景象,所以一般会选择一块较小的区域。对大多数情况下会用60度到90度左右的视场。 推荐默认值:45 |
|
aspect(长宽比) |
这是渲染结果输出区的横向长度和纵向长度的比值。在我们的例子中,由于我们会使用整个窗口作为输出界面,所以会使用这个窗口的长宽比。这个长宽比决定了水平视场和垂直视场之间的比例关系。 推荐默认值:window.innerWidth/window.innerHeight |
|
near(近裁平面) |
从距离相机多近的地方开始渲染场景。通常情况下我们会为这个属性设置一个很小的值,从而可以渲染从相机位置可以看到的所有物体。 默认值:0.1。 |
|
far(远裁平面) |
相机可以从它所处的位置看多远。如果我们将这个值设得太低,那么场景中的一部分可能不会被渲染;如果设得太高,在某些情况下会影响渲染的效率。 默认值:1000。 |
下图展示了这些属性:

要配置正交投影相机,我们得使用其他一些属性。正投影不关心使用什么样的长宽比,或者以什么样的视角观察场景。所有对象渲染的尺寸都一样。下表是正交投影相机的属性:
|
参数 |
描述 |
|
left(左边界) |
可视范围的左平面。你可以将它当做是可渲染部分的左侧边界。如果我们把这个值设为-100,那么你就不会看到任何比这个左侧边界更远的对象 |
|
right(右边界) |
跟left属性一样,不过这次是界面的另外一侧。比这个右侧边界更远的对象不会被渲染 |
|
top(上边界) |
可被渲染空间的最上面 |
|
bottom(下边界) |
可被渲染空间的最下面 |
|
near(近裁平面) |
基于相机所在的位置,从这一点开始渲染场景 |
|
far(远裁平面) |
基于相机所在的位置,一直渲染到场景中的这一点 |
所有这些属性可以在下图中找到:

设定相机的观察目标
我们也可以使用下面的代码设定相机的观察目标:
camera.lookAt(new THREE.Vector3(x,y,z));
在这个例子中,相机的观察目标可以移动,它所指向的位置用一个红点标识了出来。你会看到场景正在从左向右移动。场景并不是真的在移动,而是相机的观察目标在移动(屏幕中央的那个红点),其效果就是场景在从左向右移动。你也可以在这个例子将相机换成正交投影相机。你会看到改变相机观察目标的效果跟使用透视相机时有所不同。
完整代码
<!DOCTYPE html>
<html>
<head>
<title>示例02.01 - 相机</title>
<script src="Scripts/jquery-2.1.3.min.js"></script>
<script src="Scripts/Threejs/three.min.js"></script>
<script src="Scripts/Threejs/stats.js"></script>
<script src="../../../Scripts/Threejs/dat.gui.min.js"></script>
<style>
/* 将margin设置为0,overflow设置为hidden,可让浏览器显示全屏 */
body {
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="Stats-output">
</div>
<!-- 作为canvas容器的div -->
<div id="WebGL-output">
</div>
<script type="text/javascript">
// 页面加载完毕后,就可以运行Three.js了。
$(function () {
var stats = initStats();
// // 创建渲染器,并设置视口大小和清除色
var renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0xEEEEEE, 1.0);
renderer.setSize(window.innerWidth, window.innerHeight);
// 将WebGL的输出canvas放置到div中
$("#WebGL-output").append(renderer.domElement);
// 创建scene对象,用来容纳网格、相机、光源等对象
var scene = new THREE.Scene();
// 创建相机
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.x = 120;
camera.position.y = 60;
camera.position.z = 180;
// 创建一个Plane作为地面
var planeGeometry = new THREE.PlaneBufferGeometry(180,180);
var planeMaterial = new THREE.MeshLambertMaterial({color: 0xffffff});
var plane = new THREE.Mesh(planeGeometry,planeMaterial);
// Plane默认在xy平面,需要将它旋转到xz平面
plane.rotation.x=-0.5*Math.PI;
plane.position.x=0
plane.position.y=0
plane.position.z=0
// 将这个Plane添加到场景中
scene.add(plane);
// 添加绿色盒子
var boxGeometry = new THREE.BoxGeometry(8,4,8);
var boxMaterial = new THREE.MeshLambertMaterial({ color: 0x00ee22 });
for (var j = 0 ; j < (planeGeometry.parameters.height / 9) ; j++) {
for (var i = 0 ; i < planeGeometry.parameters.width / 9 ; i++) {
var box = new THREE.Mesh(boxGeometry, boxMaterial);
box.position.z = -((planeGeometry.parameters.height) / 2) + 2 + (j * 9);
box.position.x = -((planeGeometry.parameters.width) / 2) + 2 + (i * 9);
box.position.y=2;
scene.add(box);
}
}
// 添加一个红色球作为相机的观察目标
var lookAtGeom = new THREE.SphereGeometry(2);
var lookAtMesh = new THREE.Mesh(lookAtGeom, new THREE.MeshLambertMaterial({ color: 0xff0000 }));
scene.add(lookAtMesh);
// 添加平行光
var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.7 );
directionalLight.position.set( -20, 40, 60 );
scene.add(directionalLight);
// 添加环境光
var ambientLight = new THREE.AmbientLight(0x292929);
scene.add(ambientLight);
// 切换相机
var controls = new function() {
this.perspective = "Perspective";
this.switchCamera = function() {
if (camera instanceof THREE.PerspectiveCamera) {
camera = new THREE.OrthographicCamera( window.innerWidth / - 16, window.innerWidth / 16,
window.innerHeight / 16, window.innerHeight / - 16, -200, 500 );
camera.position.x = 2;
camera.position.y = 1;
camera.position.z = 3;
camera.lookAt(scene.position);
this.perspective = "Orthographic";
} else {
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.x = 120;
camera.position.y = 60;
camera.position.z = 180;
camera.lookAt(scene.position);
this.perspective = "Perspective";
}
};
}
var gui = new dat.GUI();
gui.add(controls, 'switchCamera');
gui.add(controls, 'perspective').listen();
render();
var step = 0;
function render() {
stats.update();
step += 0.02;
// 移动相机的观察目标
if (camera instanceof THREE.PerspectiveCamera) {
var x = 10 + (100 * (Math.sin(step)));
camera.lookAt(new THREE.Vector3(x, 30, 0));
lookAtMesh.position.set(x, 10, 0);
} else {
var x = ((Math.cos(step)));
camera.lookAt(new THREE.Vector3(x, 0, 0));
lookAtMesh.position.set(x, 10, 0);
}
requestAnimationFrame(render);
renderer.render(scene, camera);
}
function initStats() {
var stats = new Stats();
stats.setMode(0); // 0: fps, 1: ms
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
$("#Stats-output").append( stats.domElement );
return stats;
}
});
</script>
</body>
</html>
文件下载(已下载 1951 次)
发布时间:2015/7/31 下午10:18:14 阅读次数:6729
