我们什么时候需要使用 renderer.outputEncoding = THREE.sRGBEncoding

When do we need to use renderer.outputEncoding = THREE.sRGBEncoding

我是 three.js 的新手。我一直在通过尝试制作简单的场景并了解官方示例的工作原理来学习three.js。

最近一直在看https://threejs.org/examples/?q=trans#webgl_materials_physical_transmission,一直想不明白这里代码需要用renderer.outputEncoding = THREE.sRGBEncoding的具体原因是什么。在更简单的场景中,例如将 JPG 作为纹理加载到立方体上,如果不在渲染器上设置 outputEncoding,JPG 图像看起来就很好。

我尝试用谷歌搜索类似的主题,例如 gamma correction,人们说大多数在线图像都是以 sRGB 颜色 space 进行伽马编码的。但是我自己不能把所有的点都连起来...如果有人能给我解释清楚,我将不胜感激。

如果您不触摸 renderer.outputEncoding,则表示您的应用中没有使用颜色 space 工作流程。引擎假定所有输入颜色值都应为线性 space。并且每个片段的最终颜色值并没有转化为输出颜色space.

由于各种原因,这种工作流程存在问题。一个原因是您的 JPG 纹理很可能是 sRGB 编码以及许多其他纹理。要在片段着色器中计算正确的颜色,将所有输入颜色值转换为相同的颜色 space 很重要(这是线性颜色 space)。如果您不关心颜色 spaces,您很快就会得到错误的输出颜色。

对于简单的应用程序,这个细节通常无关紧要,因为最终图像“看起来不错”。但是,根据您在应用中所做的事情(例如导入 glTF 资产时),正确的颜色 space 工作流程是强制性的。

通过设置 renderer.outputEncoding = THREE.sRGBEncoding,您告诉渲染器将片段着色器中的最终颜色值从线性转换为 sRGB 颜色 space。因此,您还必须在纹理保存 sRGB 编码数据时告知渲染器。您可以通过将 THREE.sRGBEncoding 分配给纹理的 encoding 属性 来实现。 THREE.GLTFLoader 对所有颜色纹理自动执行此操作。但是手动加载纹理时,你必须自己做。