随着真实性更高的基于物理渲染(PBR)的到来,线性空间(Linear space)光照计算也越来越被经常提及。虽然线性空间和与之“对立”的伽马空间(gamma space)是简单而重要的概念,但很多开发者对它们的真正意义并不了解。这篇文档将会介绍伽马空间和线性空间、它们之间的区别以及在Unity引擎中的应用。 LINEAR SPACE线性空间是什么?简单的说,在线性空间对数字化的颜色和光照强度进行相加相乘计算得到的结果依然能与真实的结果一致。不具备这条性质就被称为“非线性”空间。见下图: GAMMA SPACE伽马(gamma)的产生原因主要有两点:第一是CRT显示器的历史原因,对显示图像的处理是非线性的。第二是因为人眼对明暗色域的辨识度不一样,有时需要对图像进行非线性处理来获得合适的辨识度,这些非线性处理叫做伽马纠正(gamma correction),具体实现是对图像中的每个像素做一次幂函数运算。伽马特指这个幂函数的指数值。见下图: 但为什么图像很够正确显示,而不是像左图一样看起来过爆呢?这是显示器显示的时候做了非线性处理导致的。CRT显示器显示图像的时候做了伽马值为2.2的纠正,之后的LCD显示器为了兼容性也做了同样的纠正。2.2为0.45的倒数,互相抵消得到了与原始一致的图像。如果图片没有做伽马纠正,显示的图像将是像右图一样,颜色被压黑。 COLOR SPACES AND THE RENDERING PIPELINE在实时渲染管线中,如果采用伽马空间,那么伽马纠正过的贴图在着色器(shader)中直接参与光照计算,得到的图像被显示器伽马纠正后输出显示。这个过程很简单,但物理上是不正确的。在真实世界中,光照行为是线性的,着色器中的数字化的光照计算也是线性的,而输入的贴图和颜色是非线性的,这意味说着色结果是不准确的。在越来越追求画面沉浸感和真实性的今天,伽马空间的光照计算满足不了需求。 因此,PBR使用了线性空间,贴图和颜色去除了伽马纠正转换到线性空间,再传递给着色器进行光照计算着色,之后的后期处理(post effects)也同样在线性空间下进行,最后获得的图像再做伽马值0.45纠正,以抵消显示器显示时2.2的伽马纠正。下图是渲染管线采用伽马空间和线性空间的流程和结果对比: COLOR SPACES IN UNITYUnity引擎渲染管线默认采用伽马空间,目前只有PC、 Xbox和PlayStation平台支持线性空间,可在编辑的此处进行切换: 如果同时设置了线性空间和HDR,那Unity所有的后期处理(post effects)全将在线性空间进行。如果只设置了线性空间,那Unity仍使用伽马帧缓冲(framebuffer),但当对帧缓冲进行读或写时,Unity会自动对颜色进行纠正来保证后期处理仍然在线性空间进行。 尽管Unity默认对移动平台不支持线性空间。但可以在着色器里来做类似实现:对传进来的贴图做幂为2.2的pow()函数处理,然后在颜色返回值前做幂为0.45的pow()函数处理。这种实现有计算开销,不能滥用。 CONCLUSION掌握伽马空间和线性空间的不同,这样在实际游戏项目中可以规避一些颜色管理上的常识性错误,从而保证画面质量。总之,线性空间的使用是获得画面沉浸感和真实性上的重要一环。 |
|