直接回答:加了后期处理器场景变黑,多半是颜色空间的问题,需要插入一个 GammaCorrectionShader 把输出转回来;这类看起来像 bug 的现象基本都是颜色空间或渲染顺序造成的。

1.添加处理器之后场景变黑

是因为颜色格式问题,解决办法如下

1
2
3
4
let renderPass = new RenderPass(globalVariable.scene, globalVariable.camera);
composer.addPass(renderPass);
const gammaCorrectionShader = new ShaderPass(GammaCorrectionShader);
composer.addPass(gammaCorrectionShader);

在renderPass之后添加一个GammaCorrect矫正

2.线框三角面片

1
2
3
4
5
6
7
8
9
10
const newObj=gltfObj.clone()
newObj.traverse((o) => {
if (o.type == "Mesh") {
const edges = new THREE.EdgesGeometry((o as THREE.Mesh).geometry);
const aa = new THREE.LineSegments(edges,xiankuangmaterial);
o.visible=false
o.parent?.add(aa)

}
})

3.关于异步加载

1
2
3
4
5
6
7
8
9
const rgbeLoader = new RGBELoader()
.setPath( 'textures/equirectangular/' );

const gltfLoader = new GLTFLoader().setPath( 'models/gltf/' );

const [ texture, gltf ] = await Promise.all( [
rgbeLoader.loadAsync( 'venice_sunset_1k.hdr' ),
gltfLoader.loadAsync( 'IridescenceLamp.glb' ),
] );

4. 关于颜色

因此你无需更改除颜色、环境和自发光贴图以外的任何纹理的编码。

5. 关于渲染器的几个优化建议

  1. 不要启用 preserveDrawingBuffer,除非你确实需要
  2. 除非需要,否则禁用透明缓冲区(alpha buffer )。
  3. 除非需要,否则不要启用模板缓冲区(stencil buffer)。
  4. 除非需要,否则禁用深度缓冲区(depth buffer)(但您可能确实需要它)。
  5. 创建渲染器时使用powerPreference: "high-performance"。这可能会促使用户的系统在多 GPU 系统中选择高性能 GPU。
  6. 仅当相机位置的发生变化或动画发生时才考虑渲染。
  7. 如果你的场景是静态的并使用OrbitControls相机,你可以监听控件的change 事件。这样你就可以只在相机移动时渲染场景:

6. 关于光照

  1. 直射光(SpotLight、PointLight、RectAreaLight和DirectionalLight)很影响性能。在您的场景中尽可能少使用直射光。
  2. 避免在场景中添加和删除光,因为这需要WebGLRenderer重新编译所有着色器程序(它确实缓存了程序,因此后续执行此操作的时间会比第一次更快)。取而代之的使用light.visible = false或light.intensiy = 0。
  3. 打开renderer.physicallyCorrectLights,使用 国际单位制的正确光照。

7. 关于阴影

  1. 如果您的场景是静态的,则仅在事物发生变化时更新阴影贴图,而不是每一帧。
  2. 使用 CameraHelper可视化阴影相机的视锥体。
  3. 使阴影视锥体尽可能小。
  4. 使阴影纹理的分辨率尽可能低。
  5. 请记住,点光源阴影比其他阴影类型更消耗性能,因为它们必须渲染六次(每个方向一次),而DirectionalLight和SpotLight阴影则需渲染一次。
  6. 当我们谈论PointLight阴影时,请注意,当用于可视化点光源阴影时,CameraHelper只可视化了六个阴影方向中的一个。它仍然很有用,但你需要在其他五个方向上发挥你的想象力。

8. 关于材质

  1. MeshLambertMaterial不适用于闪亮拉丝的材质,但对于像布料这样的哑光材质,它会产生非常相似MeshPhongMaterial的结果,但性能更高。
  2. 如果你使用的是顶点变形目标(morph targets),请确保您在材质中设置了 morphTargets = true,否则它们将不起作用!
  3. 这同样适用于 变形法线 morph normals。
  4. 如果你正在使用 SkinnedMesh来制作骨骼动画,确保 material.skinning = true.
  5. 与变形目标、变形法线或蒙皮一起使用的材质无法共享。你需要为每个蒙皮或变形的网格创建单独的材质( material.clone()在这里非常适用)。

9. 自定义材质

  1. 仅在你的 uniform 变量发生变化时更新它,而不是每一帧。

10. 几何

  1. 避免使用 LineLoop,因为它必须由直线拟合而成。

11. 纹理

  1. 你所有的纹理都需要是 2 的幂次方 (POT) 大小

    1 、2 、4 、8 、16 ,…,512 ,2048 ,….

  2. 不要更改纹理的尺寸。而是创建新的, 性能更高

  3. 尽可能使用最小尺寸的纹理(您可以使用 256x256 的平铺纹理吗?您可能会感到惊讶!)。

  4. 非 2 的幂次方 (NPOT) 纹理需要 linear 或 nearest filtering 滤镜参数设置,以及 clamp-to-border 或 clamp-to-edge 包裹方式( 详见 textures 常量)。不支持 Mipmap 过滤和重复包裹。但说真的,就不要使用 NPOT 纹理。

  5. 具有相同尺寸的纹理在内存中的大小相同,因此 JPG 的文件可能比 PNG 小,但它会在您的 GPU 上占用相同数量的内存。

