Unity 中的颜色空间

发布于:2025-06-07 ⋅ 阅读:(20) ⋅ 点赞:(0)

一、颜色空间基本概念疑问

1、什么是颜色空间?

    颜色空间是一个数学模型或系统,它定义了一套规则和方法,用来精确地描述、表示和组织颜色。​
    可以把它想象成一个三维坐标系​(或者有时更多维)
    每个维度代表一个构成颜色的基本分量
    每个维度都有一个取值范围(例如 RGB 通常是 0-255 或 0.0-1.0),这个范围定义了该颜色空间所能表示的所有可能颜色的集合,称为色域。

    简单来说:
    颜色空间就像一本关于颜色的“字典”和“语法规则”。它提供了一套标准化的方法来:
    ①、​定义一个颜色(给它一个数值坐标)。
    ②、​组织所有可能的颜色(形成一个色域)。
    ③、​沟通颜色信息(在不同设备、软件或人之间传递颜色数据)。

    常见颜色空间:
    ​RGB​ 颜色空间,维度:​红色、绿色、蓝色。任何颜色都可以看作是这三种光以不同强度混合的结果。
    CMYK​ 颜色空间(用于印刷),维度:​青色、品红色、黄色、黑色。数值代表的是油墨的浓度。
    ​HSV/HSL​ 颜色空间,维度:​色调、饱和度、明度/亮度。这更接近人眼感知颜色的方式(什么颜色?有多鲜艳?有多亮?)。
    ​Lab/L*a*b​* 颜色空间,维度:​明度、红绿轴、黄蓝轴。它试图模拟人眼感知颜色的均匀性,并且是设备无关的。

2、什么是线性空间(线性颜色空间)?

    线性颜色空间​(Linear Color Space)是指颜色值与物理光强呈线性关系的色彩表示系统。
    在这种空间中,数值的增减直接对应于光强的线性变化,没有经过任何非线性变换(如伽马校正)。
    线性关系​:颜色通道(如RGB)的数值与实际光强成正比。
    即:基于“颜色空间”的定义来看,坐标轴上均匀的数值变化,能够正比映射到均匀的物理光强变化。

    例如,RGB值 (0.5, 0.5, 0.5) 表示的光强是 (1.0, 1.0, 1.0) 的一半。

3、什么是伽马空间(伽马颜色空间)?

    伽马颜色空间(Gamma Color Space)是指颜色值经过非线性编码(伽马校正)​处理的色彩表示系统。
    在这种空间中,颜色数值与实际显示的光强之间呈非线性关系。

    注意,广义Gamma空间的概念​:泛指所有通过幂律函数(V_out = V_in ^ γ)进行非线性映射的色彩空间。无论是否 γ = 1/2.2

4、执行伽马校正的原因(将线性空间转到伽马空间的原因)是什么?

    ①、匹配人眼感知​:对颜色值进行非线性变换,使数值分布更符合人眼对亮度的感知(暗部更敏感,亮部较迟钝)。
    ②、高效数据利用​:自然场景中,大量的信息(像素数量)集中在较低亮度区域(暗部)。伽马编码通过压缩亮部数据,可在8位/通道下保留更多视觉有效信息。
    ③、兼容显示设备​:传统CRT显示器的阴极射线管(CRT)的输入电压与亮度输出呈 ​γ≈2.5​ 的幂律关系(即 亮度 ∝ 电压 ^ 2.5)。为了抵消CRT的非线性,需对输入信号预补偿(即 电压 ∝ 数值 ^ 1/2.2),最终使显示亮度与原始数据线性对应。

5、为什么要叫 “伽马” 空间/ “伽马” 校正?

    伽马校正的核心是幂律变换​(Power Law)其公式为:V_out = V_in ^ γ
    其中,γ(希腊字母Gamma)是幂律的指数,用于描述输入与输出的非线性关系。

