文章目录
- 也可以简单参考 SIGGRAPH 2010 的 PBS 的 Gamma-Correct
- Unity 中的 gamma、linear 工作流
- Unity BRP 管线中的 shaderlab 提供的 gamma2linear, linear2gamma
- Unity中线性空间配置
- DCC 中的 gamma 值是怎么计算的?
- Photoshop 的线性工作流
- 方式1
- 方式2
- 验证 Photoshop 中是否在线性工作流
- PS与 Unity 下的 Linear Workflow 实践案例
- AE 中的 Linear 工作流
- C4D 中的 Octane 渲染器 的 Linear 工作流
- 3Ds Max VRay 中的线性工作流
- 流程图
- Docs
- URP下的 UI alpha blend 的 gamma to linear
- BRP下的 UI alpha blend 的 gamma to linear
- References
我们一般说的 gamma correction 简称 gamma,而 gamme correction 就是对 pow(inputVal, 2.2)
也就是压暗颜色的处理,而 gamme correction 的逆运算可以简称:degamma,就是 pow(inputVal, 1.0/2.2)
也就是提亮的处理
好,这里总结一下:
- gammaCorrect - gamma 校正 -
pow(inputVal, 1.0/2.2)
- 提亮颜色 - degamma - gamma 反向校正 -
pow(inputVal, 2.2)
- 压暗颜色
(注意,DCC软件中的 gamma 值的设置,一般都是这么使用,比如 3Ds max 中的 gamma 值:outputVal=gammaCorrect(inputVal, gamma)
⇒ outputVal=pow(inputVal, 1.0/gamma)
,下文有提到)
OK,到这里,我们都不知道为何要有这两个东西
因为经过前人验证过
如果现实世界中,我们看到的线性的颜色亮度,人眼看起来感觉不是线性的
如下图,看图感受:
- 问题1:你觉得左边是线性值,还是右边是线性值?
- 问题2:你觉得左边的还是右边的图中的黑和白的颜色过渡比较均匀?
那么下面回答:
- 问题1 回答:左边是:非线性,右边才是:线性的值(这是前人使用过专业的光子平均面积亮度测量仪测出来的结果)
- 问题2 回答:正常人都会觉得,左边的比较均匀,感觉中间就是刚刚好的黑与白中间的中灰
下面是左边的图的 中灰 位置
下面是右边的图的 中灰 位置
上图再次总结:
- 人眼看到的亮度线性信息,大脑感知的是非线性的
- 这个非线性呈:上拱曲线型,大概是:
pow(inputVal, 1.0/2.2)
的曲线 - 从上图的右图可得知,人眼看到的是暗部偏少(也就是说,暗部的值很快就往更亮的值靠近,所以才呈现:上拱形状)
使用 GGB 可以看到 pow(InputVal, 1.0/2.2)
是怎么个拱法:
为什么变亮了,如:线性值为 0.5,但是被上拱过之后,就变成了在 0.73 左右
所以原本 0.5 变成了 0.73 那肯定就更亮了
倒回这两个黑白颜色过渡图
如果我们想要将:右边的线性值,在人眼看到后在大脑呈现上拱(被提亮)过的信号,能像 左边那样看着比较舒服的信号
那么我们就需要之前开头说的:这里相对 hunmanEyeSeeLinear之后的数据,做 类似 gamma 校正 pow(inputVal, 2.2)
- 压暗颜色 来处理 上拱过的数据
注意,所谓的 gamma 校正,没有确定一定是,上拱 的,或是 下压的曲线,都是相对不同情况时的校正方式不同而已,比如,你发光设备发射出来的 linear 的数值,但是人眼看到太亮了,那么这里的 gamma 校正就是 pow(inputVal, 2.2)
;
另一种情况是:如果 CRT 显示二极管的电极强与发光亮不是线性的,那么这里的 gamma 校正就是 pow(inputVal, 1.0/2.2)
的提亮校正
还是使用 GGB 来查看效果
将:humanEyeSeeLinear 改为:gammeCorrect 后,会更好理解 各个 DCC 软件得应用情况:outputVal=pow(inputVal, 1.0/gamma)
下面是相对各种 DCC 软件中的操作,基本上只会提供一个:gamma
给你设置,公式就是上面的:outputVal=pow(inputVal, 1.0/gamma)
的应用
可以看到 humanEyeSeeLinear
(没错就是 Cnglish,一般可以写为:linearAfterEyeSee
会更好一些)是人眼看到的线性感知后的上拱型,而我们需要的 gamma
是下压型来将 被拱 过的 压回 线性的
那么压回线性的结果就是对应: linear(x)=gammaCorrect(humanEyeSeeLinear(x))
下面引用一张图来说明(此图中的显示器都是 CRT为例)
(DCC 中编辑好得照片,在 CRT 显示器 中,感觉被 gamma=0.45454545; output=pow(input, 1.0/gamma)
,导致亮度被压暗了
然后通过软件 gammeCorrect,也就是 gamma=2.2; output=pow(input, 1.0/gamma);
,所以图片在 CRT 上看着正常了
然后通过 internet ,等传送方式到各个CRT设备上的显示时,这些图片都是经过:gamma=2.2; output=pow(input, 1.0/gamma);
处理过的(提亮了),所以在 CRT 上 gamma=0.45454545; output=pow(input, 1.0/gamma)
的特性抵消好,刚好就是 linear 的结果)
从图中也可得知:
- 先是 Linear 数据被 显示器 下压过
- 再到 上拱软件 提亮
- 然后保存 上拱过的数据(纹理,图片)
- 然后在互联网上传播的都是 被上拱过的 拘束
- 然后将 被 上拱过的数据 通过 显示器 下压 数据后再显示,这时又变回 Linear 数据
因为我们人眼在看到真实世界中的亮度值时,在眼球编码生物神经电信号给大脑中的灰度感知并非线性的(人眼会将 pow(inputVal, 1.0/2.2)
处理,会将原来的线性颜色表现出来的亮度整体偏亮,这种视觉效果感觉很差(暗部偏低,亮度又过亮)
所以我们为了提高视觉效果更好,才会在颜色输出给人眼看到之前,先将其压暗颜色,也就是A=pow(inputVal, 2.2)
,这样将压暗过的结果,再给到人眼时呈现的是 pow(A, 1.0/2.2)
颜色亮度,但是刚刚说过,给人眼看前压低了亮度,人眼编码在大脑提亮了亮度,这一降一升,刚刚好变成线性的,所以这时在人脑中的灰度信号是线性的,那么视觉上自然就会舒服很多,但是实际上真正的物理亮度是被压暗过的
如果有些设备,如:CRT,也是会降低亮度的输出,这样,CRT 降低1次,人眼再提亮1次,刚刚好看起来就像是在 线性变化的感觉(注意这时人眼看到的输出结果都是被压暗过的,不压暗就会过曝,人眼对灰度的感知编码不是线性的)
也可以简单参考 SIGGRAPH 2010 的 PBS 的 Gamma-Correct
s2010_physically_based_shading_hoffman_b.pdf
下面是原理,和需要处理的部分:
In Theory, Just Need To:
• Convert shader inputs to linear before shading
• Convert shader output to gamma at end
• “Free” (pre-convert constants & vertex colors,
HW converts from textures / to frame buffer)
• In practice this works if you never do shading
operations in the frame buffer
下面是一些引起的其他问题,多是一些早期的硬件没考虑 颜色空间的问题导致硬件程序的处理不当导致的:
Complications
• Some HW does gamma blending incorrectly
– Bad for multipass / deferred shading, transparencies
• Some HW filters gamma textures incorrectly
– But you can at least generate MIP maps the right way
• Actual nonlinear space supported by HW varies
– Especially bad for consoles
下面是导致需要在工作流中做对应调整的部分:
Unintended Consequences
• Changes light distance falloff, Lambert falloff,
soft shadow edges, vertex interpolation, etc.
– May require artist adjustment / retraining
– In some cases (like vertex interpolation) it might make
sense to fix in the shader
Unity 中的 gamma、linear 工作流
unity 文档中的 gamma space(伽马空间) 都是 下压过亮度 之后的颜色空间
比如:“A纹理是在 Photoshop Gamma 空间下生产的”
意思说:在 Photoshop 中默认(默认的颜色空间配置)对 A 纹理制作生产过程中,都是基于 下压过亮度(pow(inputVal, 2.2)
) 的颜色设置方式导出的资源
参考 :
- linear or gamma workflow
- Color space
unity 纹理 sRGB 勾选项的作用:
参考:TextureImporter.sRGBTexture
- gamma 空间上
勾不勾 都无所谓,都当作 没有勾选 纹理格式一样是使用:GL_COMPRESSED_RGB8_ETC2,就是 硬件不会有 gammaCorrect 解码处理 - linear 空间上
- 勾上,那么unity 会 gammaCorrect 解码 此纹理,也就说会 硬件将此纹理压暗;纹理格式为:GL_COMPRESSED_SRGB8_ETC2
- 不勾,就是说,硬件把你的纹理直接当做 linear 数据 不做 gammaCorrect(不压暗亮度) ,直接给到 shader 着色计算,纹理格式为:GL_COMPRESSED_RGB8_ETC2
简单总结为:
- linear space 下
- 纹理的 sRGB 勾上,说明此需要保留压暗处理,请 unity 帮我保持 gammaCorrect 编码
- 纹理的 sRGB 没勾,说明此 不需要 gammaCorrect 编码
所以你现在应该知道 unity sRGB 的作用了
颜色空间 除了会 影响纹理的 sRGB 的格式外,还会影响 FrameBuffer(下面简称 FB)的格式
下面以 OpenGL Graphics API 在 RenderDoc 中抓帧分析的情况,使用一张表格来表示
Tabel Edit | Platform | Color Space | sRGB Checked | HDR | TextureDefaultFormat | FrameBufferFormat | Comments |
---|---|---|---|---|---|---|---|
jave.lin | OpenGL | Gamma | False | False | GL_COMPRESSED_RGB8_ETC2 | GL_RGBA8 | 初始化… |
jave.lin | OpenGL | Gamma | True | False | GL_COMPRESSED_RGB8_ETC2 | GL_RGBA8 | 在 Gamma 空间下,将 sRGB=True,发现 Texture, FB 的格式都没有变化 |
jave.lin | OpenGL | Gamma | True | True | GL_COMPRESSED_RGB8_ETC2 | GL_R11F_G11F_B10F | 将 HDR=True,发现 FB 格式 RGBA8 变成了 R11FB11FG10F,A通道精度完全丢失,都放到RGB通道来来做High Range |
jave.lin | OpenGL | Linear | True | True | GL_COMPRESSED_SRGB8_ETC2 | GL_SRGB8_ALPHA8 | Color Space调整为Linear后 Texture 和 FB 的格式都有变化 |
jave.lin | OpenGL | Linear | False | True | GL_COMPRESSED_RGB8_ETC2 | GL_SRGB8_ALPHA8 | sRGB=False,Texture格式变为:GL_COMPRESSED_RGB8_ETC2 |
jave.lin | OpenGL | Linear | False | False | GL_COMPRESSED_RGB8_ETC2 | GL_R11F_G11F_B10F | 将 HDR=False,发现 FB 格式 RGBA8 变成了 R11FB11FG10F,A通道精度完全丢失,都放到RGB通道来来做High Range |
那么继续往下看
在 Unity 中,颜色空间的有:
- Edit/Project Settings…/Player/Other Settings/Color Space: Gamma 或是 Linear
- 每个纹理资源只要是颜色类型的纹理(不是 AO, Normal, Height 贴图),那么 sRGB 的勾选需要在对应的 Color Space 下选择是否勾选:
- 在 Color Space 为 Gamma 时,勾上(Unity 默认情况下时会勾上的),且够不够选都无所谓,因为在 Color Space 为 Gamma 时,unity 会当这个 纹理是在 sRGB 勾选的
- 在 Color Space 为 Linear 时
- 如果我们美术输出的纹理颜色资源都是在被 下压过的数据(压暗过的),或者说是在 Gamma 空间下生产的资源,那么就要够上 sRGB,让 unity 先 gammaCorrect 后再给到 shader 进行光照计算
- 如果我们美术输出的纹理颜色资源都是 线性的数据(没有提亮,也没压暗),那么就不要勾选 sRGB,就是啥都不处理
(但是由于现在很多 DCC 软件输出的颜色纹理默认都是 被下压过的数据(被压暗过的),所以一般我们在 Linear 下的纹理默认都会勾上 sRGB)
unity 想要保留 gamma 的处理,因为Linear 空间是有硬件兼容性问题的
在 Linear 的颜色空间的话,如果在 Android 平台,那么需要在 Android 4.3 或是 OpenGL 2.0 以上(不含 2.0))
Unity BRP 管线中的 shaderlab 提供的 gamma2linear, linear2gamma
下面是在:BRP 管线中的:UnityCG.cginc
下相关与 gamma2linear, linear2gamma
的代码
可以看出来:
half3 GammaToLinearSpace (half3 sRGB)
就是提供了将half3 sRGB
的一个下压(变暗)曲线变换,等价于:outputVal=pow(inputVal, 2.2)
half3 LinearToGammaSpace (half3 linRGB)
就是提供了将half3 linRGB
的一个上拱(提亮)曲线变换,等价于:outputVal=pow(inputVal, 1.0/2.2)
⇒outputVal=pow(inputVal, 0.4545454545)
// Legacy for compatibility with existing shaders
inline bool IsGammaSpace()
{#ifdef UNITY_COLORSPACE_GAMMAreturn true;#elsereturn false;#endif
}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);elsereturn 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=1return 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;elsereturn 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=1return 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));
}
至于 IsGammaSpace()
其实就算判断,ProjectSettings…/OtherSettings/RenderSettings/Color Space : Gamma 与否:
下面是测试 shader代码
// jave.lin : 测试是否在 gamma color space 下的判断
Shader "TestInCammaOrLinear"
{SubShader{Tags { "RenderType"="Opaque" }Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;};struct v2f{float4 vertex : SV_POSITION;};sampler2D _MainTex;float4 _MainTex_ST;v2f vert (appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);return o;}fixed4 frag (v2f i) : SV_Target{if (IsGammaSpace())return half4(1, 0, 0, 1);elsereturn half4(0, 1, 0, 1);}ENDCG}}
}
GIF 效果:
Unity中线性空间配置
- 确保 unity 项目在 线性空间 (Editor/Project Setting/Player/Other Setting/Color space : 选择Linear)
- 确保 MASK贴图的 inspector 面板属性中,不勾选:SRGB
- 确保 GraphicsSetting.asset(文件所在:<ProjectName>/ProjectSettings/GraphicsSettings.asset) 中的配置是否使用了 线性空间的 灯光强度
-
使用线性颜色空间 : Linear
-
数据纹理SRGB不要勾
-
用记事本打开:<ProjectName>/ProjectSettings/GraphicsSettings.asset 文件,修改最后的内容:m_LightsUseLinearIntensity : 1
DCC 中的 gamma 值是怎么计算的?
在往下看 各种 DCC 软件 的 gamma 值设置前
先了解这些软件他们设置的 gamma 是怎么计算的
之前我们说:
- gammaCorrect - gamma 校正 -
pow(inputVal, 1.0/2.2)
- 提亮颜色 - degamma - gamma 反向校正 -
pow(inputVal, 2.2)
- 压暗颜色
上面说法没有问题,都是代码公式中写法
DCC 软件中是这么用的:(参考:Gamma and LUT Preferences)
DCC 中提到的 gamma
值,都是这么用的 outputVal=gammaCorrect(inputVal, gamma)
⇒ outputVal=pow(inputVal, 1.0/gamma)
“gamma
”的计算是 output_intensity = input_intensity (1/gamma)
。也就是说,结果是原始值的 gamma 值的倒数次幂。该计算的一个结果是 1.0 的 Gamma 值根本不会调整图像。
Gamma = 1.0:无校正
I 代表强度。
伽玛计算的另一个结果是黑色不受调整的影响,白色也不受调整(或任何完全饱和的颜色)。Gamma 调整仅影响图像的中间色调。
左:伽马 = 1.8
右:gamma = 2.2,标准
水平轴代表输入(原始值),垂直轴代表输出(伽马校正值)。
标准伽马值为 2.2。这是sRGB 标准指定的理论上正确的值。现代显示器已根据此标准进行校准。Gamma 2.2 使存储在位图中并由渲染器使用的线性色彩空间在屏幕上看起来是线性的。
然而,由于摄影胶片的响应也不是线性的,一些用户发现这个理论上正确的值看起来太亮并且褪色了。一种折衷方案是渲染到 1.7 或 1.8 的 gamma,使事物看起来更具照片感;也就是说,就好像图像是在胶卷上拍摄然后显影的。更好的方法是使用mr 摄影曝光控制,它可以模拟胶片的响应。另一种方法是在后期制作中应用类似电影的响应曲线。
建议您始终打开伽玛校正。
如果您需要为特定显示器设置伽玛,请找到一个值,使您自己的显示器上的中间灰色与真正的中间 (50%) 灰色相匹配。
注意:如果使用您的渲染的唯一其他应用程序也是 Autodesk 媒体和娱乐产品,您可能希望使用 LUT 校正而不是 Gamma 校正来进行显示。
Photoshop 的线性工作流
(下面以 Photoshop 2022 cc,23.0.0 版本为例)
方式1
先将 图像/调整/32位每通道
然后在进行:缩放、混合、或是高斯模糊,等等(涉及到 像素之间的颜色值运算的都需要先这么处理)
处理好折后,CTRL + SHIFT + E,将所有可将图层合同一个新的图层
在将这个新的图层复制打开在另一个 *.psd 工程
然后在对这个新的 *.psd 的颜色在此调整:图像/调整/8位每通道
这个方法在官方 Adobe 论坛有找到类似得说法:Creating Linear Color space
但是这种工作流的方式导致美术那边工作很麻烦
特别是多选图层的导出更加麻烦,每次导出都要 多选需要导出的、合并、再新建 PSD 图像/模式/8位通道,然后才能导出非 HDR 的 LDR 数据图片,比如:JPG, PNG 等
所以我们强烈推荐另一种方式2,往下看
方式2
另一种是:调整 编辑/颜色设置…
如果想要同步 PS 与 Unity 中的字体的透明度混合,需要设置下面的选项:
该方法可以参考我之后的一篇:Unity & PS Linear Workflow - Unity 和 PS 的线性工作流实践 - 简单配置示例
后续美术同学在新建 PSD 文档时,就可以设置:“颜色配置文件” 的配置信息了
还有 首选项->导出->去掉 颜色空间的 sRGB 复选框,这个参考:PhotoShop如何导出线性空间下的图片
(jave.lin : 首选项->导出->颜色空间的 sRGB 复选框 在部分低版本的 PS 中是没有的,我也没找到低版本在哪设置,或是压根就没得设置)
总结为一句话:编辑->颜色设置…->工作空间->RGB->自定义 RGB->Gamma: 1.0->保存,然后每次新建 PSD 都直接选这个 RGB 设置即可
这种方式在后续的贴图的制作中,设计到颜色的混合、模糊、各种计算,都是在 Linear 下的,保存导出的图像也是 线性空间下的,比之前 方式1 的有好很多
验证 Photoshop 中是否在线性工作流
检查自己的 PS 里面是否正确配置线性空间工作流,可以这么试验:
先在 同一图层 画两个 红、绿 圆形,让两个圆形 的像素有交集半个圆左右的面积
然后使用 高斯模糊 6.0 半径
如果是模糊混合出来的颜色是带有 黑色 边缘的,说明你的 PS 不是线性工作流
正确的 红、绿 模糊时 混出来的是 黄色,如下图:
PS与 Unity 下的 Linear Workflow 实践案例
直接参考我之后写的一篇:Unity & PS Linear Workflow - Unity 和 PS 的线性工作流实践 - 简单配置示例
AE 中的 Linear 工作流
C4D 中的 Octane 渲染器 的 Linear 工作流
3Ds Max VRay 中的线性工作流
Gamma Correction changes and Linear Workflow in 3ds Max - 官方 auto desk 3ds max 的 linear workflow
在一些 DCC 软件中,如果没有 Gamma 与 线性工作流的,需要自己去转换 gamma 与 线性
如下:
Linear to sRGB : sRGB(non-linear) = pow(linear pixel, 1/2.2)
sRGB to linear = pow(sRGB pixel, 1/0.4545~)
流程图
Docs
- JaveLin_美术资源规范_2022_07_18_完善_UI_特效_PS_线性空间的配置
- JaveLin_美术资源规范_2022_07_19_完善_UI_特效_PS_AE_线性空间的配置
URP下的 UI alpha blend 的 gamma to linear
可以参考:
- Unity Products:Amplify Shader Editor/Gamma To Linear
- URP下Alpha从Gamma空间到Linner空间转换(二)——多Alpha贴图叠加
- 为什么Unity使用AssetBundle热更的时候要剔除掉.mainfest文件
BRP下的 UI alpha blend 的 gamma to linear
(后续自己增加实例测试)
References
- Color space - unity 官方的文档 - 建议先看这个 大智的讲解(相信里面的部分理解也是看过 韩世鳞 老师的视频)
- Gamma校正与线性工作流入门讲解 - 韩世鳞 老师的讲解,太牛逼了,有讲解 3ds max, vray 的 3ds max插件, photoshop 的工作流
- V-Ray for 3ds Max 线性工作流参数设置详解
- V-Ray for SketchUp 线性工作流参数设置详解
- Gamma校正 - 结合大部分 DCC 的涉及 gamma 校正的处理,很不错
- s2010_physically_based_shading_hoffman_b.pdf
- Unity3D Gamma And Linear Space
- Renderdoc确认线性or伽马空间工作流
- Technical Artist 的不归路 —— 线性空间光照
- Gamma vs Linear Space - 这帖子有点逗,从 伽马 vs 线性空间,跳到了:A2C(Alpha to Coverage) 的部分。。。
- 聊聊Unity的Gamma校正以及线性工作流
- Unite 2018 | 浅谈伽玛和线性颜色空间
- 关于Color Space是Gamma还是Linear的一些问题
- [Translate]Reverse Engineering The Rendering Of The Witcher 3 I | [译]巫师3渲染逆向工程 1 - 里面有 DXBC ASM 的查看巫师3的 gamma 校正处理
- Creating Linear Color space - Photoshop 颜色空间 的 线性空间的正确设置姿势
- Proper Linear Workflow | Fusion, AE, PS, Octane, C4D - 讲解 Fusion, AE, PS, C4D Octane 的 Linear 工作流
- UNDERSTANDING GAMMA CORRECTION - 专业摄影讲解 gamma 校正
- Linear Workflow: Gamma 2.2 Setup in 3ds max and Vray, Working with Correct math! - 3Ds max 和 VRay 渲染器的 linear workflow 设置
- Gamma Correction changes and Linear Workflow in 3ds Max - 官方 auto desk 3ds max 的 linear workflow
- Gamma and LUT Preferences - 官方 auto desk 3ds max 的 linear workflow
- Confusion about Gamma vs. Linear - 说真的,unity 把这些 gamma, linear 搞得让人发懵
- PhotoShop如何导出线性空间下的图片
- Unity线性空间UI制作方面总结
- 关于Unity伽马校正的一点笔记
- Unity线性空间UI的问题 - 里面有写 gamma 和 linear 的一些 RGB 和 Alpha 的混合公式,但是怎么由来的,或是参考哪里的,并没有说明
- Gamma校正与线性空间