Three.js
Three.js 性能优化
1.渲染,抗锯齿优化
1 | const renderer = new THREE.WebGLRenderer({ |
1 | 在 Three.js 中,顶点着色器中的变量可以使用 uniform、attribute 和 varying。这些不同类型的变量用于不同的目的: |
2.性能指标检测
- 1.用户的设备性能标准 2.监测帧率 –stats.js
1 | function estimatePerformance() { |
3.画面 resize 优化,开启节流
1 | window.addEventListener("resize", () => { |
4.创建点云可以关闭深度测试
- 损失渲染精度
- 获得好的性能
1 | this.material = new THREE.PointsMaterial({ |
5.尽量使用 clone
- threejs 一切皆对象。适合: 相似度比较高的物体。
- 在 Three.js 中,clone 方法用于创建一个对象的深拷贝。这个方法可以应用于几乎所有的 Three.js 对象,包括几何体、材质、网格、场景等。通过 clone 方法,你可以复制一个对象及其所有属性,而不会影响原始对象。
1 | 在 Three.js 中使用 clone 方法可以对性能产生积极影响,主要原因如下: |
6.不需要的对象要销毁
- 不销毁的坏处?
- 占用内存,可能会有内存泄露
- 有额外的渲染开销
- 在 Three.js 中,
dispose方法用于释放对象占用的内存资源。对于几何体、材质、纹理等对象,调用dispose方法可以确保这些资源被正确地释放,从而避免内存泄漏。
1 | import * as THREE from "three"; |
7.尽量使用 BufferGeometry
- 使用
BufferGeometry对性能更好。BufferGeometry是 Three.js 中的一种几何体类型,它比传统的Geometry更高效,特别是在处理大量顶点数据时。BufferGeometry直接使用 WebGL 的缓冲区来存储顶点数据,从而减少了内存占用和 CPU 开销。- 直接使用 WebGL 缓冲区:
BufferGeometry直接使用 WebGL 的缓冲区来存储顶点数据。这意味着数据可以直接传递给 GPU(利用显存),而不需要在 CPU 和 GPU 之间进行额外的转换和处理。 - 内存布局更紧凑:
BufferGeometry使用类型化数组(如Float32Array)来存储顶点数据,这种内存布局更紧凑,减少了内存占用和缓存未命中。 - 减少 CPU 开销:由于
BufferGeometry的数据结构更简单,Three.js 在处理几何体时需要的 CPU 计算量更少。这使得渲染过程更加高效,特别是在处理大量顶点数据时。 - 更灵活的顶点属性:
BufferGeometry允许你定义自定义的顶点属性(如颜色、法线、UV 坐标等),并且可以更灵活地控制这些属性的更新和使用。
- 直接使用 WebGL 缓冲区:
1 | import * as THREE from "three"; |
8.图片纹理优化
- 在 Three.js 中,可以通过使用压缩纹理来减少内存占用和提高渲染性能。常见的压缩纹理格式包括
DDS、KTX和PVR。这些格式可以显著减少纹理的内存占用,并且在 GPU 上的解压缩速度非常快。 - 纹理压缩格式有多种,每种格式都有其独特的优点和适用场景。以下是一些常见的纹理压缩格式及其区别:
1 | 1. DDS (DirectDraw Surface) - 优点: - 支持多种压缩格式(如 DXT1、DXT5)。 - |
9.在需要的时候进行 render
- threejs,项目通常在使用 render 的函数中,是一直在执行的,就是说 gpu 是一直在占用的。导致他一直在占用电脑性能
1 | //每一帧render |
- 怎么解决?
在需要的时候,设置一个开关
- 使用场景
- 挂机时间远远大于需要动态渲染的时间
- 挂机的时候,状态可以是静止
- 本来是一直运动的,但是长时间不管,静止也 ok
1 | let renderEnabled = false; |
10.gltf 模型压缩
gltf-pipeline是一个用于处理和优化 glTF 文件的工具库。它可以用于压缩、转换和优化 glTF 3D 模型,以提高加载性能和减少文件大小。- npm install -g gltf-pipeline
1 | //在node端运行 |
- gltf-pipeline 的底层是 Draco(zhua kou)
- Draco 是 Google 开发的一种开源库,用于压缩和解压缩 3D 图形数据。它可以显著减少 3D 模型的文件大小,从而提高加载速度和减少带宽使用。
1 | import * as THREE from 'three'; |
11.模型压缩原理
- 为了减少模型的顶点和面数,同时使用法线贴图来保持视觉效果,可以使用
gltf-pipeline和Draco压缩工具来优化 glTF 文件。
1 | 1. 使用 gltf-pipeline 和 Draco 压缩工具优化 glTF 文件。 |
12.降低材质精度
- 为了降低材质精度并尽量共享材质,可以在创建材质时设置材质的精度,并在多个网格之间共享同一个材质实例。
1 | import * as THREE from 'three'; |
13.使用 LOD 技术优化
- LOD(Level of Detail)技术是一种在 3D 图形中根据物体与相机的距离动态调整物体细节层次的技术。通过使用 LOD,可以在远距离时使用低细节模型,在近距离时使用高细节模型,从而提高渲染性能。
- 利用压缩工具对同一种模型,导出 3 种精度的模型(顶点数量不一样)
- 高精
- 中等
- low
1 | import * as THREE from "three"; |
14.使用 indexdb 存取模型
- CDN 加速,强制缓存
- 本地的加载模型,304 已经代表进行了协商缓存
- 使用 indexdb 进行缓存
IndexedDB 和 localStorage 都是浏览器提供的客户端存储解决方案,但它们在功能和使用场景上有显著的区别。
1 | IndexedDB |
1 | localStorage |
- Three.js 可以与 IndexedDB 一起使用来存储和检索 3D 模型。这可以提高应用的性能,特别是在需要频繁加载相同模型的情况下。
1 | import * as THREE from 'three'; |
15.离屏渲染
什么是离屏渲染
1.three 加载的模型一切皆对象,那么 three 经过一些列计算后,把模型渲染到屏幕上。那么离屏渲染就是不用渲染到屏幕上,因为渲染到屏幕(绘制)上一定会有一个过程叫 ➡ 光栅化
光栅化的作用,就是将 3d 模型进行各种变化,通过 2d 渲染到屏幕上
那么离屏 它就没有光栅化
那么到底什么是离屏渲染呢、
比如 b 页面是淘宝的双十一页面,那么进入双十一页面就必须先进入淘宝首页,那么我们可以在进入淘宝首页的时候就加载双十一页面,(只是加载,不渲染)这个就是离屏渲染。
再比如:视频导出功能,浏览器可以录制 canvas 的渲染结果,浏览器有 api 可以把它录制下来,然后转成视频;我要录制一个 10s 的过程,大概是 600 帧,(1s60 帧,10s600 帧),这个时候就会从 canvas 截取 600 个画面,(600 个图),然后进行拼接成视频,剪映的导出就是离屏渲染。背后就是 canvas 在运行,输出画面。但是并没有进行绘制,因为绘制就涉及到了光栅化。还有一点就是导出时用户不需要看到画面。
1 | import * as THREE from 'three'; |
16.场景阴影
- 阴影在需要时打开
1 | if (data.castShadow) { |
17.降低渲染帧率
requestAnimationFrame 它可以获取到屏幕的刷新率,settimeout 不准确
正常用户 80% 60 帧
根据用户设备性能,做判断。
1 | const start = () => { |
18.按需导入 Threejs 依赖,减少编译之后的包体积
- Tree shaking 优化
比如 1m 优化到 600k
1 | import { WebGLRenderer, Scene, PerspectiveCamera, Color, Clock } from "three"; |
19.视锥体剔除
- 视锥体剔除(Frustum Culling)是一种优化技术,用于在渲染场景时剔除那些不在相机视锥体内的物体,从而减少渲染负担。Three.js 内置了视锥体剔除功能,但你需要确保物体的
frustumCulled属性设置为true(默认值)。
1 | import * as THREE from 'three'; |