Unity Gamma空间和Linear空间转换代码

Cg版本

引自: UnityCG.cginc

//--Gamma到Linear转换
inline half3 GammaToLinearSpace (half3 sRGB)
{
    // Approximate version from http://chilliant.blogspot.com.au/2012/08/srgb-approximations-for-hlsl.html?m=1
    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 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);
}
//--Linear到Gamma的转换
inline half3 LinearToGammaSpace (half3 linRGB)
{
    linRGB = max(linRGB, half3(0.h, 0.h, 0.h));
    // An almost-perfect approximation from http://chilliant.blogspot.com.au/2012/08/srgb-approximations-for-hlsl.html?m=1
    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));
}

--精确转换
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);
}

个人理解

Gamma空间

什么是Gamma空间?为什么有Gamma空间?自古江湖上就有定论,刚开始我也是云里雾里,总觉得他们说的有问题。我们先看结果
在这里插入图片描述
OK~~没错,上图就是Unity的处理流程。没说的,需要注意的就是如果是线性空间,有的项目贴图的某个通道可能会作为数据图,注意如果是RGB通道的话,数据获取是有错误的,我们可以选择使用取消掉贴图导入是的SRGB选项。或者对数据再次进行Gamma1/2.2的矫正。

当初的疑惑

之前一直就有疑问,先做Gamma1/2.2的贴图压缩,显示器在做Gamma2.2的矫正,这不就是原始数据么?如下曲线图所示,假设一个0.5的数据贴图压缩成0.72974,显示器矫正后成0.5,这不是多此一举么?直接0.5他不香么?
在这里插入图片描述
带着疑问去寻找解决问题的答案:
1.图像编码gamma的目的是为了解决低容宽时,图像保存的信息过少的问题。
问:怎么解决呢?
答:人眼对暗色比较敏感,对亮色不敏感。比如白天亮个灯没啥感觉(相对于不亮来说亮度是有增加的),晚上一个萤火虫都存在感比较强。
问:然后呢?
答:根据人眼的规律,我们可以在有限的存储空间中,记录更多的暗的数据,去掉一些亮的数据,这样操作来尽量保持和原来的效果看上去是相似的, 上面的贴图压缩曲线就是把本来暗的区域提亮了。
问:能看出来啊~提亮后,显示器显示时不就又把提升的数据,变回去了么?有啥用?
答:WTF!原来你的点在这。假设我们显得贴图只能存储0,0.2,0.4,0.6,0.8,1这三种数据,毕竟贴图的存储数据是有限的:

实际数据00.10.20.30.40.50.60.70.80.91
贴图编码后00.350.480.580.660.730.790.850.900.951
存储数据00.40.40.60.60.80.80.8111
显示器显示00.130.130.320.320.610.610.61111

上面可以看出,真实数据通过贴图的这个中间者传递信息给显示器,而贴图本身能力有限,能存的数据就那么几种,所以他需要存储的时候多存一些暗部的信息,丢弃一些亮部的信息,以保证是个人(注意必须是个人,猫啊狗的就不一样了)看上去感觉还比较逼真。
2.显示器无法线性显示。一般CRT显示器的亮度响应曲线,可以看到其输入电压提高一倍,亮度输出并不是提高一倍,是非线性的。比如红色的亮度为50%,如果一个未经过Gamma矫正的CRT显示器的Gamma值是2.2,那么输出结果的亮度将分别为22%.
问:以前的CRT显示器,由于自身原因才出现的这种情况?还是人们故意做的。
答:确实是硬件的问题。
问:显示的这个变化和上面人类的视觉刺激是巧合还是?
答:Z,这谁知道。。

线性空间

线性空间还比较简单,主要就是为啥Es3.0才支持线性空间,其实还是硬件问题,线性空间下unity会自动开启framebuffer_sRGB。其实主要的还是处理Gamma到Linear的转换问题。

结束语

终于最近又迎来的有时间写东西的时候了~疫情期间,希望大家注意防护!

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Unity中的Gamma空间模型是一种颜色空间模型,用于描述计算机图形中的颜色显示和计算方式。在Gamma空间模型中,计算机图形使用的颜色值会根据人类视觉系统的特性进行调整,以更好地适应人类的视觉感知。 在Gamma空间模型中,颜色值会经过一个Gamma校正的过程。这是因为人类眼睛在感知亮度时对不同光强的变化有不同的感知能力。Gamma校正可以调整颜色值中的亮度信息,使得较暗的颜色更容易被人眼感知,而较亮的颜色则会被衰减,以便在显示设备上更好地还原真实场景中的亮度级别。 在Unity中,Gamma空间模型是默认的颜色空间模型。它的工作原理是将颜色从sRGB空间(标准的RGB颜色空间转换到线性空间,并在渲染完毕后再将颜色转回到sRGB空间,以便正确显示。 Gamma空间模型在图形渲染中起到重要作用。由于人眼对亮度的感知非线性,使用Gamma空间模型可以使渲染的图像更加逼真和准确。而在一些特殊的情况下,使用线性空间模型可能会导致图像亮度不平衡或者颜色失真的问题。 总结起来,Unity中的Gamma空间模型是一种能够根据人类视觉系统特性进行颜色调整的模型,能够使渲染图像更加真实和准确。通过使用Gamma校正,它可以调整颜色的亮度信息,以适应人眼对亮度的感知能力。而相对于线性空间模型,在大部分情况下,Gamma空间模型能够提供更好的图像表现效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刘培玉--大王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值