← ALL ARTICLES

颜色空间

全库目录221
本文目录8

sRGB中间灰值不是一半光能。把编码值直接当作线性光能做运算,会改变亮度关系。颜色空间记录原色、白点和传递函数;采样解码后在线性空间处理,显示时再编码。

颜色编码

线性光照计算

现实中的光能量可以线性相加。两盏相同灯一起照射,理想情况下总能量是单盏的两倍。

显示和图片编码通常不是线性的。例如把黑与白的编码值平均为0.5,显示时对应约0.214的线性值;线性光能的平均应为0.5,编码后约为0.735。加法、乘法和插值产生的错误不同,不能一概理解为固定的变暗系数。

典型流程:

text
sRGB 颜色纹理
  → 采样时解码为 Linear
  → 光照、混合和后处理
  → Tone Mapping
  → 输出编码到显示空间

sRGB传递函数

sRGB 使用分段传递函数。低值部分近似线性,其余部分接近幂函数。

从 sRGB 编码值 CsC_s 解码到线性值 ClC_l 的常见形式:

Cl={Cs/12.92,Cs≤0.04045(Cs+0.0551.055)2.4,Cs>0.04045C_l= \begin{cases} C_s/12.92,&C_s\le0.04045\\ \left(\frac{C_s+0.055}{1.055}\right)^{2.4},&C_s>0.04045 \end{cases}

用 C2.2C^{2.2} 是简化近似,不是完整 sRGB 定义。

sRGB 还规定色度原色和白点。讨论广色域、HDR 显示时,不能只看传递函数。

编码、原色与输出

编码的逆变换为

Cs={12.92Cl,Cl≤0.00313081.055Cl1/2.4−0.055,Cl>0.0031308.C_s=\begin{cases}12.92C_l,&C_l\le0.0031308\\ 1.055C_l^{1/2.4}-0.055,&C_l>0.0031308. \end{cases}

本式用于非负的标准sRGB范围,广色域变换产生的负值与超范围值需按工作流程处理,不能先裁剪再期待恢复颜色。把sRGB解码为线性值只改变传递函数,不会改变原色;线性sRGB和线性Display P3仍是不同的RGB坐标系。转换原色时通常经XYZ矩阵,白点不同时还需色适应。

以下HLSL标量函数用于离线核对或需要手动转换的明确接口,输入限定在 [0,1][0,1]。使用sRGB资源视图自动转换时,Shader直接使用读取值;手动再解码会重复变换。

hlsl
float DecodeSRGB(float encoded)
{
    return encoded <= 0.04045 ? encoded / 12.92
        : pow((encoded + 0.055) / 1.055, 2.4);
}
float EncodeSRGB(float linearValue)
{
    return linearValue <= 0.0031308 ? linearValue * 12.92
        : 1.055 * pow(linearValue, 1.0 / 2.4) - 0.055;
}

纹理过滤需要先把参与的颜色样本解码,再在线性值之间插值;混合目标也需要按API规定完成目标解码、混合和写入编码。输出到sRGB视图与手动编码二者选定一种,避免重复。输出编码是显示链末端的表示转换,不能替代Tone Mapping。

纹理编码选择

先依据资产的数值定义和文件编码判断。颜色图片可能使用sRGB,也可能已经是线性HDR;数据纹理则按定义读取数值。

常用 sRGB

  • Base Color/Albedo;
  • UI 彩色图片;
  • 手绘颜色和部分 Emissive 颜色。

常用 Linear/Data

  • Normal;
  • Roughness、Metallic、AO;
  • Mask、Height、SDF;
  • LUT 和数值查找纹理;
  • 深度和运动向量。

不能因为一张贴图看起来是灰色就判断它是 Linear。灰色照片仍是颜色,单通道 Roughness 才是数据。

在线性sRGB中,RGB到XYZ的Y分量是0.2126R+0.7152G+0.0722B。纯红(1,0,0)的相对亮度约0.2126,纯绿约0.7152,因此编码值或RGB最大分量相等不等于亮度相等。把sRGB红通道0.5先解码得到约0.2140,再乘0.2126,亮度约0.0455;直接把编码0.5代入矩阵会得到0.1063。

这个计算展示两个顺序不同的操作:先去传递函数,再变换原色坐标。白点不同还需要按选定色适应模型变换XYZ;本页不以一组亮度系数替代完整色域与白点转换。

验证方法

0.5的sRGB解码约为0.214,先比较数值再看显示。检查颜色纹理与数据纹理view,防止手动解码和硬件解码叠加。平方反比照度机制以直接光照为主归属,这里只核对计算空间。

test_post.py 检查0.5解码、线性中灰编码和分段阈值两侧往返,正文函数通过DXC编译。实际资源视图和显示输出尚未运行。

相关主题

参考资料