iOS 的 WebGL 实现相对严格,某些特性可能不兼容,需要特殊处理,以下是一些优化项
一、设置renderer
this.renderer = new THREE.WebGLRenderer({
antialias: true, // 启用抗锯齿。设置为 true 可以减少图形锯齿现象,默认值为 false
alpha: true, // 启用透明背景。设置为 true 时,背景为透明,默认值为 false
logarithmicDepthBuffer: true, // 启用对数深度缓冲区,以便改善远处物体的深度精度,尤其在场景中有大范围深度差异时。默认值为 false
})
this.renderer.setPixelRatio(2) // 一般均设置为window.devicePixelRatio,但在iso上建议不要设置为window.devicePixelRatio
二、及时释放资源
disposeResources(model) {
if (!model) return;
// 1. 从场景移除
this.scene.remove(model);
// 2. 遍历所有子对象
model.traverse((child) => {
// 释放几何体
if (child.geometry) {
child.geometry.dispose();
}
// 释放材质 & 纹理
if (child.material) {
if (Array.isArray(child.material)) {
child.material.forEach((material) => {
for (const key in material) {
if (material[key] && material[key].isTexture) {
material[key].dispose(); // 释放纹理
}
}
material.dispose();
});
} else {
for (const key in child.material) {
if (child.material[key] && child.material[key].isTexture) {
child.material[key].dispose();
}
}
child.material.dispose();
}
}
// 释放骨骼
if (child.isSkinnedMesh) {
child.skeleton.dispose();
}
});
// 3. 删除对象
model = null;
// 4. 清理 WebGL 缓存
if (typeof this.renderer !== "undefined") {
this.renderer.renderLists.dispose();
}
}
三、如果使用了png等图片,转成ktx2压缩纹理。
转换方法参考:png图片压缩成ktx2-优快云博客
import { KTX2Loader } from 'three/examples/jsm/loaders/KTX2Loader.js'
this.ktx2Loader = new KTX2Loader()
.setTranscoderPath('./threelib/basis/')
.detectSupport(this.renderer)
this.ktx2Loader.loadAsync(url)
四、压缩使用到的glb模型。压缩方法参考 glb压缩方案-优快云博客
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js'
import { KTX2Loader } from 'three/examples/jsm/loaders/KTX2Loader.js';
import { MeshoptDecoder } from 'three/examples/jsm/libs/meshopt_decoder.module.js';
const dracoLoader = new DRACOLoader()
dracoLoader.setDecoderPath('./threelib/draco/') // 设置解码器的路径,解码器可以在 Three.js 示例中找到
const ktx2Loader = new KTX2Loader()
.setTranscoderPath('./threelib/basis/') // BasisU 转码器路径
.detectSupport(this.renderer);
this.loader = new GLTFLoader()
this.loader.setDRACOLoader(dracoLoader) // 将 DracoLoader 设置到 GLTFLoader
this.loader.setKTX2Loader(ktx2Loader); // 确保在加载前调用 setKTX2Loader
this.loader.setMeshoptDecoder(MeshoptDecoder); // 确保在加载前调用 setMeshoptDecoder
this.loader.load(url, (obj) => {
this.scene.add(obj.scene)
})