|
| 1 | +# Three.js实用知识点笔记 |
| 2 | + |
| 3 | +从今天开始,在本文中记录实际 Three.js 开发过程中所遇到的知识点。 |
| 4 | + |
| 5 | + |
| 6 | + |
| 7 | +<br> |
| 8 | + |
| 9 | +**关于示例代码的一般约定说明:** |
| 10 | + |
| 11 | +1. 举例的时候,很多都是伪代码 |
| 12 | +2. 为了保证代码简洁,所以在实用某些类时没有添加 `Three.` 前缀 |
| 13 | +3. 绝大多数时候都使用箭头函数 |
| 14 | +4. 使用 Xxx 泛指同一类型,例如 XxxCamer 泛指各类相机 |
| 15 | + |
| 16 | + |
| 17 | + |
| 18 | +<br> |
| 19 | + |
| 20 | +#### 01、每一个Object3D对象都只能有一个父级 |
| 21 | + |
| 22 | +这里说的 Object3D 实际上包括所有继承于 Object3D 的子类,例如 Mesh、Camera、Group 等 |
| 23 | + |
| 24 | +举例说明: |
| 25 | + |
| 26 | +``` |
| 27 | +const mesh = new Mesh(geometry,material) |
| 28 | +
|
| 29 | +const sceneA = new Scene() |
| 30 | +const sceneB = new Scene() |
| 31 | +
|
| 32 | +sceneA.add(mesh) |
| 33 | +sceneB.add(mesh) |
| 34 | +``` |
| 35 | + |
| 36 | +由于 mesh 只能有一个父类,所以当 sceneB 也执行 .add(mesh) 后,sceneA.children 中会自动删除掉 mesh。 |
| 37 | + |
| 38 | + |
| 39 | + |
| 40 | +<br> |
| 41 | + |
| 42 | +#### 02、克隆或复制 Mesh 不会在内存中真正复制出一份 顶点(geometry)和材质(material),它们使用的是引用,而不是复制 |
| 43 | + |
| 44 | +Object3D 拥有 .clone() 和 .copy() 两个方法,Mesh 继承于 Object3D,所以也拥有这两个方法。 |
| 45 | + |
| 46 | +在 Mesh 类中扩展了 .copy() 方法,但是针对 Mesh 内部的属性 顶点和材质,实用的是引用而不是真正内存中的复制。 |
| 47 | + |
| 48 | +``` |
| 49 | +const meshB = meshA.clone() |
| 50 | +``` |
| 51 | + |
| 52 | +上述代码中新复制得到的 meshB 仅仅复制了 meshA 的一些变换相关的属性,例如 matrix 等,但是对于占内存大头的 顶点和材质 这两项实用的是引用。 |
| 53 | + |
| 54 | +也就是说此时 meshA 和 meshB 它们共用了一份 geometry 和 material。 |
| 55 | + |
| 56 | +> 不用担心因为多复制了几份 mesh 而增加很多内存。 |
| 57 | +
|
| 58 | + |
| 59 | + |
| 60 | +<br> |
| 61 | + |
| 62 | +#### 03、添加场景(scene)或其他Object3D渲染之前和渲染之后的回调函数 |
| 63 | + |
| 64 | +场景 scene 继承于 Object3D,而 Object3D 可以配置 2 个渲染之前或之后的回调函数: |
| 65 | + |
| 66 | +``` |
| 67 | +scene.onBeforeRender = () => { ...} |
| 68 | +scnet.onAfterRende = () => { ... } |
| 69 | +``` |
| 70 | + |
| 71 | +使用场景举例:假设我们希望不渲染场景上的某一类元素,那么我们可以在 renderer.render() 之前通过上面 2 个回调函数进行设置 |
| 72 | + |
| 73 | +``` |
| 74 | +scene.onBeforeRender = () => { |
| 75 | + scene.children.forEach(item => { |
| 76 | + if(item.type === 'Points'){ |
| 77 | + item.visible = false |
| 78 | + } |
| 79 | + }) |
| 80 | +} |
| 81 | +
|
| 82 | +scene.onAfterRender = () => { |
| 83 | + scene.children.forEach(item => item.visible = true) |
| 84 | +} |
| 85 | +
|
| 86 | +renderer.render(scene,camera) |
| 87 | +``` |
| 88 | + |
| 89 | + |
| 90 | + |
| 91 | +<br> |
| 92 | + |
| 93 | +#### 04、通过 .layers 控制物体是否被渲染 |
| 94 | + |
| 95 | +在 Three.js 中 .layers 对应的是 Layers 这个类,Three.js 规定 Layers 级别的值取值范围为 0 - 32。 |
| 96 | + |
| 97 | +> 你可以把 layers 翻译成 “级别”,也可以称呼为 “层级” |
| 98 | +
|
| 99 | +任何继承于 Object3D 的类,例如 相机、物体 等都具有 .layers 属性。 |
| 100 | + |
| 101 | +它们的 .layers 默认级别都为 0。 |
| 102 | + |
| 103 | +不能通过直接给 .layers 赋值的方式修改级别,而是应该通过 .set(value) 这种形式。 |
| 104 | + |
| 105 | +``` |
| 106 | +mymesh.layers.set(1) |
| 107 | +camera.layers.set(1) |
| 108 | +``` |
| 109 | + |
| 110 | + |
| 111 | + |
| 112 | +<br> |
| 113 | + |
| 114 | +对于相机而言,它只能渲染出同一级别的物体元素。 |
| 115 | + |
| 116 | +``` |
| 117 | +const meshA = new Mesh(...) |
| 118 | +//meshA.layers.set(0) //默认就是 0 |
| 119 | +
|
| 120 | +const meshB = new Mesh(...) |
| 121 | +meshB.layers.set(1) |
| 122 | +
|
| 123 | +const scene = new Scene() |
| 124 | +scene.add(meshA) |
| 125 | +scene.add(meshB) |
| 126 | +
|
| 127 | +const cameraA = new XxxCamera() |
| 128 | +//cameraA.layers.set(0) //默认就是 0 |
| 129 | +
|
| 130 | +const cameraB = new XxxCamera() |
| 131 | +cameraB.layers.set(1) |
| 132 | +``` |
| 133 | + |
| 134 | +在上面代码中: |
| 135 | + |
| 136 | +1. 我们按照默认的形式添加了 meshA、cameraA,它们默认层级为 0 |
| 137 | +2. 手动修改了 meshB、cameraB 的 .layers 层级为 1 |
| 138 | + |
| 139 | +<br> |
| 140 | + |
| 141 | +那么当执行下面的代码: |
| 142 | + |
| 143 | +``` |
| 144 | +renderer.render(scene, cameraA) |
| 145 | +renderer.render(scene. cameraB) |
| 146 | +``` |
| 147 | + |
| 148 | +1. cameraA 只会渲染出场景中同一级别的 meshA |
| 149 | +2. cameraB 只会渲染出场景中同一级别的 meshB |
| 150 | + |
| 151 | + |
| 152 | + |
| 153 | +<br> |
| 154 | + |
| 155 | +也可以选择随时修改 meshA 的 .layers 值,这样 cameraB 就可以渲染到它了。 |
| 156 | + |
| 157 | +``` |
| 158 | +meshA.layers.set(1) |
| 159 | +renderer.render(secen, cameraB) |
| 160 | +``` |
| 161 | + |
| 162 | + |
| 163 | + |
| 164 | +<br> |
| 165 | + |
| 166 | +换句话说,假设我们希望控制是否渲染场景中某些元素,那么有 2 种途径: |
| 167 | + |
| 168 | +1. 设置其 .visible 的值来决定是否渲染 |
| 169 | +2. 设置其 .layers 的值来决定只被同一层级的相机渲染 |
| 170 | + |
| 171 | + |
| 172 | + |
| 173 | +<br> |
| 174 | + |
0 commit comments