打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Three.js 摄像机的使用详解(透视投影摄像机、正交投影摄像机)

一、两种摄像机的区别与比较

Three.js 库提供了两种不同的摄像机:透视投影摄像机和正交投影摄像机。
  • 透视投影摄像机:这种摄像机的效果更贴近真实世界。也就是物体离摄像机越远,它们就会被渲染得越小。
  • 正交投影摄像机:对象相对于摄像机的距离对渲染的结果是没有影响的,也就是说物体不离摄像头多远,渲染出来的尺寸都是一样的。这中摄像机通常被用于二位游戏中,比如《模拟城市4》或早期的《文明》。

1,效果图

(1)页面打开后默认使用的是“透视投影摄像机”。

(2)点击控制面板上的“切换摄象机”按钮,可以实现两种类型的摄象机相互切换。下面是“正交投影摄像机”效果图。

2,样例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>hangge.com</title>
    <script type="text/javascript" src="../libs/three.js"></script>
    <script type="text/javascript" src="../libs/stats.js"></script>
    <script type="text/javascript" src="../libs/dat.gui.js"></script>
    <style>
        body {
            margin: 0;
            overflow: hidden;
        }
    </style>
</head>
<body>
<!-- 用于显示统计图形 -->
<div id="Stats-output">
</div>
<!-- 作为Three.js渲染器输出元素 -->
<div id="WebGL-output">
</div>
<script type="text/javascript">
    //网页加载完毕后会被调用
    function init() {
        ////初始化统计对象
        var stats = initStats();
        //创建一个场景(场景是一个容器,用于保存、跟踪所要渲染的物体和使用的光源)
        var scene = new THREE.Scene();
        //创建一个摄像机对象(摄像机决定了能够在场景里看到什么)
        var camera = new THREE.PerspectiveCamera(45,
          window.innerWidth / window.innerHeight, 0.1, 1000);
        camera.position.x = 40;
        camera.position.y = 20;
        camera.position.z = 60;
        camera.lookAt(scene.position);
        //创建一个WebGL渲染器并设置其大小
        var renderer = new THREE.WebGLRenderer();
        renderer.setClearColor(new THREE.Color(0xEEEEEE));
        renderer.setSize(window.innerWidth, window.innerHeight);
        //创建一个平面
        var planeGeometry = new THREE.PlaneGeometry(50, 50);
        var planeMaterial = new THREE.MeshLambertMaterial({color: 0xffffff});
        var plane = new THREE.Mesh(planeGeometry, planeMaterial);
        //设置平面的旋转角度和位置
        plane.rotation.x = -0.5 * Math.PI;
        plane.position.x = 0;
        plane.position.y = 0;
        plane.position.z = 0;
        //将平面添加场景中
        scene.add(plane);
        //在平面上方添加一个个小方块
        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);
            }
        }
        //添加环境光
        var ambientLight = new THREE.AmbientLight(0x292929);
        scene.add(ambientLight);
        //添加平行光
        var directionalLight = new THREE.DirectionalLight(0xffffff, 0.7);
        directionalLight.position.set(-20, 40, 60);
        scene.add(directionalLight);
        //将渲染的结果输出到指定页面元素中
        document.getElementById("WebGL-output").appendChild(renderer.domElement);
        //dat.GUI对象使用的配置(存放有所有需要改变的属性的对象)
        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 = 40;
                  camera.position.y = 20;
                  camera.position.z = 60;
                  camera.lookAt(scene.position);
                  this.perspective = "Orthographic";
              } else {
                  //切换成透视投影摄像机
                  camera = new THREE.PerspectiveCamera(45,
                    window.innerWidth / window.innerHeight, 0.1, 1000);
                  camera.position.x = 40;
                  camera.position.y = 20;
                  camera.position.z = 60;
                  camera.lookAt(scene.position);
                  this.perspective = "Perspective";
              }
          };
        };
        //创建dat.GUI,传递并设置属性
        var gui = new dat.GUI();
        gui.add(controls, 'switchCamera').name("切换摄像机");
        gui.add(controls, 'perspective').listen();
        //渲染场景
        render();
        //渲染场景
        function render() {
            stats.update();
            //通过requestAnimationFrame方法在特定时间间隔重新渲染场景
            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';
            //将统计对象添加到对应的<div>元素中
            document.getElementById("Stats-output").appendChild(stats.domElement);
            return stats;
        }
    }
    //确保init方法在网页加载完毕后被调用
    window.onload = init
