three.js入门(5)照相机

时间:2022-05-15 04:42:26

什么是照相机?

我们使用Three.js创建的场景是三维的,而通常情况下显示屏是二维的,那么三维的场景如何显示到二维的显示屏上呢?照相机就是这样一个抽象,它定义了三维空间到二维屏幕的投影方式,用“照相机”这样一个类比,可以使我们直观地理解这一投影方式。而针对投影方式的不同,照相机又分为正交投影照相机与透视投影照相机。我们需要为自己的程序选择合适的照相机。这两者分别是什么,以及两者有何差异

1.透视投影

使用透视投影照相机获得的结果是类似人眼在真实世界中看到的有“近大远小”的效果,下面是一个透视图,也是最自然的视图,正如你所看到的,距离相机越远的方块,被渲染的越小。

three.js入门(5)照相机

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

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

它接受如下参数:

three.js入门(5)照相机

下图很好的展示了将这些属性结合在一起,从而你能看到什么 :

three.js入门(5)照相机

2.正视投影

使用正视投影,所有方块渲染出来的尺寸都一样,对象和相机之间的居然不会影响渲染结果,如下图展示:

three.js入门(5)照相机

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

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

它接受如下参数:

three.js入门(5)照相机

所有这些属性你都能从下图中找到 :

three.js入门(5)照相机

我们可以通过以下例子带感受下正视投影和透视投影,点击右上角的Orthographic切换到正视投影,Perspective切换到透视投影:

three.js入门(5)照相机

完整代码如下:

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<title>three.js入门(5)照相机</title>
<script src="lib/three.js"></script>
<script src="lib/stats.min.js"></script>
<script src="lib/dat.gui.min.js"></script>
<style>
*{margin: 0;padding: 0;}
</style>
</head>

<body>
<script>
// 渲染器
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
renderer.setClearColor(0xeeeeee);

// 场景
var scene = new THREE.Scene();

// 照相机
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(120, 60, 180);
camera.lookAt(new THREE.Vector3(0, 0, 0));

// 平面
var planeGeometry = new THREE.PlaneGeometry(180, 180);
var planeMaterial = new THREE.MeshLambertMaterial({
color: 0xffffff
});
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.position.set(0, 0, 0);
plane.rotation.x = -0.5 * Math.PI;
scene.add(plane);

// 平行光
var directionalLight = new THREE.DirectionalLight(0xffffff, 0.7);
directionalLight.position.set(-20, 40, 60);
scene.add(directionalLight);
//平行光辅助
var helper = new THREE.DirectionalLightHelper( directionalLight, 20 );
scene.add( helper );

// 辅助轴
var axes = new THREE.AxisHelper(20);
scene.add(axes);

//生成 planeGeometry.parameters.height / 5行 planeGeometry.parameters.width / 5列的小立方体
var cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
for (var j = 0; j < (planeGeometry.parameters.height / 5); j++) {
for (var i = 0; i < planeGeometry.parameters.width / 5; i++) {
var rnd = Math.random() * 0.75 + 0.25;
var cubeMaterial = new THREE.MeshLambertMaterial();
cubeMaterial.color = new THREE.Color(rnd, 0, 0);
var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);

cube.position.z = -((planeGeometry.parameters.height) / 2) + 2 + (j * 5);
cube.position.x = -((planeGeometry.parameters.width) / 2) + 2 + (i * 5);
cube.position.y = 2;
scene.add(cube);
}
}


//统计对象,用户显示FPS
var stats = initStats();

// 用来保存我们想要通过dat.gui修改的那些变量,或点击后运行的函数
var ctrls = {
camera:'Perspective',
Perspective:function(){
if (this.camera === "Perspective") return;
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.camera = "Perspective";
},
Orthographic:function(){
if (this.camera === "Orthographic") return;
camera = new THREE.OrthographicCamera(window.innerWidth / -16, window.innerWidth / 16, window.innerHeight / 16, window.innerHeight / -16, -200, 500);
camera.position.x = 120;
camera.position.y = 60;
camera.position.z = 180;
camera.lookAt(scene.position);
this.camera = "Orthographic";
}
}
//初始化对象,并添加变量的取值范围
var gui = new dat.GUI();
gui.add(ctrls, 'Perspective');
gui.add(ctrls, 'Orthographic');
//添加并监听number变化
gui.add(ctrls, 'camera').listen();

// 调用渲染函数
render();
function render() {
stats.update();
requestAnimationFrame(render);
renderer.render(scene, camera);
}
//初始化统计对象
function initStats(){
var stats = new Stats();
stats.setMode(0);
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
stats.domElement.style.left = '0px';
document.body.appendChild(stats.domElement);
return stats;
}
</script>
</body>
</html>

通过例子应该可以知道正视投影和透视投影的区别了。如果不清楚dat.gui的使用,看three.js入门(3)或者详细使用方式看这里

点击查看 示例代码05-camera.html