本文主要是介绍Three.js 效能要点,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
本文在线示例查看。更多精彩内容尽在数字孪生平台,关注公众号:sky的数孪技术,技术交流、源码下载请添加VX:digital_twin123
模型方面:
- 尽量合并模型,以减少drawcalls
- 不要合并远距离模型,因为对于远距离模型而言裁剪过滤比合并更有效
- 次要物体尽量减面,主要物体使用LOD,LOD可以针对整体区域也可以针对单个模型
- 删除不必要的(如物体内部、看不到的外墙等)面
- 尽可能合并贴图,多个物体共用UV空间和贴图,多种贴图合并通道
- 尽量使用预烘焙,比如光照、阴影、光晕效果
- 面与面之间的距离保持2mm以上,避免zfighting(闪烁)
- 避免物体放置在视锥体的远平面附近,避免zfighting(闪烁)
- 使用贴图(比如十字贴图)和简单的平面来模拟复杂形状的模型,比如台阶模拟,餐桌瓶子模拟
- 尽量复制对象,这样几何体、材质、贴图资源可以共用
- 避免单个Mesh占据过大的区域,不利于裁剪优化
- 场景合理布局,尽量避免Mesh过于集中堆放
- 对于gltf模型,使用blender启用压缩来导出模型或使用命令行压缩工具(如gltf-pipeline)对其进行压缩:gltf-pipeline -i inputModel.gltf -o outputModel.gltf -d
- 模型分布在原点周围,不要整体偏移在很远的坐标处,尽可能使用实际尺寸,不要用很大(或很小)的缩放
程序方面:
- 使用stats插件来监控性能指标
FPS Frames rendered in the last second. 越高越好,不要低于30
MS Milliseconds needed to render a frame. 越低越好
MB MBytes of allocated memory.
- 使用http://renderer.info来实现检测drawcalls等数据
console.log("Scene polycount:", renderer.info.render.triangles)
console.log("Active Drawcalls:", renderer.info.render.calls)
console.log("Textures in Memory", renderer.info.memory.textures)
console.log("Geometries in Memory", renderer.info.memory.geometries)
- 尽可能复用geometry、material和texture
- 避免在render loop中创建任何对象
- 避免使用文本格式的模型,使用二进制格式的数据,对于主要用途是web端浏览的应用程序而言,glb是最好的格式,对于要在线编辑模型的应用而言,可以选用fbx
- 尽量少使用光源,光照是很消耗渲染性能的,使用预烘培贴图来模拟光照和阴影
- 尽量小的FOV和FAR,使用响应式FOV,即对于PC使用较大值,手机使用较小值
- 在创建渲染器时选择powerPreference:“高性能”。这可能会使用户系统在多GPU系统中选择高性能GPU
- 尽可能的禁用抗锯齿,在使用Retina技术的设备上开启AA的效果不明显,可以禁用掉,比如使用如下代码:
let pixelRatio = window.devicePixelRatio
let AA = true
if (pixelRatio > 1) {AA = false
}this.renderer = new THREE.WebGLRenderer({antialias: AA,powerPreference: "high-performance",
})
- 尽量不要动态在场景中添加和删除光源,因为这会导致WebGLRenderer重新编译shader程序,使用:
light.visible = falseorlight.intensiy = 0
- 使用光源时,尽量限定范围,比如pointlight的距离,AmbientLight、DirectionalLight和HemisphereLight 是轻量级的。PointLight阴影是昂贵的,因为它需要在6个方向上渲染。
- 合理使用材质,尽可能减少物理材质的使用:
MeshPhysicalMaterial : slowest/highest quality
MeshStandardMaterial : near to physical material
MeshPhongMaterial
MeshLambertMaterial : might be removed from future three.js, near to PhongMaterial without specular
MeshBasicMaterial fastest/lowest quality, not affected by lights
MeshBasicMaterial是threejs引擎里的unlit material,尽可能使用unlit material加贴图来模拟视觉效果
- 材质尽量使用单面,尽量少用透明材质,因为透明物体性能低下
- 尽量减少不必要的循环刷新,使用needsUpdate来控制对象的刷新,比如仅当camera变动、orbitcontrols触发change事件、或者动画播放时,才调用render update:
OrbitControls.addEventListener("change", () => renderer.render(scene, camera));
- 对于大规模场景,尽量使用LOD控制,并使用延迟加载(靠近时加载)
- 对于大屏,尽量不要应用SSR和屏幕空间的后效处理
- 对于大量重复物体,如花草树木,使用实例化对象
- 如果多个类似物体按规律排列在空间中,那么选取策略可以合并所有物体然后使用空间坐标寻址,而不必使用射线和每个物体进行选取检测
- 和18类似,更普遍的,使用BVH算法来加速光线投射并支持快速的3D空间查询: three-mesh-bvh
- 在需要构建碰撞检测的场合,尽可能减少不必要的碰撞体,比如使用octree来构建时,根据场景,采取忽略一定高度以上的物品,忽略尺寸很小的物品等策略
- 使用draco压缩解压gltf模型,或者gltfpack,自行测试下具体哪个效果更好
- 关闭不必要的阴影效果,对于light castShadow=false, 对于mesh castShadow=false, receiveShadow=false,对于需要的阴影,使阴影截锥体尽可能小,使阴影纹理的分辨率尽可能低
- devicePixelRatio很影响性能,有些设备dpi能达到5,程序最好对此做出限制,不要超过3,在牺牲少量清晰度的情况下,能大幅度提升性能
- 如果要整体隐藏或显示场景中的部分模型,使用layers来管理这些模型集合
- 使用尽量少的贴图,贴图尽量使用jpg而非png,尽可能的压缩以减少尺寸,自行实现足够用的贴图mipmap,而不是由程序生成(可能会多余)
这篇关于Three.js 效能要点的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!