6、【易混淆点】物理世界是什么颜色空间?

    注意颜色空间的定义!它是一个人为定义的数学模型,物理世界不是模型,所有没有颜色空间的概念。
    因此,物理世界本身没有颜色空间的概念。
    但,光的叠加遵循线性规则,人类用线性颜色空间模拟其光的线性混合行为,因此光的物理行为等价于线性空间。

7、颜色在计算机中存储时是什么颜色空间?

    在计算机中存储颜色时,最常用的颜色空间是 ​sRGB(Gamma空间)

    为什么是sRGB?​
    ①、历史与普及性​:由微软和惠普于1996年制定,成为互联网、操作系统和消费级显示器的默认标准。
    ②、​兼容性​:几乎所有设备(显示器、手机、相机)默认支持sRGB,确保颜色显示一致。
    ③、存储效率​:通过伽马编码(≈γ2.2)优化8位/通道的数据分布,保留更多暗部细节。

8、颜色在交给显示器时是什么颜色空间?

    当颜色数据最终交给显示器显示时,通常需要转换为显示器原生支持的色彩空间,而现代显示器主要遵循 ​sRGB标准。

    为什么是sRGB?​

    ①、历史兼容性​:CRT时代遗留的伽马特性(γ≈2.2)与sRGB一致,现代LCD/OLED仍沿用此标准。
    ②、内容适配​:互联网、操作系统、大部分内容(JPEG、视频)默认以sRGB编码。
    ③、硬件校准​:消费级显示器出厂默认以sRGB为色彩目标(即使面板色域更广)。

9、从物理世界的颜色到显示器的整个过程是怎样的?

    “物理世界的线性数值” 通常是在图像捕获(如相机)或渲染(如3D图形)阶段生成的线性数据。
    然后,为了存储或传输(如第7条所述),数据会经过伽马编码(γ=1/2.2)转换为sRGB等伽马空间(非线性)。
    当你在计算机上查看一张JPEG图片(sRGB编码)时,数据以伽马空间形式发送到显示器。
    显示器内部的电子系统(或显示驱动)再应用γ≈2.2的曲线,最终输出线性光强。

    V_out = V_in ^  1/2.2 ^ 2.2 = V_in

    最终显示器输出的光强完美还原了原始线性光强。

10、sRGB 是什么? sRGB 的 s 指什么?

    sRGB​(Standard Red Green Blue)是由 ​微软(Microsoft)​​ 和 ​惠普(Hewlett-Packard)​​ 于1996年联合制定的国际标准色彩空间​(IEC 61966-2-1),
    旨在统一显示设备、互联网和操作系统的颜色表现。

    其名称中的 ​​“s”​​ 代表 ​​“Standard”(标准)​,强调其作为通用默认色彩空间的定位。

11、sRGB 和 Gamma空间 的关系是什么?

    sRGB 是一种特定的 Gamma 编码色彩空间(one of)

    其核心是通过 ​标准化的 Gamma 曲线(≈2.2)​​ 将线性光强转换为非线性存储值,以适配人眼感知和显示设备特性。

------------------------------------------------- NRatel割 -----------------------------------------------------

二、Unity 中的颜色空间

https://docs.unity3d.com/cn/current/Manual/class-PlayerSettingsAndroid.html#Renderinghttp://颜色空间选择

https://docs.unity3d.com/2021.3/Documentation/Manual/class-TextureImporter.htmlhttp://Texture 导入选项(TextureImporter)(纹理的 Inspector 窗口)(重点关注 sRGB 选项)

https://docs.unity3d.com/2021.3/Documentation/Manual/LinearLighting.htmlhttp://颜色空间

https://docs.unity3d.com/2021.3/Documentation/Manual/LinearRendering-LinearOrGammaWorkflow.html​​​​​​http://线性或伽马工作流程

https://docs.unity3d.com/2021.3/Documentation/Manual/LinearRendering-GammaTextures.htmlhttp://采用线性渲染的伽马纹理

