理解three.js 的渲染结构
1 three.js
的渲染
Three.js
封装了场景、灯光、阴影、材质、纹理和三维算法,让你不必再直接用WebGL 开发项目。three.js
在渲染三维场景时,需要创建很多对象,并将它们关联在一起。
下图便是一个基本的three.js 渲染结构。
解释一下上面的示意图:
1.1 Renderer
渲染器
Renderer 是three.js 的主要对象。当你将一个场景Scene 和一个摄像机Camera 传递到渲染器的渲染方法中,渲染器便会将摄像机视椎体中的三维场景渲染成一个二维图像显示在canvas 画布中。
1.2 Scene
场景对象
场景对象是树状结构的,其中包含了三维对象Object3D 和灯光对象Light。
- Object3D 是可以被直接渲染出来的,Object3D是网格对象Mesh和集合对象Group的基类。
- 场景对象可以定义场景的背景色和雾效。
在场景对象的树状结构中,每个对象的变换信息都是相对的。
比如汽车和汽车里的人,人的位置是相对于汽车而言的,当汽车移动了,人的本地坐标位坐标位虽然不变,但其世界坐标位已经变了。
1.3 Camera
相机对象
按理说,相机对象是在场景里的,但是相机对象不在它所看的场景里,这就像我们自己看不见自己的眼睛一样。
因此,相机对象可以独立于场景之外。
相机对象是可以作为其它三维对象的子对象的,这样相机就会随其父对象同步变换。
1.4 Mesh
网格对象
网格对象由几何体`Geometry`和材质`Material`两部分组成,Geometry 负责塑形,Material 负责着色。
Geometry 和Materia 是可以被多个Mesh 对象复用的。
比如要绘制两个一模一样的立方体,那只需要实例化两个Mesh 即可,Geometry 和Materia可以使用一套。
1.5 Geometry
几何体对象
几何体对象负责塑形,存储了与顶点相关的数据,比如顶点点位、顶点索引、uv坐标等。
Three.js 中内置了许多基本几何体,我们也可以自定义几何体,或者从外部的模型文件里加载几何体
1.6 Material
材质对象
材质对象负责着色,绘制几何体的表面属性,比如漫反射、镜面反射、光泽度、凹凸等。
材质对象的许多属性都可以用纹理贴图表示,比如漫反射贴图、凹凸贴图等。
1.7 Texture
纹理对象
纹理对象就是一张图像。纹理图像的图像源可以是Image 图片、canvas 画布、Video 视频等。
1.8 Light
光源对象
Light 对象不像Object3D 那样依托于顶点,它更多的是像Object3D 里的材质Material 那样,作用于物体的样式。
Light 对象可以理解为在为几何体添加了材质后,再利用光效配合材质对几何体的样式进行二次加工。
2 示例-绘制多个立方体
练习一下three.js
的渲染结构。
2.1. 在vue2 项目中安装three依赖
npm install three @types/three --save --registry=https://registry.npm.taobao.org
2.2 绘制一个立方体
绘制一个立方体,其渲染结构如下:
<template><div id="threeBox"></div>
</template>
<script> import * as THREE from 'three'
export default {data() {return {}},mounted() {this.init();},methods: {init() {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.querySelector("#threeBox").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>
当前这个立方体的材质是MeshNormalMaterial
,并不受光照影响。
2.3 修改材质,添加光源
给立方体换个MeshPhongMaterial
材质,再添加光源。
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshPhongMaterial({ color: 0x44aa88 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
const color = 0xffffff;
const intensity = 1;
const light = new THREE.DirectionalLight(color, intensity);
light.position.set(-1, 2, 4);
scene.add(light);
当前的渲染结构如下:
效果如下:
2.4 绘制多个立方体
在场景中再添加两个一模一样的立方体,几何体和材质可被多个Mesh 对象共享。
<template><div id="threeBox"></div>
</template>
<script> import * as THREE from 'three'
export default {data() {return {}},mounted() {this.init();},methods: {init() {// 场景和相机const scene = new THREE.Scene();const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );camera.position.z = 5;// 渲染器const renderer = new THREE.WebGLRenderer();renderer.setSize( window.innerWidth, window.innerHeight );document.querySelector("#threeBox").appendChild( renderer.domElement );// 光源const color = 0xffffff;const intensity = 1;const light = new THREE.DirectionalLight(color, intensity);light.position.set(-1, 2, 4);scene.add(light);// 几何体和材质const geometry = new THREE.BoxGeometry();const material = new THREE.MeshPhongMaterial({ color: 0x44aa88 });// 几何体和材质可被多个Mesh 对象共享。const cubes = [-2, 0, 2].map((num) => makeInstance(num));scene.add(...cubes);//批量生成 Mesh 网格对象function makeInstance(x) {const cube = new THREE.Mesh(geometry, material);cube.position.x = x;return cube;}// 动画渲染animate()function animate() {requestAnimationFrame(animate);cubes.forEach((cube) => {cube.rotation.x += 0.01;cube.rotation.y += 0.01;});renderer.render(scene, camera);}}}
} </script>
当前的渲染结构如下:
效果如下:
最后
为大家准备了一个前端资料包。包含54本,2.57G的前端相关电子书,《前端面试宝典(附答案和解析)》,难点、重点知识视频教程(全套)。
有需要的小伙伴,可以点击下方卡片领取,无偿分享