1. three.js中大多数材质需要有了光照才可以看到, MeshBasicMaterial 是一种不需要光照就可以见的材质。看看你那显示不了的东西,是不是缺少了光照~
  2. 物体不在相机的视锥体内,是会被裁剪掉,看不到滴,相机的视锥体以米为单位。为了获得最佳性能,应设置的尽可能的小(FPS提升一小步,性能提升一大步)。
  3. 不要把物体放在远剪裁平面上(特别是如果你的远剪裁平面真的很大),因为这会引起闪烁。
  4. three.js中的一个单位对应的是一米。如果你加载了模型看不到,找找屏幕中间的小黑点~,可以用scale把它放大。
    three.js处处都是用的国际单位制。如果处于某种原因使用不同类型的单位(例如:英寸),让人头秃。
    国际单位制(SI Units)
    ○ 距离以米为单位(three.js的1单位 = 1米)
    ○ 时间以秒为单位
    ○ 光照以国际光照强度单位测量,坎德拉(cd)、流明(lm)和勒克斯(lx)。至少需要开启renderer.physicallyCorrectLights
    如果你要创建史诗级规模场景(空间模拟或类似的东西),请使用缩放因子或切换到使用对数深度缓冲区-logarithmic depth buffer
  5. 如果你需要操作大量物体可见和不可见(或从场景中添加/删除它们),请考虑使用图层-Layers以获得最佳性能。
  6. 永远不要移动你的场景(Scene)。在(0,0,0)位置创建,这是其中所有物体的默认参考系。
  7. 尽可能减少渲染循环中的消耗,不要每帧都创建新的对象。应创建一个单一的对象,例如Vector3并使用**vector.set()**或类似的方法来重用循环内的对象。
  8. 总是使用BufferGeometry,而不是Geometry,它更快,性能更好。预先封装好的对象也是如此,始终使用缓冲几何版本BoxBufferGeometry而不是BoxGeometry。始终尝试重用对象,例如物体,材质,纹理等(尽管更新某些内容可能比创建新内容慢)
  9. 避免使用常见的基于文本的3D数据格式(例如obj)进行数据交付。取而代之,请使用针对Web端优化的格式,例如gltf。可以使用Draco对gltf进行网格压缩,或者使用gltfpack
  10. 针对渲染器方面:非必要就不要启用preserveDrawingBuffer,禁用透明缓冲区,禁用深度缓冲区,禁用模版缓冲区。创建渲染器时使用powerPreference:"high-performance",这可能会促使用户系统在多GPU系统中选择高性能GPU。仅在相机位置发生变化或动画发生时才考虑渲染。使用OrbitControls相机,可以监听控件的change事件。在相机移动时渲染场景:
    OrbitControls.addEventListener("change", () => renderer.render(scene, camera));
  11. 光照方面:
    a. 直射光(SpotLightPointLightRectAreaLightDirectionalLight)很影响性能,尽可能少使用直射光。
    b. 避免在场景中添加和删除光,因为这需要WebGLRenderer重新编译所有着色器程序,使用light.visible = falselight.intensiy = 0
    c. 打开renderer.physicallyCorrectLights,使用国际单位制的正确光照。
  12. 阴影方面:
    a. 如果场景是静态的,仅在事物发生变化时更新阴影贴图。
    b. 使用CameraHelper可视化阴影相机的视锥体,使阴影视锥体尽可能小,使阴影纹理的分辨率尽可能低。
    c. 点光源阴影比其他阴影类型更消耗性能,因为它们必须渲染六次(每个方向一次),而DirectionalLightSpotLight阴影则需要渲染一次。
    d. 使用PointLight阴影时,请注意,当用于可视化点光源阴影时,CameraHelper只可视化了六个阴影方向中的一个。
  13. 材质方面:
    a. MeshLambertMateria不适用于闪亮拉丝的材质,当对于像布料这样的哑光材质,它会产生非常相似MeshPhongMaterial的结果,但性能更高。
    b. 如果使用的是顶点变形目标(morph targets),请确保你在材质中设置了morphTargets = true,否则它们将不起作用,这同样适用于变形法线(morph normals)。
    c. 使用SkinnedMesh来制作骨骼动画,确保material.skinning = true
    d. 与变形目标,变形法线或蒙皮一起使用的材质无法共享。需要为每个蒙皮或变形的网格创建单独的材质(material.clone()在这里非常适用)
    e. 自定义材质:仅在你的uniform变量发生变化时更新它,而不是每一帧。
  14. 几何:避免使用LineLoop,因为它必须由直线拟合而成。
  15. 纹理
    a. 纹理需要是2的幂次方(POT)大小
    b. 不要更改纹理的尺寸,而是创建新的,性能更高。
    c. 尽可能使用最小尺寸的纹理。
    d. 非2的幂次方(NPOT)纹理需要linearnearest filtering滤镜参数设置,以及clamp-to-borderclamp-to-edge包裹方式(详见textures常量)不支持Mipmap过滤和重复包裹。(还是不要使用NPOT纹理啦)
    e. 具有相同尺寸的纹理在内存中的大小相同,因此JPG的文件可能比PNG小,但它会在你的GPU上占用相同数量的内存。
  16. 抗锯齿:抗锯齿的最坏情况是几何体由许多相互平行排列的细直片组成。想想金属百叶窗或格子栅栏。如果可能的话,不要在场景中包含这样的几何体。如果别无选择,请考虑用纹理替换晶格,因为这可能会产生更好的结果。
  17. 后处理
    a. 内置抗锯齿功能不适合用于后期处理(至少在WebGL 1中)。您需要手动使用FXAASMAA(可能更快,更好)。
    b. 没有使用内置抗锯齿的时候,请禁用它。
    c. three.js中有大量的后处理着色器。但请记住,每个通道都需要渲染整个场景。完成测试后,请考虑是否可以将你的通道合并为一个自定义通道。这样虽要多做一些工作,但可以显著提高性能。
  18. 物体的释放
    a. 如果你稍后还需要添加回来。你可以暂时隐藏对象,设置object.visible = false(也适用于光照)或material.opacity = 0。你可以设置light.intensity = 0禁用光照而不会导致着色器重新编译。
    b. 如果你确实需要从场景中永久的移除物品,请看:如何释放物体-How to dispose of objects
  19. 更新场景中的对象:如何更新 - How to update things
  20. 性能:
    a. 为静态或很少移动的物体设置object.matrixAutoUpdate = fase,并手动调用object.updateMatrix()在(位置/旋转/四元数/缩放)更新时。
    b. 透明物体很消耗性能,在场景中尽可能少使用透明物体。
    c. 尽可能使用alphatest,而不是标准透明度,它会更快。
    d. 在测试应用程序的性能时,你需要做的第一件事就是检查它是受CPU限制还是受GPU限制。使用基础材质替换所有材质scene.overrideMaterial。如果性能提高,那么你的应用程序受GPU限制。如果性能没有提高,则你的程序受CPU限制。
    e. 在性能好的机器上进行性能测试时,你可能最多获得60FPS的帧率。运行chrome以open -a "Google Chrome" --args --disable-gpu-vsync获得无限制的帧率。
    f. 现代移动设备的像素比高达5。考虑将这些设备上的最大像素比限制为2或3。以场景的一些非常轻微的模糊为代价,你将获得可观的性能提升。
    g. 烘培光照和阴影贴图以减少场景中的光照数量。
    h. 密切关注场景中的绘制方法的(drawcalls)调用次数。一个好的经验法则 是更少的绘制调用 = 更好的性能。
    i. 远处的物体不需要同靠近相机的物体具有相同的模型精度。有许多可以降低远处物体的精度的技巧来提高性能。考虑使用LOD(细节层次)物体。你也可以只为远处的物体每2或3帧更新位置/动画,或者用billboard替换它们-即物体的图片。
  21. 不要使用TriangleFanDrawMode,很耗性能。
  22. 当你有成百或上千个相似的几何图形时,请使用几何实例化。
  23. 在GPU而非CPU上进行动画处理,尤其是在为顶点或粒子设置动画时(参阅THREE.Bas)

推荐阅读:
Threejs 技巧和窍门大清单!

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