中EN
概念页

显示编码与 sRGB

Display Encoding & sRGB

更新于 2026-10-15 约 13 分钟gammasRGB线性工作流颜色

光照、纹理等计算假设数值是线性的,但显示缓冲和纹理使用非线性编码。简短的回答是:着色器输出 [0,1] 的颜色要取 1/2.21/2.2 次幂(gamma 校正),读入的纹理和颜色做相反的变换,多数情况下可以让 GPU 自动完成。忽略它会导致画面偏暗、色相偏移、光照叠加错误和抗锯齿边缘"绳索化"。

为什么有非线性编码

  • CRT 的输入电压与发出辐亮度呈大于 1 的幂函数关系(例如幂为 2 时,50% 的像素只发出 1/4 的光)。LCD 等显示器内置转换电路来模仿 CRT 的响应。
  • 这个幂函数几乎正好是人眼亮度感知的逆,所以编码近似感知均匀:相邻编码值的感知差异在整个范围内大致恒定(人眼在很多条件下能察觉约 1% 的亮度差)。这样在有限精度的显示缓冲和纹理中能最大程度减少色带。
  • 显示传递函数 (EOTF) 描述缓冲中的数字值与显示器发出辐亮度的关系,是硬件的一部分;采集设备一端是 OETF。

编码与解码

flowchart LR
  A["PNG 等颜色纹理 显示编码"] -->|"解码"| B["线性值: 着色与色调映射"]
  B -->|"编码"| C["帧缓冲"]
  C -->|"显示器传递函数"| D["发出的辐亮度 与线性计算值成正比"]

上图对应书中 Figure 5.39:读纹理时解码成线性值,着色和色调映射后编码写入帧缓冲;编码函数与显示器传递函数相互抵消,最终辐亮度与计算值成正比。

  • 个人电脑显示器的标准传递函数由 sRGB 规范定义。多数 API 可以设置在读取纹理、写入颜色缓冲时自动做 sRGB 转换;mipmap 生成会考虑 sRGB 编码;双线性插值会先转成线性再插值;alpha 混合会先解码、混合、再编码。
  • 转换要在渲染的最后阶段写入显示帧缓冲时进行。如果在显示编码之后再做后处理,就是在非线性值上计算,通常错误且会产生伪影。
  • 可以把显示编码看作一种最大程度保留感知效果的压缩。

公式