</script>
</body>
</html>

二、摄像机创建方法参数

THREE.PerspectiveCameraTHREE.OrthographicCamera 这两种摄像机创建方法是不一样的,它们接收的参数分别如下:

1,透视投影摄像机(ThREE.PerspectiveCamera)


 参数 描述 推荐默认值
 fov  表示视场。这是在摄像机中能够看到的那部分场景。
 比如:人类有接近 180 度的视场,而有些鸟类有接近 360 度的视场。但由于计算机不能完全显示我们能够看到的景象,所以一般会选择一块较小的区域。对于游戏而言,视场大小通常为 60 度到 90 度。
 50
 aspect(长宽比)  这是渲染结果的横向尺寸和纵向尺寸的比值。这个长宽比决定了横向视场和纵向视场的比例关系。
 在上面的样例中,由于使用窗口作为输出界面,所以使用的是窗口的长宽比。
 window.innerWidth / window.innerHeight
 near(近面距离)  该属性定义了从距离摄像机多近的距离开始渲染。
 通常情况下这个值会设置得尽量小,从而能够渲染从摄像机位置可以看到的所有物体。
 0.1
 far(远面距离)  该属性定义了摄像机从它所出的位置能够看多远。
  • 如果这个值设置得较小,那么场景中有一部分不会被渲染。
  • 如果设置的较大,那么就会影响渲染的性能。
 1000
 zoom(变焦)  可以使用该属性放大或缩小场景。
  • 如果这个值设置得小于 1,那么场景就会被缩小。
  • 如果这个值设置得大于 1,那么场景就会被放大。
  • 如果设置的值为负数,那么场景就会上下颠倒。
 1000

2,正交投影摄像机(ThREE.OrthographicCamera)

由于正交投影摄像机渲染出的物体大小都是一样的,所以它并不关心使用什么长宽比,或者以什么样的视角了观察场景。
我们使用正交投影摄像机时,要定义的是一个需要被渲染的方块区域。

 参数 描述
 left(左边界)  可视范围的左平面。我们可以将它看作是渲染部分的左边界。任何比这个左边界的物体都不会被渲染。
 right(右边界)  和 left 属性一样,只不过它定义的是可被渲染区域的另一个侧面。任何比这个右边界远的物体都不会被渲染。
 top(上边界)  可被渲染区域的最上面。
 bottom(下边界)  可被渲染区域的最下面。
 near(近面距离)  基于摄像机所在的位置,从这一点开始渲染场景。
 far(远面距离)  基于摄像机所在的位置,渲染场景到这一点为止。
 zoom(变焦)  可以使用该属性放大或缩小场景。
  • 如果这个值设置得小于 1,那么场景就会被缩小。
  • 如果这个值设置得大于 1,那么场景就会被放大。
  • 如果设置的值为负数,那么场景就会上下颠倒。

三、将摄像机聚焦在指定点上

1,改变摄像机所指向的位置

通常来说,摄像机会指向场景的中心,用坐标表示就是 position(0,0,0)。但我们可以通过 lookAt() 方法改变摄像机所指向的位置:
1
camera.lookAt(new THREE.Vector3(x, y, z));

2,让摄像机追随某个物体

由于 THREE.Mesh 对象的位置都是 THREE.Vector3 对象,所以可以使用 lookAt() 方法使摄像机指向场景中特定的某个网格。
比如我们在 render 循环中执行如下代码,看到的效果就是摄像机随着物体的移动而移动。
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
可拖拽可改变大小的层
<Three.js>(第三节)全景漫游
关于怎样使用three.js的小教程
Three.js Example 注解 —— webgl_materials_grass.html
JSFIDDLE 助力 Threejs 功能探秘
你知道用js怎么绘制3D动画场景么
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服