这是我们开始使用Three.js的第一个小节,我们回顾一下用Web开发最经典的方式来使用它,一个<script>
标签。
首先我们创建一个最为基本的 index.html 文件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>03 - 基础场景</title>
</head>
<body>
<script src="./script.js"></script>
</body>
</html>
然后再创建一个 script.js
文件,里面的代码很简单,就一行
console.log('Hello Three.js')
接着我们双击 index.html
文件,不出意外的话,会使用你电脑中默认的浏览器打开。虽然Three.js可以在大部分浏览器中正常工作,但我仍然强烈建议大家使用Chrome,因为它更利于我们开发和调试。
现在我们按下键盘上的F12,将打开一个开发者调试工具
接着切换到Console(控制台)标签,在开发的过程中,我们应该时刻关注控制台中输出的错误、警告、日志。
现在我们需要在网页里加载 Three.js
库。
打开 Three.js
的官网 https://threejs.org/ ,然后单击Download按钮来下载最新的 Three.js
库,将下载后的zip文件解压缩。文件很多,因为这是整个仓库,里面有离线的文档和全部的示例源码。在本小节中,我们只需要一个文件。
解压缩后的文件夹大概长这样:
/assets/lessons/03/image-1.png
打开 build/
文件夹并且将其中的 three.min.js
文件复制粘贴到你的项目中
复制粘贴完后,你的项目文件夹应该有三个文件了:
/assets/lessons/03/image-2.png
再加入一个<script>
标签来加载Three.js 库:
<script src="./three.min.js"></script>
<script src="./script.js"></script>
你需要确保在你的代码之前已经加载好了 three.min.js
,否则,是无法正常使用的。
在我们的script.js
文件中,我们现在可以访问到一个名为THREE的变量。注意,THREE大写。
如果你使用console.log()
去打印这个变量,你将看到很多信息
console.log(THREE)
THREE
这个变量包含了 Three.js
项目中可能用到大多数
类、方法和属性。
要使用某一个类,我们需要先实例化它。比如要创建场景,则编写代码const scene = new THREE.Scene ()
。如果要创建一个3D球体,则编写代码const sphereGeometry = new THREE.SphereGeometry(1.5,32,32)
。这些类和初始化参数的意义我们一会儿再来详细了解。
现在准备好用 Three.js
在网页里来创建我们的第一个3D场景。
创建一个3D场景,我们至少需要4个对象:
场景就像一个容器,我们在这个容器中放置三维世界中的元素,比如模型,灯光,粒子等等,然后在某个时机, Three.js会结合Camera(相机)等各种因素将场景通过Renderer渲染器绘制到画布上。
要创建一个场景,使用Scene这个类:
// Scene
const scene = new THREE.Scene()
3D对象可以是很多东西,比如一些最基本的几何体,导入的3D模型,粒子,灯光等等都是3D对象。
我们从创建一个最简单的红色立方体开始吧。
立方体,其实是一种名为Mesh的对象。而Mesh是由几何体和材质组合的。
Three.js中内置了许多基本的几何体类型和许多基础材质,但第一节课我们还是先简单一点,就创建一个立方体(BoxGeometry)和基础材质。
要创建立方体,需要使用BoxGeometry类,3个参数分别对应于盒子的大小。这是一种向量尺寸,请不要理解为像素
// Object
const geometry = new THREE.BoxGeometry(1, 1, 1)
要创建基础材质,要用到MeshBasicMaterial类,并且在实例化的时候,我们通过{}
来包含初始化的一些参数,比如颜色属性。当然我们也可以在初始化之后再设置颜色属性。
在Three.js中有很多方法可以指定颜色。比如红色,既可以使用十六进制数字0xff0000来表达,也可以写为字符串 “#ff0000” ,还可以使用比如 “red” 这样的颜色名称,这里我们使用第一种,其他的就不过多叙述了。
// Object
const geometry = new THREE.BoxGeometry(1, 1, 1)
const material = new THREE.MeshBasicMaterial({ color: 0xff0000 })
最后使用Mesh类并将几何体geometry和材质material作为参数传递。
// Object
const geometry = new THREE.BoxGeometry(1, 1, 1)
const material = new THREE.MeshBasicMaterial({ color: 0xff0000 })
const mesh = new THREE.Mesh(geometry, material)
现在,我们使用场景的add方法把这个Mesh对象添加到场景中:
scene.add(mesh)
请牢记,如果我们只是创建了3D对象,但没有把它添加到场景中的话,是看不见的。
相机虽然也是一种3D对象,并且需要添加到场景中,但它本身是不可见的。当我们对3D场景进行渲染时,渲染器将从相机所在的角度来看。
在一个场景中我们也可以布置多个摄像头,就像拍电影时的多个机位,我们可以在这些相机之间切换。不过,通常我们只使用一个相机。
在Three.js中有两种类型的相机类型,一种是透视相机,一种是等距相机。一般情况下,我们也只需要用到透视相机 (近大远小)。
要创建相机,我们需要用到PerspectiveCamera这个类。在实例化这个对象时,我们需要提供两个基本参数。
千万不要忘记把相机Camera也添加到场景中哦
// Sizes
const sizes = {
width: 800,
height: 600
}
// Camera
const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height)
scene.add(camera)
渲染器的工作就是把Camera在场景中看到的内容渲染绘制到画布上。
想让渲染器渲染我们的场景之前,我们要先在html文件中创建一个canvas画布。
在html的body中添加 <canvas>
标签
<canvas class="webgl"></canvas>
要创建渲染器,我们要用到WebGLRenderer类,这个类在实例化的时候需要我们提供一个画布对象的参数,使用JS方法的document.querySelector(...)
即可获取到我们刚才在html中创建的canvas对象。
最好将画布分配给一个变量,因为我们可能还会有其它用途。
接着我们还需要使用setSize(...) 方法来更新渲染器的绘制尺寸。
// Canvas
const canvas = document.querySelector('canvas.webgl')
// ...
// Renderer
const renderer = new THREE.WebGLRenderer({
canvas: canvas
})
renderer.setSize(sizes.width, sizes.height)
当这些代码都写完之后,我们刷新一下当前网页,我们将看到一个800像素宽,600像素高的黑色画布。
/assets/lessons/03/step-01.png
准备进行我们的第一次渲染,调用渲染器的render(...)
方法,并将场景和相机作为参数:
renderer.render(scene, camera)
似乎有点问题,什么都没有呢。这个问题恰好帮我们更好的理解三维世界的运行机制。因为我们没有指定3D立方体的位置,也没有设置相机的位置,它们默认的位置都在0,0,0
,这是场景的中心,也就是说,相机此时正在立方体的内部。一般情况下,我们是无法从内部看到3D对象的。一个3D对象有很多属性,比如位置position,旋转rotation和缩放scale。位置position是一个具有三个属性的对象,这三个属性分别为 x轴,y轴和z轴。那么我们通过设置它们,就可以移动相机。现在我们把相机移动到z轴为3的位置。注意,Three.js采用右手笛卡尔坐标系。
image.png
const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height)
camera.position.z = 3
scene.add(camera)
/assets/lessons/03/step-02.png
恭喜,我们的3D场景已经渲染到画布上了,它看起来并不立体,像一个正方形,这是因为相机与立方体在一个水平线上,所以我们只能看到立方体的一侧。
不用担心,在接下来的课程中,我们将学习更多关于位置、旋转和缩放属性的用法,以及如何为它们设置动画。那个时候,它们会看上去非常“立方体”。