为什么不是从零开始呢? 因为这里面确实涉及到很多编程知识需要有一定基础, 特别是面向对象的设计模式, 0基础要看懂还是很难很难.
整个系列将会基于THREEjs权威指南的知识体系, 力图拨丝抽茧.
我将分为几个模块来一步步梳理, 主要分为以下几个部分:
整体描述
整体流程
整个THREjs的最核心部分就是以下的流程
- 创建一个场景scene --> 一个容器, 保存和跟踪索要渲染的物体和光源, 没有它就无法渲染任何物体
- 添加摄像机 --> 决定能够看到场景中的内容
- 添加光源 --> 决定材质的表面, 亮度等
- 添加参考平面,带材质的物体 --> 组成复杂场景的原子
- 添加渲染器 --> 基于摄像机的角度计算场景应该被渲染成什么样, 会使用WebGL技术使用显卡进行场景渲染.
- 对物体,物体集合或摄像机进行控制并对渲染器进行循环渲染以产生动画 --> 会使用
requestAnimationFrame使动画更平滑. - 氪金皮肤--着色器, 纹理等
- 模拟自然--物理引擎
- 添加到HTML的DOM节点中
- 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