从1开始学习THREE.js

754 阅读4分钟

为什么不是从零开始呢? 因为这里面确实涉及到很多编程知识需要有一定基础, 特别是面向对象的设计模式, 0基础要看懂还是很难很难.

整个系列将会基于THREEjs权威指南的知识体系, 力图拨丝抽茧.

我将分为几个模块来一步步梳理, 主要分为以下几个部分:

整体描述

整体流程

整个THREjs的最核心部分就是以下的流程

  1. 创建一个场景scene --> 一个容器, 保存和跟踪索要渲染的物体和光源, 没有它就无法渲染任何物体
  2. 添加摄像机 --> 决定能够看到场景中的内容
  3. 添加光源 --> 决定材质的表面, 亮度等
  4. 添加参考平面,带材质的物体 --> 组成复杂场景的原子
  5. 添加渲染器 --> 基于摄像机的角度计算场景应该被渲染成什么样, 会使用WebGL技术使用显卡进行场景渲染.
  6. 对物体,物体集合或摄像机进行控制并对渲染器进行循环渲染以产生动画 --> 会使用requestAnimationFrame使动画更平滑.
  7. 氪金皮肤--着色器, 纹理等
  8. 模拟自然--物理引擎
  9. 添加到HTML的DOM节点中
  10. renderer进行渲染

其中最后两个不是必须会的, 而且需要第三方的库的支持可供选择的格式也有很多种, 我会尽可能在后面对应章节中举实例来说明.

以上流程其实就是一堆API的调用, 全局有个THREE对象, 封装了所有的方法, 跟jQuery的$符类似.

整体代码

本系列的所有代码都力图不用使用webpack等打包方式来实现. 文件较大, 官方不推荐使用script在线引用, 请下载build版本到本地路径, 然后再行引入, 除此之外, 还需要设置一些全局样式以更好的进行内容呈现

设置全局样式

body { margin: 0; }
canvas { width: 100%; height: 100% }

创建第一个场景

以下代码只会简略说明, 具体每一个对象的用法会在之后的文章中一一介绍详情.

这第一个场景将会包含基本材质,基本集合体,平面, 摄像机, 辅助axes. 最终的效果为:

function init() {
  const scene = new THREE.Scene()
  const camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 1000)
  const renderer = new THREE.WebGLRenderer()
  renderer.setClearColor(new THREE.Color(0x000000))
  renderer.setSize(window.innerWidth, window.innerHeight)

  const axes = new THREE.AxesHelper(20)
  scene.add(axes)

  const planeGeometry = new THREE.PlaneGeometry(60, 20)
  const planeMaterial = new THREE.MeshBasicMaterial({color: 'grey'})
  const plane = new THREE.Mesh(planeGeometry, planeMaterial)
  plane.rotation.x = -0.5 * Math.PI
  plane.position.set(15, 0, 0)
  scene.add(plane)

  const cubeGeometry = new THREE.BoxGeometry(4, 4, 4)
  const cubeMaterial = new THREE.MeshBasicMaterial({
    wireframe: true,
    color: 'red',
  })
  const cube = new THREE.Mesh(cubeGeometry, cubeMaterial)

  cube.position.set(-4, 4, 4)
  scene.add(cube)

  camera.position.set(-30, 30, 30)
  camera.lookAt(scene.position)
  // 将render的dom对象放到DOM中进行渲染
  document.getElementById('webgl-output').appendChild(renderer.domElement)
  renderer.render(scene, camera)
}

上述代码其实就是最开始我们说的如何创建一个THREEjs的流程, 每个API的具体用法, 比如PerspectiveCamera, Geometry等会在之后的文章中一一进行解释.

有很多数据不是随意设置的, 比如cube的Geometry设置为4,4,4, 也就是长宽高, 那么再去设置它的position的时候需要注意, 如果设置为-4,-4,-4, 那么cube就会在平面的下方, 也就看不见cube了, 还是需要一些基础的几何学基础, 所以不能说从零开始学.不过难度不会很大, 请读者放心.

本章具体代码以及每行的注释请参见github

最后再引入一个全局都会使用到的一个辅助工具, dat.gui, 可以很方便的使用GUI的方式控制某些参数., 下面的参数就是用于控制cube的坐标位置

// 添加control.js
import * as dat from 'dat.gui'
const gui = new dat.GUI()

export const controller = {
  x : -4,
  y : 4,
  z : 4,
}

gui.add(controller, 'x', -10, 10)
gui.add(controller, 'y', -10, 10)
gui.add(controller, 'z', -10, 10)

然后再使用requestAnimationFrame这个全局方法来实时响应式更新场景

const render = function() {
  cube.position.x = controller.x
  cube.position.y = controller.y
  cube.position.z = controller.z
  // 进行渲染
  renderer.render(scene, camera)
  requestAnimationFrame(render)
}

这样在界面中就可以看到cube的移动了

动画也是如此原理, 只需要使用

// 沿x轴移动
cube.position.x += 0.02

下一篇会说到场景相关的东西.

封面图来自threejs.org