很多场景中会需要同一个模型很多次,但是如果多次加载同一个模型会占用很高的带宽,导致加载很慢,因此就需要使用clone,也就是加载一个模型后,其他需要使用的地方使用clone的方式复制出多个同样的模型,再改变复制出来的模型位置,达到一次加载,多次使用。但另一个情况是克隆的模型是新的模型,在threejs的场景中是一个完整独立的,具有一个正常模型所有的属性,很大,加载和渲染需要花费很多的时间,那么就又需要对克隆出的模型进行合并,成为一个整体的模型放到threejs的场景中。
首先我们需要搭建一个threejs的场景,包括相机,灯光,渲染器等,这里为了方便看合并后的效果,再添加上State性能监视器。其他的场景搭建之前章节中都已存在这里就不贴代码了。性能监视器的代码如下
import Stats from 'three/addons/libs/stats.module.js';
this.stats = new Stats();
document.body.appendChild(this.stats.domElement);
然后加载一个模型,我这里使用一个料箱模型作为演示的模型。
initModel(){
const loader = new GLTFLoader()
loader.load("/static/models/box.glb", (gltf) => {
this.scene.add(gltf.scene)
})
},
然后开始clone料箱。先clone1000个,并修改每个料箱的位置,此时发现threejs渲染已经非常吃力,FPS已经掉帧到12了。
initModel(){
const loader = new GLTFLoader()
loader.load("/static/models/box.glb", (gltf) => {
let originaMesh = gltf.scene.children[0];
for (let i = 0; i < 100; i++) {
for (let j = 0; j < 10; j++) {
for (let k = 0; k < 10; k++) {
let mesh = originaMesh.clone()
mesh.position.set(i*6,j*6,k*10);
this.scene.add(mesh)
}
}
}
})
},
然后我们开始模型合并,模型合并其实就是将每个模型的geometry克隆出来,放到一个集合中,最终把这个集合渲染为一个整体的大模型。
initModel(){
const loader = new GLTFLoader()
loader.load("/static/models/box.glb", (gltf) => {
this.scene.add(gltf.scene)
let meshArr = []
let originaMesh = gltf.scene.children[0];
for (let i = 0; i < 100; i++) {
for (let j = 0; j < 10; j++) {
for (let k = 0; k < 10; k++) {
let mesh = originaMesh.clone()
mesh.position.set(i*6,j*6,k*10);
mesh.updateMatrixWorld(true);
const geometry = mesh.geometry.clone();
geometry.applyMatrix4(mesh.matrixWorld);
meshArr.push(geometry)
}
}
}
const bayGeometry = mergeGeometries(meshArr,true);
const material = new THREE.MeshStandardMaterial({ color: '#0000FF' });
const totalMesh = new THREE.Mesh(bayGeometry, material);
totalMesh.name="大模型"
this.scene.add(totalMesh);
})
},
最终通过模型合并,1000个料箱同时展示,FPS又回到了60,因为对于threejs来讲,只有一个模型了,渲染也是一次成型。
如果有疑问或者需要源码可以给我留言。