ThreeJs初探

这几天想给个人主页加点东西丰富内容,想来在如今成熟的软硬件条件下,现代浏览器对WebGL的支持已经十分完善,所以寻思不如来点3d效果,也借此机会对ThreeJs有个大体的了解。

本文将简单介绍three.js的使用,希望尽量用精简的文字帮助大家快速入门。

ThreeJs介绍

我们知道,WebGL相当于OpenGL的Web版,借助其提供的Api,我们能够在浏览器环境上充分利用硬件加速来渲染3D场景和模型。然而这些Api对一般Web开发人员来说门槛较高,于是three.js应运而生,这是一个基于WebGL封装的轻量易用的第三方js库。

开始上手

官方地址:https://threejs.org/

github:https://github.com/mrdoob/three.js

官方demo

首先访问three.js的github地址,看到其说明中给了一个简单示例,我们把这段代码放到html中,并且引入three.js

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>three demo</title>
</head>
<body>
</body>
<script src="https://threejs.org/build/three.min.js"></script>
<script>
    var camera, scene, renderer;
    var geometry, material, mesh;

    init();
    animate();

    function init() {
        camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.01, 10);
        camera.position.z = 1;

        scene = new THREE.Scene();

        geometry = new THREE.BoxGeometry(0.2, 0.2, 0.2);
        material = new THREE.MeshNormalMaterial();

        mesh = new THREE.Mesh(geometry, material);
        scene.add(mesh);

        renderer = new THREE.WebGLRenderer({
            antialias: true
        });
        renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(renderer.domElement);
    }

    function animate() {
        requestAnimationFrame(animate);

        mesh.rotation.x += 0.01;
        mesh.rotation.y += 0.02;

        renderer.render(scene, camera);
    }
</script>
</html>

然后用浏览器打开看看,可以看到一个旋转的正方形,环境就这么跑起来了。

了解概念

我们再来看看示例的这段js代码做了什么,简单归纳如下:

Camera --> Scene --> Renderer --> render
              add │            │
                 Mesh          │
                  │ Animation ─┘
        Geometry ─┤
                  │
        Material ─┘

于是这里涉及几个概念:

  • 场景(Scene):所有物体的容器,即我们构建的三维世界
  • 摄像机(Camera):观察场景的视角,决定3D场景如何投影到画布上
  • 渲染器(Renderer):将场景以摄像机投影视角绘制到画布

关于摄像机投影,有以下两种:

  • 正交投影:

正交投影

  • 透视投影:

透视投影

各位可以把自己想象成一名摄影师

代码中的PerspectiveCamera就是透视投影,该方法的四个参数分别为视野角度、宽高比、摄像机允许观察的最近距离、摄像机允许观察的最远距离

再看看另外几个概念:

  • 网格(Mesh):计算机世界中弧线是由大量线段连接而成,三维模型也类似,普遍做法是用三角形组成的网格来描述,这就是Mesh模型
  • 形状(Geometry):构成模型的形状,threejs提供了盒子(Box)、圆形(Circle)、圆柱体(Cylinder)、球体(Sphere)等基本形状
  • 材质(Material):模型表面的材质,包括网格深度材质(MeshDepthMaterial)、网格非发光材质(MeshLambertMaterial)等

入门实践

现在来试下用three.js来构建一个运动的葫芦

创建物体

我们知道葫芦可以看成是一个轴对称图形,于是注意到three.js提供了LatheGeometry(车床模型),它可以用来生成 甜甜圈,管道,花瓶 等围绕Y轴旋转的模型,那么接下来看看怎么用数学函数来表示葫芦的轮廓

......

上面这段纯属瞎掰,用函数来表示葫芦也并非容易,所以这里暂且略过,我们还是直接从网上找个模型来用吧,来看看怎么导入

<!-- 引入objloader.js -->
<script src="./js/OBJLoader.js"></script>
//加载obj文件
var loader = new THREE.OBJLoader();
loader.load(
	// obj文件URL
	'./hulu.obj',
	// 文件加载完成
	function (object) {
		/* 省略部分代码 */
		console.log('object即加载得到的Object3D实例');
	},
	// 文件加载中
	function (xhr) {
		console.log((xhr.loaded / xhr.total * 100) + '% loaded');
	},
	// 加载出错
	function (error) {
		console.log('An error happened');
	}
); 

构造场景

然后就是参考前面官方demo的三板斧

  • 创建场景
  • 摆放摄像机
  • 摆放物体
  • 准备灯光

详细代码可以参考我放到github上的源码,这里不再详述

创建动画

最后一步,来告诉葫芦要怎么动,就让它绕着一根轴旋转吧

function animate() {
  if (mesh) {
		requestAnimationFrame(animate);
		let axis = new THREE.Vector3(0, 1, 0);
		axis.normalize()
		// 绕Y轴旋转
		mesh.rotateOnAxis(axis, -0.01)
		renderer.render(scene, camera);
	}
}

好了,现在可以大喊一声Action

把html和其他资源文件放到服务器上后打开即可看到最终效果。

小结

3D是个博大精深的课题,除了计算机,还涉及数学、图形学等多门学科,所以本文也仅做简单介绍,希望能帮助前端开发者有个入门的了解

对于three.js,本人也是初学者,文章如有纰漏之处,还请多多包涵~

上次更新: 2018-9-25 00:48:29