12. 抗锯齿

  1. 抗锯齿的最坏情况是几何体由许多相互平行排列的细直片组成。想想金属百叶窗或格子栅栏。如果可能的话,**不要在场景中包含这样的几何体。**如果别无选择,请考虑用纹理替换晶格,因为这可能会产生更好的结果。

13. 后处理

  1. 内置抗锯齿功能不适用于后期处理(至少在 WebGL 1 中)。您需要手动使用 FXAA或 SMAA(可能更快、更好)。
  2. 当你没有使用内置抗锯齿( AA),请务必禁用它!
  3. three.js 有大量的后处理着色器,这太棒了!但请记住,每个通道都需要渲染整个场景。完成测试后,请考虑是否可以将你的通道合并为一个自定义通道。这样会需要多做一些工作,但可以显着提高性能。

14. 物体的释放

从你的场景中删除一些东西?

首先,考虑不这样做,特别是如果你稍后还需要添加回来。你可以暂时隐藏对象,设置object.visible = false(也适用于光照)或material.opacity = 0。你可以设置light.intensity = 0禁用光照而不会导致着色器重新编译。

如果您确实需要从场景中永久移除物品,请先阅读这篇文章: 如何释放物体-How to dispose of objects。

15. 更新场景中的对象?#

阅读这篇文章: 如何更新-How to update things。

16. 性能

  1. 为静态或很少移动的物体设置object.matrixAutoUpdate = false ,并手动调用object.updateMatrix() 在其位置/旋转/四元数/缩放更新时。
  2. **透明物体很消耗性能。**在场景中尽可能少使用透明物体。
  3. 尽可能使用 alphatest , 而不是标准透明度,它会更快。
  4. 在测试应用程序的性能时,你需要做的第一件事就是检查它是受 CPU 限制还是受 GPU 限制。使用基础材质(basic material )替换所有材质scene.overrideMaterial(请参阅入门技巧和页面的开头)。如果性能提高,那么你的应用程序受 GPU 限制。如果性能没有提高,则你的应用程序受 CPU 限制。
  5. 在性能好的机器上进行性能测试时,你可能最多获得 60FPS 的帧率。运行 chrome 以open -a "Google Chrome" --args --disable-gpu-vsync获得无限制的帧率。
  6. 现代移动设备的像素比高达 5 - 考虑将这些设备上的最大像素比限制为 2 或 3。以场景的一些非常轻微的模糊为代价,你将获得可观的性能提升。
  7. 烘焙光照和阴影贴图以减少场景中的光照数量。
  8. 密切关注场景中的绘制方法的(drawcalls)调用次数。一个好的经验法则是更少的绘制调用 = 更好的性能。
  9. 远处的物体不需要同靠近相机的物体具有相同的模型精度。有许多可以降低远处物体的精度的技巧来提高性能。考虑使用 LOD(细节层次)物体。你也可以只为远处的物体每 2 或 3 帧更新位置/动画,或者用 billboard 替换它们 - 即物体的图片。

17. 高阶技巧

  1. 不要用TriangleFanDrawMode,很耗性能。
  2. 当您有成百或上千个相似的几何图形时,请使用几何实例化。
  3. 在 GPU 而非 CPU 上进行动画处理,尤其是在为顶点或粒子设置动画时(请参阅 THREE.Bas以了解执行此操作的一种方法)。

18.关于怎么取消上下拉动的时候浏览器留下的边框

image-20240327235959523

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

image-20240328000215887

这个是为了解决向下拖动触控板出现空白的

19.关于屏幕尺寸变化需要做的

1
2
3
4
5
6
7
8
9
10
11
window.addEventListener('resize',()=>
// Update sizes
sizes.width = window.innerWidth
sizes.height = window.innerHeight
// Update camera
camera.aspect = sizes.width / sizes.height
camera.updateProjectionMatrix()
// Update renderer
renderer.setSize(sizes.width, sizes.height)
})

1
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)) // 屏幕像素比

20.全屏最新代码

1
2
3
4
5
6
7
window.addEventListener('dblclick', () => {
if (!document.fullscreenElement) {
canvas.requestFullscreen()
} else {
document.exitFullscreen()
}
})

21.如果指定贴图过滤器,那么就禁止生成mip映射

1
2
3
colorTexture.generateMipmaps=false
colorTexture.minFilter=THREE.NerarestFilter
colorTextture.magFilter=THREE.NearestFilter // 很小的贴图用在很大的物体上,正常会很模糊,如果用上这个过滤就会很清晰,教程里的黑白棋盘

23.没有灯光的时候可以用MeshMatcapMaterial材质,

可以不打灯光直接用这个材质,这个材质里面直接把明暗烘焙进去

这篇笔记整理自我自己的实践记录,如果做法有出入,或者你踩过别的坑,欢迎到留言板一起聊聊。

站内搜索

没有找到内容!