1. Three.js入门案例

587 阅读5分钟

1、three.js 简介

three.js是用JavaScript编写的WebGL第三方JavaScript库,用于在 Web 浏览器中创建 3D Web 图形。

具体而言,three.js 是一款基于WebGL运行在浏览器中的 3D 引擎,可以用three.js 创建各种三维场景。

three.js 官网:threejs.org/

github:github.com/mrdoob/thre…

image.png

image.png

2. 3D 场景前置知识

2.1 场景(Scene)——物体、光源等元素的容器

场景:是物体、光源等元素的容器,可以配合 chrome 插件使用,抛出 window.scene即可实时调整 obj 的信息和材质信息。

Scene 是场景对象,所有的网格对象、灯光、动画等都需要放在场景中,使用 new THREE.Scene 初始化场景,下面是场景的一些常用属性和方法。

  • fog:设置场景的雾化效果,可以渲染出一层雾气,隐层远处的的物体。
  • overrideMaterial:强制场景中所有物体使用相同材质。
  • autoUpdate:设置是否自动更新。
  • background:设置场景背景,默认为黑色。
  • children:所有对象的列表。
  • add():向场景中添加对象。
  • remove():从场景中移除对象。
  • getChildByName():根据名字直接返回这个对象。
  • traverse():传入一个回调函数访问所有的对象。

2.2 相机(Camera)——代替人眼去观察

场景中的相机,代替人眼去观察,场景中只能添加一个。

为了在场景中显示物体,就必须给场景添加相机,相机类型可以分为正交相机透视相机

image.png

一般常用的是透视相机 PerspectiveCamera,可以像下面这样使用透视相机。

2.2.1 透视相机构造函数

PerspectiveCamera(fov, aspect, near, far)
  • fov:表示视场,就是能够看到的角度范围,人的眼睛大约能够看到 180度 的视场,视角大小设置要根据具体应用,一般游戏会设置 60~90 度,默认值 45
  • aspect:表示渲染窗口的长宽比,如果一个网页上只有一个全屏的 canvas 画布且画布上只有一个窗口,那么 aspect 的值就是网页窗口客户区的宽高比 window.innerWidth/window.innerHeight
  • near:属性表示的是从距离相机多远的位置开始渲染,一般情况会设置一个很小的值。 默认值 0.1
  • far:属性表示的是距离相机多远的位置截止渲染,如果设置的值偏小,会有部分场景看不到,默认值 1000

2.3 物体对象(Mesh)——包括二维物体(点、线、面)、三维物体,模型等等

three.js 的世界中,材质(Material)+几何体(Geometry)就是一个 mesh

  • 设置其name属性可以通过scene.getObjectByName(name)获取该物体对象;
  • Geometry就好像是骨架,材质则类似于皮肤

2.3.1 几何体种类

几何:物体的形状,由顶点(点)和面(物体的平面)组成。Three.js 也给了很多预制的几何图形只需要给它一些参数它会处理那里的细节。

image.png

image.png

2.3.2 材质分类

材质:物体是由什么组成的,这将包括像颜色这样的东西,它将决定光如何与我们的物体交互。

如果有一个鹅卵石和一个金属球轴承,它们会有相似的几何形状,但它们的材料是非常不同的,这将改变它在观众眼中的样子。

image.png

2.4 光源(Light)——场景中的光照

如果不添加光照场景将会是一片漆黑,包括全局光、平行光、点光源等

image.png

2.5 渲染器(Renderer)——场景的渲染方式

场景的渲染方式,如webGL\canvas2D\Css3D。

WebGLRendererWebGL 渲染出场景。

  • 通过 new THREE.WebGLRenderer 初始化渲染器,并将 canvas 容器作为参数传给它。
  • 通过调用 setSize 方法设置渲染器的尺寸;
  • 调用 setPixelRatio 设置 canvas 的像素比为当前设备的屏幕像素比,避免高分屏下出现模糊情况。

2.6 控制器(Control)

通过键盘、鼠标控制相机的移动

3. 搭建一个场景——旋转的立方体

3.1 容器构建、引入资源

添加需要渲染 3D 内容的容器和基本页面结构。

导入Three.js、以及开发页面功能所需要的其他库、静态资源等。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>入门案例</title>
        <style>
                body { margin: 0; }
        </style>
    </head>
    <body>
        <script src="https://unpkg.com/three/build/three.js"></script>
        <script>
                // Our Javascript will go here.
        </script>
    </body>
</html>

3.2 场景初始化

  • 定义一些全局变量如渲染尺寸、容器等;
  • 初始化渲染器;
  • 初始化场景;
  • 处理页面缩放事件监听处理等。
// 创建一个场景
const scene = new THREE.Scene();
// 透明相机
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
// // 初始化渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );

3.3 逻辑开发——添加三维模型

要创建可加载显示在场景中的内置三维模型,需要添加网格 Mesh,并为它创建几何体 Geometry 和 材质 Material

const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshNormalMaterial();
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

camera.position.z = 5;

3.3.1 立方体 BoxGeometry

BoxGeometry 是四边形的原始几何类,来创建立方体或者不规则四边形

BoxGeometry(width : Float, height : Float, depth : Float, widthSegments : Integer, heightSegments : Integer, depthSegments : Integer)
  • widthX轴 的宽度,默认为 1
  • heightY轴 的高度,默认为 1
  • depthZ轴 的深度,默认为 1
  • widthSegments:可选,宽度的分段数,默认是 1
  • heightSegments:可选,高度的分段数,默认是 1
  • depthSegments:可选,深度的分段数,默认是 1

3.3.2 基础网格材质 MeshBasicMaterial

基础网格材质是一种一个以简单着色方式来绘制几何体的材质,它不受光照的影响。

MeshBasicMaterial(parameters: Object)
  • parameters:可选,用于定义材质外观的对象,具有一个或多个属性如 colormap

3.4 动画更新 ——页面循环渲染

在连续渲染方法里旋转立方体

  • 自定义动画方法animate(),它的功能是使渲染器可以在每次屏幕刷新时对场景进行循环绘制
  • requestAnimationFrame刷新率一般为60次/秒
animate()
function animate() {
  // 页面重绘时调用转动动画
  requestAnimationFrame( animate );
  // 给网格模型添加一个转动动画
  cube.rotation.x += 0.01;
  cube.rotation.y += 0.01;
  // 更新渲染器
  renderer.render( scene, camera );
};

3.5 运行效果

1.gif

image.png

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>首次尝试</title></title>
        <style>
                body { margin: 0; }
        </style>
    </head>
    <body>
        <script src="https://unpkg.com/three/build/three.js"></script>
        <script>
            const scene = new THREE.Scene();
            const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );

            const renderer = new THREE.WebGLRenderer();
            renderer.setSize( window.innerWidth, window.innerHeight );
            document.body.appendChild( renderer.domElement );

            const geometry = new THREE.BoxGeometry();
            const material = new THREE.MeshNormalMaterial();
            const cube = new THREE.Mesh(geometry, material);
            scene.add(cube);

            camera.position.z = 5;
            animate()
            function animate() {
                requestAnimationFrame( animate );

                cube.rotation.x += 0.01;
                cube.rotation.y += 0.01;

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