直接回答:加了后期处理器场景变黑,多半是颜色空间的问题,需要插入一个 GammaCorrectionShader 把输出转回来;这类看起来像 bug 的现象基本都是颜色空间或渲染顺序造成的。
1.添加处理器之后场景变黑
是因为颜色格式问题,解决办法如下
1 | let renderPass = new RenderPass(globalVariable.scene, globalVariable.camera); |
在renderPass之后添加一个GammaCorrect矫正
2.线框三角面片
1 | const newObj=gltfObj.clone() |
3.关于异步加载
1 | const rgbeLoader = new RGBELoader() |
4. 关于颜色
因此你无需更改除颜色、环境和自发光贴图以外的任何纹理的编码。
5. 关于渲染器的几个优化建议
- 不要启用
preserveDrawingBuffer,除非你确实需要 - 除非需要,否则禁用透明缓冲区(alpha buffer )。
- 除非需要,否则不要启用模板缓冲区(stencil buffer)。
- 除非需要,否则禁用深度缓冲区(depth buffer)(但您可能确实需要它)。
- 创建渲染器时使用
powerPreference: "high-performance"。这可能会促使用户的系统在多 GPU 系统中选择高性能 GPU。 - 仅当相机位置的发生变化或动画发生时才考虑渲染。
- 如果你的场景是静态的并使用
OrbitControls相机,你可以监听控件的change事件。这样你就可以只在相机移动时渲染场景:
6. 关于光照
- 直射光(
SpotLight、PointLight、RectAreaLight和DirectionalLight)很影响性能。在您的场景中尽可能少使用直射光。 - 避免在场景中添加和删除光,因为这需要
WebGLRenderer重新编译所有着色器程序(它确实缓存了程序,因此后续执行此操作的时间会比第一次更快)。取而代之的使用light.visible = false或light.intensiy = 0。 - 打开
renderer.physicallyCorrectLights,使用 国际单位制的正确光照。
7. 关于阴影
- 如果您的场景是静态的,则仅在事物发生变化时更新阴影贴图,而不是每一帧。
- 使用
CameraHelper可视化阴影相机的视锥体。 - 使阴影视锥体尽可能小。
- 使阴影纹理的分辨率尽可能低。
- 请记住,点光源阴影比其他阴影类型更消耗性能,因为它们必须渲染六次(每个方向一次),而
DirectionalLight和SpotLight阴影则需渲染一次。 - 当我们谈论
PointLight阴影时,请注意,当用于可视化点光源阴影时,CameraHelper只可视化了六个阴影方向中的一个。它仍然很有用,但你需要在其他五个方向上发挥你的想象力。
8. 关于材质
MeshLambertMaterial不适用于闪亮拉丝的材质,但对于像布料这样的哑光材质,它会产生非常相似MeshPhongMaterial的结果,但性能更高。- 如果你使用的是顶点变形目标(morph targets),请确保您在材质中设置了
morphTargets = true,否则它们将不起作用! - 这同样适用于 变形法线 morph normals。
- 如果你正在使用 SkinnedMesh来制作骨骼动画,确保
material.skinning = true. - 与变形目标、变形法线或蒙皮一起使用的材质无法共享。你需要为每个蒙皮或变形的网格创建单独的材质(
material.clone()在这里非常适用)。
9. 自定义材质
- 仅在你的 uniform 变量发生变化时更新它,而不是每一帧。
10. 几何
- 避免使用
LineLoop,因为它必须由直线拟合而成。
11. 纹理
你所有的纹理都需要是 2 的幂次方 (POT) 大小
1 、2 、4 、8 、16 ,…,512 ,2048 ,….
不要更改纹理的尺寸。而是创建新的, 性能更高
尽可能使用最小尺寸的纹理(您可以使用 256x256 的平铺纹理吗?您可能会感到惊讶!)。
非 2 的幂次方 (NPOT) 纹理需要 linear 或 nearest filtering 滤镜参数设置,以及 clamp-to-border 或 clamp-to-edge 包裹方式( 详见 textures 常量)。不支持 Mipmap 过滤和重复包裹。但说真的,就不要使用 NPOT 纹理。
具有相同尺寸的纹理在内存中的大小相同,因此 JPG 的文件可能比 PNG 小,但它会在您的 GPU 上占用相同数量的内存。
12. 抗锯齿
- 抗锯齿的最坏情况是几何体由许多相互平行排列的细直片组成。想想金属百叶窗或格子栅栏。如果可能的话,**不要在场景中包含这样的几何体。**如果别无选择,请考虑用纹理替换晶格,因为这可能会产生更好的结果。
13. 后处理
- 内置抗锯齿功能不适用于后期处理(至少在 WebGL 1 中)。您需要手动使用 FXAA或 SMAA(可能更快、更好)。
- 当你没有使用内置抗锯齿( AA),请务必禁用它!
- three.js 有大量的后处理着色器,这太棒了!但请记住,每个通道都需要渲染整个场景。完成测试后,请考虑是否可以将你的通道合并为一个自定义通道。这样会需要多做一些工作,但可以显着提高性能。
14. 物体的释放
从你的场景中删除一些东西?
首先,考虑不这样做,特别是如果你稍后还需要添加回来。你可以暂时隐藏对象,设置object.visible = false(也适用于光照)或material.opacity = 0。你可以设置light.intensity = 0禁用光照而不会导致着色器重新编译。
如果您确实需要从场景中永久移除物品,请先阅读这篇文章: 如何释放物体-How to dispose of objects。
15. 更新场景中的对象?#
阅读这篇文章: 如何更新-How to update things。
16. 性能
- 为静态或很少移动的物体设置
object.matrixAutoUpdate = false,并手动调用object.updateMatrix()在其位置/旋转/四元数/缩放更新时。 - **透明物体很消耗性能。**在场景中尽可能少使用透明物体。
- 尽可能使用
alphatest, 而不是标准透明度,它会更快。 - 在测试应用程序的性能时,你需要做的第一件事就是检查它是受 CPU 限制还是受 GPU 限制。使用基础材质(basic material )替换所有材质
scene.overrideMaterial(请参阅入门技巧和页面的开头)。如果性能提高,那么你的应用程序受 GPU 限制。如果性能没有提高,则你的应用程序受 CPU 限制。 - 在性能好的机器上进行性能测试时,你可能最多获得 60FPS 的帧率。运行 chrome 以
open -a "Google Chrome" --args --disable-gpu-vsync获得无限制的帧率。 - 现代移动设备的像素比高达 5 - 考虑将这些设备上的最大像素比限制为 2 或 3。以场景的一些非常轻微的模糊为代价,你将获得可观的性能提升。
- 烘焙光照和阴影贴图以减少场景中的光照数量。
- 密切关注场景中的绘制方法的(drawcalls)调用次数。一个好的经验法则是更少的绘制调用 = 更好的性能。
- 远处的物体不需要同靠近相机的物体具有相同的模型精度。有许多可以降低远处物体的精度的技巧来提高性能。考虑使用 LOD(细节层次)物体。你也可以只为远处的物体每 2 或 3 帧更新位置/动画,或者用 billboard 替换它们 - 即物体的图片。
17. 高阶技巧
- 不要用
TriangleFanDrawMode,很耗性能。 - 当您有成百或上千个相似的几何图形时,请使用几何实例化。
- 在 GPU 而非 CPU 上进行动画处理,尤其是在为顶点或粒子设置动画时(请参阅 THREE.Bas以了解执行此操作的一种方法)。
18.关于怎么取消上下拉动的时候浏览器留下的边框

这里的position,top,left是为了全浏览器窗口查看

这个是为了解决向下拖动触控板出现空白的
19.关于屏幕尺寸变化需要做的
1 | window.addEventListener('resize',()=> |
1 | renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)) // 屏幕像素比 |
20.全屏最新代码
1 | window.addEventListener('dblclick', () => { |
21.如果指定贴图过滤器,那么就禁止生成mip映射
1 | colorTexture.generateMipmaps=false |
23.没有灯光的时候可以用MeshMatcapMaterial材质,
可以不打灯光直接用这个材质,这个材质里面直接把明暗烘焙进去
这篇笔记整理自我自己的实践记录,如果做法有出入,或者你踩过别的坑,欢迎到留言板一起聊聊。