https://docs.unity3d.com/2021.3/Documentation/Manual/LinearRendering-LinearTextures.htmlhttp://使用线性纹理

1、基本

    光照计算应该在线性空间中进行,以便确保数学上的正确性,但结果应该在伽马空间中呈现以便让人眼看起来正确。

    纹理倾向于保存在伽马颜色空间中,而着色器期望使用线性颜色空间。

2、在 Unity 的 PlayerSettings/OtherSettings/ColorSpace 中,可选颜色空间 Gamma / Linear

    选择 Gamma:
        伽马空间的着色器程序 在使用纹理时,不会从纹理中移除伽马校正。
        在纹理的 Inspector 窗口中取消勾选 sRGB,即可在 Gamma 模式下绕过 sRGB 采样。

    选择 Linear:
        应总是向 线性颜色空间的着色器程序 输入 线性空间的纹理。
        若纹理是在伽马空间创建的,应在纹理的 Inspector 窗口中勾选 sRGB。
        若纹理本身就是在线性空间创建的,则应在纹理的 Inspector 窗口中取消勾选 sRGB。
        当完成着色工作后,GPU会在Shader写入颜色缓冲区前自动进行伽马校正或保持线性在后续进行伽马校正。

如何选择?

在Unity项目中选择颜色空间(Color Space)时,主要取决于项目的视觉风格、目标平台以及光照需求

适合 Linear 空间的情况:
        写实风格项目​:需要物理准确的光照(如PBR材质、HDRP/URP)。
        复杂光照效果​:动态光影、阴影、反射等。
        目标平台为中高端设备​(PC、主机、高端移动设备)。
        使用HDR或后期处理​。
适合 Gamma 空间的情况:
​        风格化或低多边形(Low Poly)项目​:对物理光照无硬性需求。
        目标为低端移动设备​(性能敏感,硬件不支持线性空间)。
        2D项目或UI为主​:颜色混合需求简单,无需物理光照。
特殊情况:
        如抖音小游戏 开启WEBGL2.0时,要求必须使用 Linear 空间。

3、若在Texture 导入选项(TextureImporter)上勾选 sRGB,意味着:

    此设置仅在项目使用线性颜色空间时相关。   
    指示纹理将数据存储于 sRGB(也称为伽马)颜色空间中。
    如果启用,它会指示 GPU 在着色器中对纹理进行采样时将数据从 sRGB 颜色空间转换为线性颜色空间。

    对于存储常规颜色数据的非 HDR 纹理启用此功能。
    对于包含非颜色数据(例如平滑度或金属度)的纹理禁用此功能。
    对于 HDR 纹理,Unity 默认禁用此值并隐藏复选框。
    对于非 HDR 纹理,Unity 默认启用此功能。

4、不同颜色空间下混合

    伽马空间下混合:在数学上是不正确的,并可能得出不符合期望的结果,但这种方法是在某些图形硬件上进行混合的唯一方法。

    线性空间下混合:在数学上是正确的,并提供精确的结果。

5、注意,更改颜色空间后,需重新烘焙光照贴图

6、注意,旧版GUI系统(IMGUI)中的元素渲染始终在伽马空间中完成

7、查找纹理(lookup Texture)、遮罩、Noarmal贴图、Metalic贴图 和 其他具有特定含义的在线性空间性下制作的纹理应取消勾选 sRGB。

三、游戏UI在线性空间下的混合 与 美术效果图不一致的问题

原因:

sRGB编码的半透明图片,在Unity中,勾选sRGB,在进行混合前,着色器会在对纹理进行采样时,会先将数据从 sRGB 颜色空间转换为线性颜色空间。然后使用 混合公式 进行混合。

而绝大多数绘图软件 (Photoshop, Krita, Illustrator 等) 默认在 sRGB 色彩空间下工作、混合、显示和保存图片。

在这些软件中,用半透明画笔、图层叠加模式 (如 "正常"、"正片叠底"、"叠加"、"滤色"、"叠加"、"柔光" 等) 绘制或叠加 UI 元素时,​混合操作是基于 sRGB 空间中存储的值直接进行的。

