three.js伽马校正和自定义着色器

5
我不确定THREE.js内部如何处理伽马校正。似乎启用它的唯一方法是在渲染器对象上设置以下标志:
gammaInput = true; gammaOutput = true;
然而,当您编写自定义着色器并从纹理中获取颜色时,是否仍需要将颜色转换为线性空间,或者THREE.js会在上传到GPU之前转换纹理(当gammaInput设置为true时)?
类似地,当在您的着色器中确定最终颜色时,是否必须将其转换为伽玛空间,或者THREE.js自动应用后处理效果(当gammaOutput设置为true时)?
谢谢

请查看 https://github.com/mrdoob/three.js/issues/1488 - gaitat
2个回答

3

在上传到GPU之前,Three.js不会将你的纹理映射到另一个空间。所有操作都是在着色器中使用代码块来完成。

将输入值转换为线性:

以Three.js处理map属性为例,可以在这里看到它的处理方式。基本上你会看到这行代码:

texelColor = mapTexelToLinear( texelColor );
mapTexelToLinear基本上是在WebGLProgram.js文件中创建的。
你明白了。
总之,你可以在着色器顶部包含这个代码块
#include <encodings_pars_fragment>

然后,您需要根据纹理所在的空间解码纹理像素。例如,如果您使用sRGB纹理:

vec4 color = sRGBToLinear(texel);

输出伽马校正值:

您还需要在着色器顶部包含encodings_pars_fragment

#include <encodings_pars_fragment>

你需要在自定义着色器的末尾包含修改片元颜色的代码块。请参考此行
通过在自定义着色器的末尾包含 encodings_fragment 代码块,它将根据你在 THREE.WebGLRenderer 上使用的参数自动映射你的片元。
要理解为什么会这样,请查看编码代码块,其中只包含:
gl_FragColor = linearToOutputTexel( gl_FragColor );

然后您可以查看WebGLProgram.js文件,以了解linearToOutputText函数的工作原理。这个函数的工作方式基本上与纹素解码相同。

希望这对您有所帮助!


0

虽然我相信https://github.com/mrdoob/three.js/issues/1488回答了你的第一个问题,但是你的第二个问题仍未得到解答。

我发现

renderer.gammaOutput = true;

在使用自定义着色器材质时并没有起作用。你可以通过启用 gammaOutput 并将 gammaFactor 设置为极端值来测试此问题。内置材质会响应,但是自定义着色器不会。

因此,在这种情况下,您需要自己处理 gamma,要么通过修改输出颜色,要么在所有线性空间渲染完成后添加后处理步骤。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接