六、扩充 gamma校正流程

文章详细阐述了计算机图像处理中的gamma校正过程,解释了由于人眼视觉非线性,需要将8位每通道的图像从物理灰阶转换到美术灰阶以避免色阶断层。介绍了正确的工作流程,包括De-Gamma、线性处理和最终的gamma校正,以及在Unity中的应用实例。

gamma校正流程

计算机为什么要做gamma校正:

  1. 人的视觉对光强度的感知是非线性的
  2. 数字图像所能采集和回放的灰阶层次有限的,需要省着点用(节约带宽)

物理光强相对值

上面一条,实际的物理光强50%位置其实再后面一点的位置。

物理光强相对值21.8。

物理灰阶与美术(视觉)灰阶相对关系

灰阶有限需要省着用的解释

8位每通道一共记录256个数据。

如果均匀分布美术灰阶则如下图所示:

如果均等分布物理灰阶则如下图所示

上图可见,物理中灰过于偏向亮部(绿线),亮部区域过于集中,导致暗部区域样本数缺少。

如果按照物理中灰进行采样,下图中可见红线与

现象

上图可知,如果对8位每通道采用物理灰度进行采样即线性记录物理光强数据,“美术暗部”只会有56个样本,就会导致一个现象——色阶断层。

如果按照非线性记录物理光强数据,则会得到一个人眼看起来较为平滑的画面。

流程图:

渲染器32位每通道(物理数据)-> gamma≈2.2校正到8位每通道(美术数据)->gamma = 1校正8位每通道

引擎渲图问题(灯光过曝、室内过暗等)

原因:

开始如数的数据是“美术数据”输入的gamma≈2.2 ,经过一屏幕的压暗处理后贴图是正常了,但是光线变得很暗,导致画面整体偏暗,然后引擎内部再将整体画面提亮后,光线虽然正常了,但是贴图会变的很亮导致画面渲染错误。

错误的工作流程:

正确的工作流程:

    • 首先渲染器对输入的贴图使用下压的gamma曲线将贴图的数值还原会gamma=1的数值——De-Gamma操作。
    • 然后对线性的贴图数据,线性的光照数据进行操作,得到线性结果
    • 通过屏幕输出后,屏幕会将图片压暗
    • 通过引擎内置按钮,再将图片进行一遍gamma校正,得到最终正确的图像

对比图:

PS操作中的误区

颜色混合

8位每通道与32位每通道(生活中的样子)颜色混合对比图

图片缩放

缩放前

缩放后

  • 在8位每通道环境下进行测试

  • 缩放后看到的是在“美术色阶”(gamma约等于2.2)的图像,美术中灰0.5,则实际物理中灰是0.2
  • 本来我们想要的是一个物理中灰,但是PS算出一个物理中灰

高斯模糊

32位每通道下进行高斯模糊

8位每通道下进行高斯模糊

PS中的线性工作流程

  • 现在32位每通道中进行色彩运算,然后切换到8位每通道,再进行保存导出即可。
  • 图像->模式->32/每通道 ——> 图像->模式->8/每通道

作业

直接修改Unity里的色彩空间选项

Gamma空间下效果:

Linner空间下效果:

代码转换:

①调用Unity内部方法GammaToLinearSpace、LinearSpaceToGammaSpace。

转换前:

转换后:

UnityCG.cginc内部源码

inline float GammaToLinearSpaceExact (float value)
{
    if (value <= 0.04045F)
        return value / 12.92F;
    else if (value < 1.0F)
        return pow((value + 0.055F)/1.055F, 2.4F);
    else
        return pow(value, 2.2F);//看灰色的return,调用的GammaToLinearSpaceExact ,rgb大于1时,pow 2.2曲线下压变暗
}

inline half3 GammaToLinearSpace (half3 sRGB)
{
  
    return sRGB * (sRGB * (sRGB * 0.305306011h + 0.682171111h) + 0.012522878h);

    // Precise version, useful for debugging.
    //return half3(GammaToLinearSpaceExact(sRGB.r), GammaToLinearSpaceExact(sRGB.g), GammaToLinearSpaceExact(sRGB.b));
}

inline float LinearToGammaSpaceExact (float value)
{
    if (value <= 0.0F)
        return 0.0F;
    else if (value <= 0.0031308F)
        return 12.92F * value;
    else if (value < 1.0F)
        return 1.055F * pow(value, 0.4166667F) - 0.055F;
    else
        return pow(value, 0.45454545F); //pow 1/2.2,曲线上突变亮
}

inline half3 LinearToGammaSpace (half3 linRGB)
{
    linRGB = max(linRGB, half3(0.h, 0.h, 0.h));
    return max(1.055h * pow(linRGB, 0.416666667h) - 0.055h, 0.h);

    // Exact version, useful for debugging.
    //return half3(LinearToGammaSpaceExact(linRGB.r), LinearToGammaSpaceExact(linRGB.g), LinearToGammaSpaceExact(linRGB.b));
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值