简单说,在绘图软件中,直接使用Gamma空间下的色值套用线性空间下才应该使用的 混合公式,产生了实际上错误的混合结果。

PS 图层混合模式https://helpx.adobe.com/hk_zh/photoshop/using/blending-modes.html例如,图层混合模式为 Normal 的混合公式为:

(该公式为线性空间下的混合公式,输入应为线性色值)

color = A.rgb * A.alpha + B.rgb * (1 - A.alpha)

在 Unity 线性空间下,sRGB编码的图片,勾选了sRGB时,混合时将执行:

color = (A.rgb^2.2 * A.alpha + B.rgb^2.2 * (1 - A.alpha))

交给显示器前,将会再对其执行一次伽马校正,转回 Gamma空间,即:

color1 = (A.rgb^2.2 * A.alpha + B.rgb^2.2 * (1 - A.alpha)) ^ (1/2.2)

而在 PS 伽马空间下,sRGB编码的图片的色值,将直接带入Normal混合公式:

color2 = A.rgb * A.alpha + B.rgb * (1 - A.alpha)

很明显,color1 ≠ color2 (这者最终都是 伽马空间下 的值)。

------------------------------------------------- NRatel割 -----------------------------------------------------

实例:

游戏中(color1)(Unity 线性空间下,sRGB图片勾选sRGB)

 效果图中(color2)(PS在伽马空间下)

------------------------------------------------- NRatel割 -----------------------------------------------------

为使 游戏UI在线性空间下的混合 与 美术效果图一致,解决的思路无非以下两种(盲调除外):

方式1、保持游戏UI在线性空间下混合,并让美术也在线性空间下混合。

    修改 PS 中的设置(编辑> 颜色设定>高级选项):勾选 Blend RGB Colors Using Gamma

 参考 photoshop官方文档的说明:

Photoshop 颜色设定https://helpx.adobe.com/hk_zh/photoshop/using/color-settings.htmlGamma空间下,但 γ=1.00,即相当于处于线性空间下。

中文版本的 ps 中,此处称为 “用灰度系数混合RGB颜色”,以下为 PS CS6中文版中截图。

为什么把 “Gamma(γ)” 要叫做 “灰度系数” 呢?

经查,主要由于 早期翻译的局限性行业习惯的固化

20 世纪 80-90 年代,计算机图形学刚引入中文语境时,术语翻译尚未标准化。Gamma 作为专业概念,可能被简单意译为“灰度系数”,侧重其 ​对明暗(灰度)的调节作用,而忽略了它对 ​所有颜色通道(RGB)​​ 的普遍影响。

尽管 Gamma 实际影响所有颜色通道,但“灰度系数”一词在显示器校准、印刷等领域沿用至今,成为约定俗成的译法

这种方式的优缺点:

    优点:美术和程序都能得到数学上的正确结果。
    缺点:美术可能会不适应这种感官(差异于之前长久的习惯)。

方式2、保持美术在伽马空间下混合,并让游戏UI也在伽马空间下混合。

    (使 场景使用线性空间,而UI使用伽马空间。)

一些修改方案:

    https://github.com/killop/URP-12-GammaUIAndSplitResolution

    https://github.com/TakeshiCho/UI_RenderPipelineInLinearSpace

这种方式的优缺点:

    优点:美术保持原习惯。
    缺点:修改渲染方式可能导致一些潜在问题,如性能变差。

------------------------------------------------- NRatel割 -----------------------------------------------------

个人倾向选择方式1。原因是:

1、简单,且让程序和美术都面向一个正确结果。

2、2D 或 2D+3D 的游戏项目也可会在有线性空间下进行混合的需求。SpriteRenderer也是由美术在PS中像UI一样出的图。只让UI在Gamma下混合不能满足实际需要。


网站公告

今日签到

点亮在社区的每一天
去签到