GREE正确处理sRGB纹理在THREE.js

时间:2017-05-11 02:55:39

标签: three.js

我无法正确处理sRGB纹理的三个.js。我该怎么办?

这是sRGB测试图像,应该统一显示为50%灰色:

An sRGB test image that should appear completely 50% gray.

它主要由棋盘图案中交替的黑白像素组成。黑=(0,0,0)白=(255,255,255) 这应该导致平均线性强度为50%。 中间有三个50%强度灰色的色块,用sRGB编码为(188,188,188)(下面解释)。

  

解释:(见sRGB的维基百科文章   这表示标准化的50%强度应该得到sRGB值(1.055 * 0.5 ^(1 / 2.4)) - 0.055 =   0.735358,在8位sRGB中约为187.516,因此将其编码为188的逻辑。

视觉上,在任何经过​​适当校准的显示器上本机查看时,纹理显然是正确的,并且除非您的浏览器缩小了图像,否则在此帖子中看起来可能正常。 (浏览器也会因伽马校正的下采样而失败,因此如果您已经可以轻松查看三个条形图,请以原始分辨率查看图像。)

当缩小此图像时,大多数天真的软件将简单地平均sRGB编码并达到太暗的虚假强度。黑色和白色像素将被天真地平均为(0 + 255)/ 2,以获得(128,128,128)的颜色,其强度仅为约22%(((128/255)+0.055)/(1.055)^ 2.4 )= ~0.215861。这比50%的期望强度(相当贡献的平均强度为0%和100%)暗得多。直观地说,"半亮度"是50%。

在OpenGL中,这很容易。您只需将纹理视为sRGB并使用sRGB帧缓冲区。纹理样本在采样时从sRGB编码转换为线性,并且在写入帧缓冲区时线性值被编码为sRGB,并且一切都很好。

我完全失去了如何在three.js框架内实现这一目标。有人可以帮忙吗?

我试过设置......

renderer.gammaFactor = 2.2;
renderer.gammaInput = true;
renderer.gammaOutput = true;`

...但实际上看来mipmap生成并没有将纹理正确地视为sRGB。加载纹理时我没有做任何特别的事情 - 只使用了THREE.TextureLoader。

var texture = textureLoader.load( 'images/gamma_srgb.png' );

但是这里质量差的结果是图像的棋盘部分太暗,但图像的纯色区域要亮得多。 Example output with bad gamma treatment

仅供参考,我确实使用{antialias: true}创建了WebGLRenderer,并且我在纹理上将maxAnisotropy设置为渲染器的最大各向异性值。

编辑:在jsfiddle中添加了一个repro。 https://jsfiddle.net/fvusxp1g/

0 个答案:

没有答案