内容简介:这是侑虎科技第536篇文章,感谢作者Luisa供稿。欢迎转发分享,未经作者授权请勿转载。如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。(QQ群:793972859)作者主页:相信大部分了解图形学的人,都听说过Gamma校正或者Gamma空间,线性空间这些词。这里不对Gamma Space形成的历史原因做过多描述。Gamma和Linear空间的一些原理,文章也很多,包括
这是侑虎科技第536篇文章,感谢作者Luisa供稿。欢迎转发分享,未经作者授权请勿转载。如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。(QQ群:793972859)
作者主页: https://zhuanlan.zhihu.com/p/59683711 ,作者也是U Sparkle活动参与者,UWA欢迎更多开发朋友加入U Sparkle开发者计划,这个舞台有你更精彩!
相信大部分了解图形学的人,都听说过Gamma校正或者Gamma空间,线性空间这些词。这里不对Gamma Space形成的历史原因做过多描述。Gamma和Linear空间的一些原理,文章也很多,包括 Unity官网的描述 ,都可以看看。
显示器显示的Gamma空间的颜色变化规律,对应了下图中的黄色曲线。当美术在Gamma空间中,RGB(255,255,255)的颜色单位上,增加了1的颜色亮度,最后输出显示的亮度,其实是低于1的。这个差距,在特别暗的地方更加明显,也就容易让场景因为太暗,而看不清细节。我们公司的美术也表示,线性空间的效果其实更加直观,而Gamma空间的颜色有可能会越叠越深。所以为了更好的美术效果,尤其是让贴图的阴暗处有更多的细节,将Gamma Space转换为Linear Space还是相当有必要的。
基本思路,一般来说就是通过pow(1/Gamma)将颜色强度提高。下图中的蓝色曲线是pow(1/2.2)的近似数,pow(0.45),这样就可以抵消掉黄色曲线的变化,使颜色变化可以趋于线性。
三种函数的曲线
Infinite 3D Head Scan by Lee Perry-Smith, licensed under a Creative Commons Attribution 3.0 Unported License (available from www.ir-ltd.net)
虽然Unity 5.5开始,已经提供 转换工程为线性空间 的功能,但是仅对OpenGLES 3.0及以上的设备进行支持。详细数据可以参考这篇 Unity的Blog ,可以看到,还有两成左右的设备是不具备这个条件的。所以如果项目组需要考虑低端机,尤其是考虑海外发行的话,就不能直接改变整个渲染空间。
因此替代的方法,是手动在Shader中,修改Colour Space。转换空间用到的相关函数,Unity其实已经在Unity CG.cgnic中提供了,可以直接使用。
函数如下:
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); }
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)); 8}
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); }
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)) }
其中主要用到的是GammaToLinearSpace() 和LinearToGammaSpace() 。下面将说一下,到底怎么用这两个函数。
主要的思路是,把从贴图中读取进来的颜色,同时也是Gamma Space下的颜色,进行一次转换,转换到Linear Space。之后对这些颜色数据进行原本要进行的处理。处理结束后,在输出的时候,进行一次逆转换,将这些颜色数据,从Linear Space转换回Gamma Space。
以下是我实际使用的一段代码:
half4 color = UNITY_SAMPLE_TEX2D(_MainTex, i.uv); color.rgb = GammaToLinearSpace(color.rgb); // 转换到Linear Space bakeGI += DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap, i.ambientOrLightmapUV.xy)).rgb; // 不要忽略预烘焙的Light Map // 中间省略一些计算过程 colLit += color.rgb * bakeGI; color.rgb = colLit; color.rgb = LinearToGammaSpace(color.rgb * unity_ColorSpaceDouble); //转回Gamma Space return color;
补充一点,由于通道图,一般来说,其实已经是线性的了,所以是不需要参与到这个转换中的,直接用就好。但这段代码里特别注意的一点是,最后转换回Gamma Space的时候,我在Color上乘了一个Unity_ColorSpaceDouble。
最开始,我只进行了一个转换回Gamma Space的方法,然后发现,场景不仅没有变亮,反而变得更暗了。随后查阅到 一篇文章 提到了,需要在最后转回Gamma Space的时候,乘上一个值。
“与此相关的有,一个Unity提供的与色彩空间相关的值,Unity_ColorSpaceDouble。这个值在Gamma Color Space时为2,在Linear Color Space时为4.594(2的2.2次方)。对于这个值可以这样来理解。一般在Gamma Color Space中将两个Color值相乘后,为了避免颜色变得很暗,会在后面乘以2。”
也就是说,为了避免颜色变暗,应该扩大两倍,但同时因为是在线性空间下,所以这个2要变成Unity_ColorSpaceDouble。
最后来看一下效果吧~
上图为Gamma Space时的效果,下图为做完一系列变换后的结果。可以看到,整体颜色变亮,尤其是暗部的亮度和细节都有明显的提升。
可以看到特别暗的地方,在进行Gamma校正之后的变化也相对较大。所以这里也需要注意一点,如果是项目已经进行了一段时期之后,想要进行Gamma校正,一定要同时修改光照等一系列参数,以避免一些地方的光照效果过曝。
文末,再次感谢Luisa的分享,如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。
QQ群:793972859
也欢迎大家来积极参与U Sparkle开发者计划,简称“US”,代表你和我,代表UWA和开发者在一起!
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- OpenCV实现基于傅里叶变换的旋转文本校正
- CVPR2020 | SCNet:自校正卷积网络,无复杂度增加换来性能提升
- ECCV 2018 | 旷视科技提出GridFace:通过学习局部单应变换实现人脸校正
- LLVM每日谈之五十四 新建后端的第二步校正(register set)
- LLVM每日谈之五十二 创建LLVM后端的第一步校正(target machine)
- *Matlab—线性回归方程式与线性系统
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
深入浅出Ext JS
何启伟、徐会生、康爱媛 / 人民邮电出版社 / 2010-5 / 69.00元
以用户为中心的时代,应用的界面外观变得越来越重要。然而,很多程序员都缺乏美术功底,要开发出界面美观的应用实属不易。Ext JS的出现,为广大程序员解决了这一难题。它有丰富多彩的界面和强大的功能,是开发具有炫丽外观的RIA应用的最佳选择。 本书是《深入浅出Ext JS》的升级版,涵盖了最新发布的Ext JS 3.2新特性,并对上一版的内容进行增补,充实了示例代码,同时补充了两个功能强大的实例。......一起来看看 《深入浅出Ext JS》 这本书的介绍吧!