关闭

Technical Artist 的不归路 —— 线性空间光照

标签: CGHLSLTA
1374人阅读 评论(2) 收藏 举报
分类:

这篇博客简单介绍了线性空间光照的内容。


线性空间的介绍

先来看一张图:

Image1

上图中左右两边的黑色与白色颜色值分别为0与255.

现在,读者可以尝试远离屏幕,直到左右两边的线条浑然一体 —— 由于左右的线条都是等高的,因此可以猜测其颜色值为127.5。此时应该会发现左右两边的颜色与中间下方色块的颜色是一样的,而上方偏暗。

但是实际上中间下方的色块的颜色值为187,上方的颜色值才是128.因此可以推断在屏幕上的颜色值与亮度并不是线性关系的。在顽皮狗工作室有对应的分享博客专门提到这一块的内容,传送门

Image2

Gamma空间

很多人认为在显示器中,值为50的颜色刚好是值为25的颜色亮度的两倍。这实际上是错误的 —— 大多数的显示器都会进行Gamma校正,这个校正在大多数显示器或者游戏引擎中都是以pow(x, 2.2)的形式存在。因此在显示器上所显示出来的效果就是Gamma空间,换句话说,大多数的美术人员都是工作在Gamma空间下的。

当然有时根据不同的显示器Gamma曲线可能也有不同,例如Mac的显示器的Gamma曲线为1.8.

另外,在游戏中常用的sRGB也与Gamma曲线相接近。

因此很多时候可以通过Gamma校正来对图像进行一些操作。例如当图像太亮,则可以使用使用pow(x, 2.2)的修正来让它变得正常一些。

Image3

因此可以推断出来,由于显示器将图片调亮了,那么存储在硬盘中的图像比起显示器中的图像要暗一些。这样就解释了没有经验的打印店老板所打印的美术作品有时会偏暗的原因。

同样的,正因为这个原因,大多数的商业照相机都内置了Gamma校正 —— 通过将图像存储在Gamma空间中,当传感器接收到光照的时候,摄像机会使用pow(x, 1/2.2)再进行量化。因此储存的图像要比真实场景更亮一些,只是在显示在显示器的时候,这个差值会被修正。

Image4

线性空间光照

如下图:

Image5

在某些方面来说,左边的光影渲染是错误的,首先,在亮处的地方颜色的衰减比较快,在暗处的地方颜色的衰减比较慢,整体上看起来非常柔和。另一方面,色彩的偏移非常明显,尤其在Specular高光那里尤其明显。看起来有点像是从白色便宜到黄色然后再到绿色最后再回到黄色。比较右边的图像来说,能够很清楚的看出来是一个漫反射的表面加上一个镜面高光,这更像一个所谓的光照模型。

但是,就像PPT里面说的,这里讨论的是“正确”,而不是追求最好的效果。真实不一定意味着好的效果,好的效果也不一定就是真实存在的。

为何会出现这个效果?首先,我们从硬盘上读取纹理,但是这个纹理是储存于gamma-space的,也就是说比你真实看起来更加亮和更加柔和一些。所以,我们读入了一个过亮的纹理,然后进行了光照处理。

Image6

对应的HLSL代码如下:

float specular = ...; 
float3 color = tex2D ( sampler , uv .xy );
float diffuse = saturate (dot ( N, L ));
float3 finalColor = color * diffuse + specular ;
return finalColor ;

因此,需要将其转化到线性空间进行处理,代码如下:

float specular = ...; 
float3 color = pow ( tex2D( sampler , uv . xy), 2.2f );
float diffuse = saturate (dot ( N, L ));
float3 finalColor = pow ( color * diffuse + specular , 1.f / 2.2f);
return finalColor ;

从代码里很容易看出来,在对于纹理进行采样的时候,我们先进行了一个gamma变换,将其转换到线性空间里面,然后再进行光照运算。在我们获得了我们想要的图像后,我们使用pow(color, 1.f/2.2f)将其变换回gamma空间中,当显示器显示这个颜色时,会将其修正回来。

对于可编程管线来说,pow并不便宜。但是在硬件层对于纹理进行采样的时候,我们可以进行硬件层的优化。如果是DX系列,那么使用D3DSAMP_SRGBTEXTURE来进行采样,然后再render-to-target的时候,使用D3DRS_SRGBWRITEENABLE。
这样一来就可以直接使用先前的代码了。

Image7

反思

在游戏的制作流程中,通常也都有涉及到贴图的操作。但正如之前所讲:大部分的美术人员都工作在Gamma空间下,因此在进行光照计算时都需要时刻注意将其转化到线性空间中。例如虚幻Ⅳ引擎就在贴图的处理中加入了sRGB的选项:

Image8

但是值得一提的是,线性空间的转化通常是与颜色相关,针对于那些颜色无关的贴图(例如法线贴图、Substance Painter导出的Metallic&Roughness贴图等)由于这些数值具有功能性,因此不能随意修正。

<全文完>

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:85889次
    • 积分:1510
    • 等级:
    • 排名:千里之外
    • 原创:60篇
    • 转载:0篇
    • 译文:4篇
    • 评论:58条
    最新评论