更新于 

Instenced Mesh 实例化网格

渲染大量网格时需要考虑的问题

Render Call

在使用threejs在场景中绘制出一个实体时,
threejs实际在后台帮我们略去了很多复杂的绘图操作。

这些操作中包括比较关键的步骤:CPU与GPU之间的通信。

CPU发出绘图指令,GPU负责执行绘图。

场景中有N个实体,这种通信就要执行N次。

如果绘制的图形如果具有相同的Geometry和Material,
这样的操作如果执行N次会导致渲染效率低下。

就好像你要把同一条短信发给好几个人,
如果一个一个发效率自然会很低下。

InstancedMesh

THREE.InstancedMesh能够一次性创建N个具有相同Geo和Mat的实体,
无需再使用for循环N次。

1
let mesh = new THREE.InstancedMesh(geo, mat, count)

InstancedMesh中提供了修改内部实例的变换矩阵颜色的接口:

  • matrix
    • InstancedMesh.setMatrixAt(index,matrix)
      • 注意setMatrixAt调用过后,需要将InstancedMesh.instanceMatrix.needsUpdate改为true,更新矩阵
    • InstancedMesh.getMatrixAt(index,matrix)
  • color
    • InstancedMesh.setColorAt(index, THREE.Color)
      • 同样的需要再之后将InstancedMesh.instanceColor.needsUpdate修改为true
1
2
3
4
mesh.setMatrixAt(i, dummy.matrix)
mesh.instanceMatrix.needsUpdate = true
mesh.setColorAt(i,new THREE.Color(Math.random()*0xffffff))
mesh.instanceColor.needsUpdate = true

如果在loop函数中,需要获取mesh内实例的模型矩阵的各个分量(旋转、平移、缩放),
可以用Matrix4.decompose拆解实例的模型矩阵matrix:

1
2
3
const matrix = new THREE.Matrix4() // 空矩阵
mesh.getMatrixAt(i, matrix) // 获取mesh内第i个实例的matrix
matrix.decompose(dummy.position, dummy.rotation, dummy.scale) // 拆解