线性 → sRGB 编码: y={1.055x1/2.4−0.055,x>0.003130812.92x,x≤0.0031308y=\begin{cases}1.055x^{1/2.4}-0.055,&x>0.0031308\\12.92x,&x\le0.0031308\end{cases} sRGB → 线性解码: x={(y+0.0551.055)2.4,y>0.04045y12.92,y≤0.04045x=\begin{cases}\left(\frac{y+0.055}{1.055}\right)^{2.4},&y>0.04045\\ \frac{y}{12.92},&y\le0.04045\end{cases}

  • 线性小段是为了让变换在数字硬件上可完全逆转。幂函数部分可近似为 y=x1/γy=x^{1/\gamma},γ=2.2\gamma=2.2,这就是"gamma 校正"名称的来源。
  • 移动端和浏览器有时用更简单的 y=xy=\sqrt{x}、x=y2x=y^2,虽然粗糙,但比完全忽略好。
  • 截图或拾色器得到的颜色、PNG/JPEG/GIF 中的值都是显示编码的数据,参与着色计算前必须解码。

常见错误

  • 手动转换时用了编码后的颜色当线性值,或者重复编码/解码两次。
  • 不编码:线性 0.1、0.2、0.5 本应编码为 0.351、0.481、0.730,直接输出会让暗部过暗、部分颜色色相偏移。过去建模人员常把暗色人为调亮来补偿,相当于把逆显示变换"烤"进了资产。(0 和 1 在任何变换下不变。)
  • 光照叠加错误:两盏聚光灯 0.6 与 0.4 在非线性空间相加,左边看起来亮得多,重叠处亮得不真实。
  • 抗锯齿边缘:线性覆盖率 0.125、0.375、0.625、0.875 若不经编码直接显示会过暗,边缘看起来像扭曲的绳子,称为 roping。

之后的发展

sRGB 标准于 1996 年制定。更亮、色域更宽的显示器出现后,相关内容见第 8 章(色度学与色彩空间、色调映射)。

GEA 的视角:位图颜色格式与 gamma(卷 II 11.3.3、11.3.4.2)

位图、渲染目标与颜色格式

  • 位图是数字编码颜色的二维表,单元格即像素。引擎的输出是叫帧缓冲的位图;引擎绘制进去的任何缓冲(帧缓冲或离屏图像)都叫渲染目标 (render target);贴在表面上的位图叫纹理(卷 II 11.3.3)。
  • 分辨率与宽高比:早期电视 4:3(fullscreen),电影偏好 16:9(widescreen),如今 16:9 是电影和游戏的事实标准,部分游戏支持 21:9、32:9 超宽屏。"4K"指约 4,000 像素宽的 16:9 格式(精确为 3,840),又称 2160p,后者引用的是高度;p 指逐行扫描,与隔行扫描相对。可用 16×2160=9×384016\times2160=9\times3840 验证 16:9。

原书问题(11.3.3.1):

  • GEA 说一百万像素"更精确地说是 1,048,576 即 2202^{20} 像素"。百万像素 (megapixel) 的 mega 是十进制 SI 前缀,1 MP = 10610^6 像素(Wikipedia "Pixel" 的 Megapixel 一节);书中自己的例子也只在十进制下成立:5,312 × 2,988 = 15,872,256 ≈ 15.9 × 10610^6,若按 2202^{20} 算只有约 15.1 MP。
  • GEA 说 IMAX 画幅"高大于宽(通常 1:1.43 或 1:1.90)"。IMAX 的 1.43:1 和 1.90:1 是宽:高,画面仍是宽大于高,只是比 16:9(1.78:1)更方或略宽(Wikipedia "IMAX")。
  • "电影人偏好 16:9"不准确:影院宽银幕常用 1.85:1 和 2.39:1;16:9 是 SMPTE 的 Kerns Powers 在 1980 年代为 HDTV 选的折中比例(约为 4:3 与 2.35:1 的几何平均),便于以最少的黑边兼容各种画幅(Wikipedia "16:9 aspect ratio")。
  • 颜色格式描述编码方式、每通道如何存储(浮点或整数)以及位数,常以"编码 + 每像素位数"概括:
格式每像素说明
3×FP3296 位引擎内部做光照计算用,HDR 需要高精度
RGB88824 位每通道 0–255
RGB56516 位红蓝 5 位、绿 6 位
I8 / R88 位只存亮度的灰度图
调色板少量位像素存颜色表索引,早期 2D 像素画常用
RGBA888832 位加 8 位 alpha
RGBA555116 位1 位 alpha,只能全透明或全不透明
log-LUV32 位HDR:亮度 L 以 2 为底取对数存 16 位,色度 U、V 各 8 位(人眼对亮度变化比对色度更敏感)
FP16每通道 16 位HDR:IEEE 754-2008 半精度,1 位符号、5 位指数、10 位尾数(含隐含位 11 位)
  • alpha 表示不透明度,0 为全透明、1 为全不透明。GEA 指出它在光线追踪引擎里用处不大,但在光栅化引擎里被广泛用作模拟光穿过参与介质的"hack"(见 透明渲染与 Alpha 混合)。FP16 的位布局见 数值表示与浮点数。

gamma 校正

  • 把 [0,1] 浮点颜色线性映射到 [0,255] 会在人眼不敏感的亮部浪费精度、在敏感的暗部精度不足,所以写入整数格式时要先做 gamma 校正(卷 II 11.3.4.2)。
  • GEA 把公式写成 Cout=CinγC_{out}=C_{in}^{\gamma}:γ<1\gamma<1 叫编码 gamma(gamma 压缩),用于把线性浮点颜色存进位图;γ>1\gamma>1 叫解码 gamma(gamma 展开),用于读入压缩位图后转回浮点参与着色。所有光照计算都应在线性空间进行。
  • 由来:老式 CRT 对输入信号的响应是约 γ=2.2\gamma=2.2 的幂函数;现代显示器没有这种固有曲线,但为了一致性仍模仿它,所以引擎写帧缓冲前要做 gamma 编码,由显示器抵消。

与本页 RTR4 内容的对照

  • 记号不同:RTR4 把编码写成 y=x1/γy=x^{1/\gamma}、γ=2.2\gamma=2.2;GEA 把指数本身叫 γ\gamma,编码时 γ<1\gamma<1。两者等价,读公式时要看清 γ\gamma 指的是哪个数。
  • sRGB 帧缓冲的描述:RTR4 说缓冲中存的是显示编码后的非线性值,API 在写入颜色缓冲时自动做 sRGB 转换;GEA 卷 II 11.3.4 则写道"今天的显卡支持 sRGB 格式,颜色以线性空间存储,gamma 校正由硬件自动应用"。按 RTR4 的说法,硬件自动转换的是"写入"和"读取"这两步,缓冲中的数据本身是编码过的;GEA 这句话容易被理解为缓冲里存的是线性值。这里并列记录。

原书问题(11.3.4):按字面理解 GEA 的说法是错的。D3D 的 *_SRGB 格式(如 DXGI_FORMAT_R8G8B8A8_UNORM_SRGB)中存的是 sRGB 编码后的值,硬件在着色器读取时解码为线性、在写入渲染目标(以及混合)时编码回 sRGB(MS Learn "Gamma correction" / "Converting data for the color space");所以着色器"看到"的是线性值,内存里存的不是。RTR4 的描述正确。

PBRT 的视角:ColorEncoding(PBRT 4e B.5.6)

  • 动机:CRT 的亮度与电压呈 VγV^\gamma 关系;如今显示器不再用电子枪,但量化存储(8 位)仍应使用非线性编码,因为按韦伯定律 (Weber's law) 人眼大约需要 1% 的相对变化才能察觉,线性编码会把码值浪费在看不出的差别上。
  • sRGB 编码:x≤0.0031308x\le0.0031308 时 xe=12.92xx_e=12.92x,否则 xe=1.055x1/2.4−0.055x_e=1.055x^{1/2.4}-0.055;逆变换以 xe≤0.04045x_e\le0.04045 为界。pbrt 的 LinearToSRGB8() 用有理多项式近似避免 std::pow,8 位解码用 256 项查找表,任意浮点用另一个有理近似。
  • pbrt 内部全部用线性浮点,只在读写 PNG 等定点格式时编解码;输出推荐 OpenEXR 或 PFM 这类浮点格式以保留高动态范围。

LearnOpenGL 的视角:线性工作流与 sRGB 纹理(Advanced Lighting / Gamma Correction)

来源:Gamma Correction;摘录 Advanced Lighting — Gamma Correction。与上文 RTR/PBRT 的显示编码对照;此处补 OpenGL 开关与着色器落地。

监视器近似把电压按 γ≈2.2 映射亮度(sRGB 空间接近该曲线)。若在「看起来正确」的监视器空间里配光再当线性用,中间亮度会被压暗,翻倍光源在屏上可亮四倍以上。做法:在最终输出前做逆 gamma(×^(1/2.2)),或 glEnable(GL_FRAMEBUFFER_SRGB) 让硬件在写入颜色缓冲前校正。多 pass 时中间缓冲保持线性,只在最后一档校正。

纹理:美术在监视器上画的漫反射图已在 sRGB;若渲染端再做一次 gamma,会过亮。可用 pow(tex, 2.2) 或内部格式 GL_SRGB / GL_SRGB_ALPHA 在采样时自动转到线性。镜面/法线等数据贴图通常已是线性,不要标成 sRGB。

衰减:无 gamma 时 1/d21/d^2 往往过猛,人们改用 1/d1/d 或可调二次式;进入线性工作流后物理上的 1/d21/d^2 突然更合理,因为以前等于又被监视器 gamma 再压了一次。更复杂的 1/(Kc+Kld+Kqd2)1/(K_c + K_l d + K_q d^2) 仍可用,但参数要按 gamma 场景重调。PBR 章要求输入全线性,与此一致。

GPU Gems 的视角:保持线性的重要性(GPU Gems 3 第 24 章)

来源:Gritz & d'Eon《The Importance of Being Linear》;摘录 Chapter 24. The Importance of Being Linear — Gritz, d'Eon。与上文 RTR/PBRT/LearnOpenGL/GEA 的 gamma 讨论同源;本章把症状与皮肤着色绑在一起讲透。

光传输是线性的,CRT/仿 CRT 的 LCD 响应接近指数(γ≈2.0–2.4)。JPEG 默认按 γ≈2.2 预校正,在非线性空间做光照、mip 平均、alpha 合成都会算错。典型症状:Lambert 球体 60° 处本应一半亮,γ=2 屏上只剩四分之一;mip 边界亮度跳动;皮肤次表面在非线性空间调参会出现蜡感与阴影边缘青绿色;高光加到漫反射上发黄。

处方三步:假定玩家显示器约 2.2(或提供校准图);颜色纹理用 sRGB 格式取样时硬件线性化(GF8+ 在过滤前线性化),法线/高度/alpha 不要线性化;最后一步才做输出 gamma(优先 sRGB 帧缓冲,混合也会先线性化再校正)。中间 8 位线性缓冲会丢掉暗部精度,中间色多用 16F 或 sRGB FBO。「纹理也不线性化、输出也不校正」的双重错误有时看起来还行,但一改灯光颜色就穿帮——游戏与电影 CG 观感差距里,色彩管理是常被低估的一项。

  1. realtime_rendering_4ed.pdf 第 5 章 Shading Basics
  2. Game_Engine_Architecture_4th_Edtion_Volume_2_-_Jason_Gregory.pdf
  3. Jason Gregory《Game Engine Architecture》第 4 版(2026)卷 II 第 11 章 11.3.3、11.3.4.2 节
  4. PBRT 4e source excerpt: chapter B (Utilities)
  5. Pharr, Jakob, Humphreys《Physically Based Rendering: From Theory to Implementation》第 4 版(MIT Press, 2023)附录 B B.2–B.7 节与延伸阅读,pbr-book.org/4ed/Utilities
  6. Chapter 24. The Importance of Being Linear — Gritz, d'Eon
  7. developer.nvidia.com/gpugems/gpugems3/part-iv-image-effects/chapter-24-importance-being-linear
  8. Advanced Lighting — Gamma Correction
  9. learnopengl.com/Advanced-Lighting/Gamma-Correction

相关页面

图形学色调映射Tone Mapping色调映射把场景参考的辐射亮度转换为显示参考的辐射亮度,目标不是恒等复现、也不是把所有信息"挤进"显示范围,而是在显示条件下尽量复现观看原场景时的感知印象。它通常是曝光缩放加一条 S 形曲线(全局映射),之后可做调色;最后由显示编码输出到 SDR 或 HDR 显示器。图形学色度学与色彩空间Colorimetry & Color Spaces色度学研究光谱功率分布与颜色感知的关系。人眼只有三种视锥细胞,所以三个数就能精确表示任意颜色刺激;CIE XYZ 是标准的三刺激值空间,各种 RGB 色彩空间由三原色和白点定义,可用 3×3 矩阵互相转换。实时渲染用 RGB 而非光谱计算,严格说是范畴错误,但对非预测性渲染效果出奇地好。图形学纹理映射管线Texturing Pipeline纹理通过修改着色方程中使用的值(颜色、粗糙度、法线等)来高效表现表面材质的变化。通用纹理管线是:空间位置 → 投影函数得到纹理坐标 → 对应函数变换到纹理空间 → 取值 → 值变换 → 用于着色。本页还整理纹理坐标约定、纹理表示方式、程序纹理、纹理动画、材质贴图、alpha 贴图和纹理光源。图形学抗锯齿Antialiasing渲染本质上是采样,采样频率不足就会混叠(锯齿、闪烁的"萤火虫"、车轮倒转)。屏幕空间抗锯齿在每个像素取多个样本并加权求和:超采样最直接但最贵,MSAA 每像素只着色一次,时间抗锯齿 (TAA) 把样本分散到多帧,形态学方法 (FXAA/SMAA) 作为后处理重建边缘。没有一种方法在所有方面最好。图形学纹理过滤与 MipmapTexture Filtering & Mipmap纹理在屏幕上被放大时需要插值,被缩小时一个像素覆盖许多纹素,必须预先滤波才能避免混叠。放大用最近邻、双线性或双三次;缩小的主流方案是 mipmap + 三线性插值,斜视角下用各向异性过滤减少过度模糊。注意:过滤纹理值只在输入与着色结果线性相关时等价于过滤最终颜色。图形学GPU 内存、缓冲压缩与多重缓冲GPU Memory, Buffer Compression & Multiple Buffering带宽是稀缺资源。GPU 通过独立显存或统一内存架构 (UMA)、多级缓存与按瓦片存储提高局部性,并用基于瓦片表的无损压缩和快速清除减少渲染目标的带宽(注意:无损压缩只省带宽,不省内存)。颜色缓冲有高彩、真彩、深色三种模式;显示控制器以固定刷新率或 FreeSync/G-sync 自适应同步把颜色缓冲送到显示器;单/双/三缓冲在撕裂、等待与延迟之间取舍。图形学菲涅耳反射Fresnel Reflectance菲涅耳方程描述光在两种物质的平坦界面上反射的比例 F,它取决于入射角和两侧折射率:垂直入射时为材质特有的 F0(特征镜面色),掠射时趋于 1。实时渲染用以 F0 为参数的 Schlick 近似。电介质 F0 低且无色,金属 F0 高且常带色,半导体介于其间;金属度参数化利用了这一点。光从物体内部射向表面时还可能发生全内反射。本页对应 RTR4 9.5 节。游戏数学数值表示与浮点数Numeric Representation & Floating Point游戏引擎里到处是数值,所以要清楚它们在机器中如何存储:二进制和十六进制、补码整数、定点数、IEEE-754 浮点数(量级与精度此消彼长、次正规数、机器 epsilon、ULP),以及多字节值的大小端问题和安全的类型双关 (type punning) 方法。书中一个直观的例子是:用 32 位浮点数记录以秒为单位的游戏时钟,大约 12.14 天后,加 1/30 秒就不再改变它的值。图形学透明渲染与 Alpha 混合Transparency & Alpha Blending本页讲最简单的"视角相关"透明:半透明物体只衰减其后方物体的颜色。z-buffer 每像素只存一个表面,所以透明物体通常要从后往前用 over 运算符混合;顺序无关透明 (OIT) 方法用多遍渲染、逐像素链表或近似公式避免排序,各有内存、性能或准确性代价。预乘 alpha 让过滤、混合和合成更正确高效。图形学渲染方程Rendering Equation渲染方程 (Kajiya, 1986) 把"某点接收到的光就是其他点发出或反射的光"写成递归积分,概括了光从光源出发经任意次反弹到达眼睛的所有路径。反射方程是它的受限特例。离线用辐射度 (Radiosity) 或蒙特卡洛路径追踪求解;实时渲染则靠简化和预计算逼近它(RTR4 第 11 章)。游戏美术线性工作流(Birn)Linear Workflow from Birn第 3 版 Ch8「Working in a Linear Workflow」强调:贴图、表面色、灯光、渲染与合成全程保持数字色值与真实光强的线性对应;美术灯光必须在线性空间思考,否则二次衰减、GI、叠光都会「算对了却看起来错」。图形学着色器中的颜色Color in Shaders在 GLSL 里颜色与空间坐标共用 vec2/vec3/vec4:可用 .rgba / .xyzw / .stpq 或下标访问,并 swizzle 任意重排。mix 在 [0,1] 上混合;HSB(HSV)比 RGB 更直观,还可映到极坐标色轮。图形学着色模型与光源Shading Models & Light Sources着色模型描述物体颜色如何随表面朝向、观察方向和光照变化。光源通过两个参数与着色模型交互:指向光源的方向 \mathbf{l} 和光的颜色 \mathbf{c}{\text{light}}。方向光、点光源、聚光灯的区别就在于这两个量如何随场景变化;距离衰减和方向衰减函数的选择同时影响画面与性能。图形学基于物理的着色Physically Based Shading基于物理的着色从光与物质交互的物理出发,用 BRDF 和反射方程计算表面沿视线方向射出的辐射亮度:镜面项来自微表面理论与菲涅耳反射,漫反射项来自局部次表面散射,布料、波动光学与分层材质再作扩展。本页是 RTR4 第 9 章的总览,并收录该章第 9.13 节的材质混合与材质过滤(镜面抗锯齿)。图形学着色器纹理采样Shader Texture SamplingGPU 把图像存成 sampler2D:一张浮点向量的「表」,坐标连续时硬件做插值。片元里用 texture2D(sampler, uv)(现代 GLSL 为 texture)按归一化 UV 取色。BoS 强调:通道是 [0,1] 连续域、可越界重复、可用噪声扭曲 UV——图像变成可拉伸的「数码软垫」,为后处理与光学玩具式特效铺路。游戏美术Base Color 与反照率制作Base Color & Albedo AuthoringBase Color(MR)/ Diffuse·Albedo(SG)承载物质固有色:电介质为漫反射反照率,金属为镜面反射色(F0)。制作要点是保持正确亮度区间、不要画进光照/阴影/AO(微遮蔽例外),并注意 sRGB 贴图与线性着色的分工。游戏美术Filament 材质模型参数Filament Material Model ParametersGoogle Filament 的 Lit(标准)模型按 Disney/UE/Substance 互通思路设计,用 baseColor、metallic、roughness、reflectance 等参数描述导体与电介质,并叠加 clearCoat、sheen、iridescence、transmission 等层。本页从美术/TA 角度说明含义、合理范围,以及与 UE / Substance 的对照;不做 BRDF 公式展开。游戏美术PBR 材质校验与参考值PBR Validation & Reference Values校验 PBR 贴图先问「是不是金属」,再对照反照率亮度、金属 F0、电介质 F0 的实测区间。本页汇总《The PBR Guide》附录与 Filament Reflectance 表中的生产向数字,并列出常见错误模式。游戏美术数字色彩方案与色彩平衡Color Schemes & Color Balance现以第 3 版 Ch8 为准。 章首是 线性工作流(专页);其后才是混色、色方案、色温与色彩平衡、数字色与 HDR。本页管「怎么设计颜色关系」;编码与显示链 线性工作流(Birn)、显示编码与 sRGB。游戏美术曝光与相机模拟Exposure & Camera Simulation现以第 3 版 Ch6「Cameras and Exposure」为准。 覆盖光圈/景深、快门/运动模糊、感光度与颗粒、摄影曝光(互易律、Zone System、直方图、EV、包围曝光),以及镜头瑕疵匹配。物理灯光(IES)必须配合理曝光才可信。

被这些页面引用3 篇

输入关键词开始搜索

滚轮或双指缩放 · 拖动平移 · 双击放大 / 还原