Unity Color Space

这一周都在看Unity的Color Space相关的内容,看明白了,写下来给自己和他们参考,有不对的地方欢迎指正.

  显示器所能显示的颜色很有限,于是业界出了sRGB颜色空间,Photo Shop默认的颜色空间就是这个.照相机不用这个,用别的,这里不多说了.

  早期的显示器,电压和颜色变化不是线性关系,是幂函数关系:G(x)^Gamma,Gamma取2.2.于是要想正确在显示器上显示颜色,就该对图本身进行一次校正:G(x)^(1/Gamma),这样最终图像在屏幕上显示就是正确的.

  用Photo Shop做出的图保存之后,是经过了G(x)^(1/Gamma)校正了的,以便显示在显示器上时正确.接着说Unity的Color Space中的Gamma Space和Linear Space.

  在Shader中计算颜色是在线性空间进行的.

  Gamma Space:加载贴图(此时贴图是校正了的),采样,计算,再写到缓冲区,显示在屏幕上.直接显示图没有问题,因为两次运算结果是一个线性变换,能反应出原图.但是如果在原图基础上进行了颜色计算,就会:Final = G(x)^(1/Gamma)(原图) * S(x)(线性颜色计算) * G(x)^Gamma(显示器显示颜色) ,颜色如果S(x)变化了,但Final不是线性变化的,带来了颜色显示不准确.

此外,Alpha混合操作是线性操作,对写入到颜色缓冲区的Final进行线性变换会使得混合颜色不准确.看起来其实说得过去,但那其实并不是我们想要的.

  Linear Spcace:会创建支持sRGB的缓冲区,替换普通的缓冲区.这里我给的解释不明确.同时贴图加载进去之后,保证采样的时候,贴图校正回了原来的线性变换,也就是对贴图进行了一次G(x)^Gamma,这样接下来的Shader执行的输入是线性变化的贴图,计算后结果是正确的.写入到支持sRGB的缓冲区时,硬件会自动对颜色进行G(x)^(1/Gamma),这样显示在显示器上时结果就是正确的了.同时,在此种缓冲区进行Alpha混合时,先将缓冲区的颜色G(x)^Gamma,变换回线性变化,再进行混合,而后再对得到的结果G(x)^(1/Gamma)到缓冲区,这样保证Alpha混合时结果也是正确的.此外,如果应用了HDR,创建了浮点缓冲区,写入和读取浮点缓冲区时都没做特殊处理,里面的内容都是线性变化的,在将浮点缓冲区写入带sRGB的缓冲区时再一次性进行G(x)^(1/Gamma).

  以上内容多数是Unity官方文档中的(搜:Unity Linear Space就有).但是想整明白还不是看几遍就能明白的,这个问题也困扰了我大半年,这个礼拜才决心整明白.为了一鼓作气写完这个,延迟了吃饭的时间,上次这样,还要追溯到大概2年前了.

  补充一下,贴图的Bypass sRGB sampling的意思是绕过G(x)^Gamma.值得注意的是,这个选项只有在设定为Linear Space后才起作用,因为Gamma Space本来就是不进行G(x)^Gamma这步处理的.适用于用来look up的贴图,当然还有法线贴图.把法线贴图的Import Type改为Texture后会发现选中了Bypass sRGB sampling.至于为什么UI也要选中Bypass sRGB sampling,我还不清楚.

猜你喜欢

转载自blog.csdn.net/gaojinjingg/article/details/80756142
今日推荐