颜色工作流程

线性和非线性伽马色彩空间

sRGB 色彩空间的目的是表示在计算机显示器上显示的颜色。目前,sRGB 是非线性伽马色彩空间的标准。之所以需要它,是因为人类对光的感知是非线性的,而计算机显示器对光强度的响应也是非线性的。

人眼对较暗色调的区分能力优于较亮色调。因此,在屏幕上存储和显示图像时,为深色强度保留更多的准确性是有意义的。非线性伽马色彩空间通过伽马校正实现这一点,它通过幂函数处理图像中每个像素的强度:

\[I^{\gamma}\]

图像通常以应用了编码伽马的方式存储,屏幕则应用解码伽马。此图像显示了 Kanzi 用于在线性和伽马色彩空间之间转换的伽马传递函数图。

../../_images/gamma.svg

此图像显示了一个渐变,其中屏幕发出的光的强度线性增加。

../../_images/linear_emitted_intensity.png

将解码伽马应用于上述渐变会产生此渐变,其中感知光强度线性增加。

../../_images/linear_perceptual_intensity.png

非线性伽马色彩空间的问题在于其不适合图形操作。在非线性空间中进行颜色计算会导致颜色和 alpha 混合结果不准确。线性色彩空间对于数学上正确的光照和颜色混合计算是必需的。

在线性色彩空间中,数值强度值对应于其实际强度,这使得可以正确地添加和乘以颜色值。线性色彩空间渲染提供了更准确的结果和更真实的表面阴影,特别是在使用基于物理的渲染技术时。

这些图像显示了在非线性伽马(左)和线性(右)色彩空间中混合的示例。在非线性伽马色彩空间中混合会导致过亮的混合和饱和的色带。

../../_images/legacy-blending.png ../../_images/linear-blending.png

Kanzi 默认使用非线性伽马颜色工作流(即标准颜色工作流),在该工作流中,Kanzi 在伽马颜色空间中对颜色值进行运算。请参阅 使用标准颜色工作流。

Kanzi 还支持线性颜色工作流,在该工作流中,Kanzi 在线性颜色空间中对颜色值进行运算。请参阅 使用线性颜色工作流 和 将应用程序从标准颜色工作流转换为线性颜色工作流。

使用线性颜色工作流

在线性颜色工作流中,Kanzi 可实现逼真的光照计算和正确的颜色混合。为了准确渲染颜色和光照,Kanzi 会先将所有颜色值转换到线性颜色空间,再对其进行运算。然后,Kanzi 将颜色值转换回伽马颜色空间以进行存储或显示。

图像 (Images)

要在您的 Kanzi Studio 项目中配置图像以进行线性色彩工作流程:

  • 在 Library > Resource Files > Images 中,为每个使用 ASTC、ETC2、JPEG 或 PNG 格式的图像资源设置 sRGB Content 属性的值:

    • 如果图像包含 sRGB 颜色信息,请将 sRGB Content 属性设置为启用。这是默认设置。

      如果您禁用包含 sRGB 颜色信息的图像的 sRGB Content 属性,Kanzi 渲染使用该图像的纹理时可能会比预期更亮。

    • 如果图像包含非颜色信息,例如法线、粗糙度或遮挡贴图,请将 sRGB Content 属性设置为禁用。

      包含非颜色信息的纹理以线性格式存储。通过禁用 sRGB Content 属性,您将 Kanzi 设置为直接将图像数据传递给着色器,而不执行颜色空间转换。

    ../../_images/srgb-content.png
  • 默认情况下,Kanzi 在线性色彩空间中预乘图像的 alpha 通道。要在图像的色彩空间中预乘 alpha 通道,请在 Library > Resource Files > Images 中选择一个图像,并在 Properties 中禁用 Linear Premultiply 属性。请参阅 在第三方工具中准备图像。

    ../../_images/linear-premultiply.png

颜色属性绑定

要在线性色彩工作流中的绑定表达式中设置颜色值:

  • 在 sRGB 色彩空间中指定 Color4 值。请参阅 color4。

    例如:

    Color4(0, 0.75, 0.25, 1)
    
    ../../_images/r0g192b64.png
  • 在线性色彩空间中指定各个 RGB 色彩通道的值。

    使用 sRGBToLinear 绑定函数将颜色通道值转换为线性颜色空间。

    例如:

    • 此绑定表达式等于 Color4(0, 0.75, 0.25, 1):

      color = Color4(0, 0, 0, 1)
      color.g = sRGBToLinear(0.75)
      color.b = sRGBToLinear(0.25)
      color
      
      ../../_images/r0g192b64.png
    • 此绑定表达式等于 Color4(0, 0.879, 0.535, 1):

      color = Color4(0, 0, 0, 1)
      color.g = 0.75
      color.b = 0.25
      color
      
      ../../_images/r0g225b137.png

着色器 (Shaders)

在线性色彩工作流程中,着色器期望颜色输入为线性色彩空间,并在输出时也是线性色彩空间。为了在以每通道8位的纹理格式中存储颜色值时保持准确性,Kanzi 在存储之前将颜色值转换回 sRGB 色彩空间。

Graphics API

线性颜色工作流需要以下条件之一:

  • EGL 1.5 或更高版本,或者带有 EGL_KHR_gl_colorspace 扩展的 EGL 1.4 版本。

  • Vulkan 1.1 或更高版本。

使用标准颜色工作流

默认情况下,Kanzi 使用标准颜色工作流。该工作流在非线性伽马颜色空间中对颜色值进行运算,其渲染结果的精度低于线性颜色工作流。

在以下情况下使用标准颜色工作流:

  • 将您的应用程序部署到不支持线性色彩空间的设备。

    要支持线性颜色空间,您的目标平台必须实现 EGL 1.5 或更高版本、带有 EGL_KHR_gl_colorspace 扩展的 EGL 1.4 版本,或者 Vulkan 1.1 或更高版本。

    当您的 Kanzi 应用程序请求线性色彩空间但目标设备不支持时,结果行为在不同的目标平台之间会有所不同。

    例如,您的应用程序可以:

    • 在日志中打印有关不支持 EGL_GL_COLORSPACE 的警告,并回退到传统色彩空间。

    • 以此错误终止:

      eglCreateWindowSurface() failed: EGL_BAD_ATTRIBUTE
      
  • 将项目从较早版本的 Kanzi 迁移。

在标准颜色工作流中,Kanzi 不会转换颜色输入。如果您使用 Kanzi Engine API 创建 ColorRGBA 对象,请提供 sRGB 颜色空间中的颜色值。

要使用标准颜色工作流:

  1. 通过设置以下任一项,将您的应用程序配置为使用未指定的颜色空间:

    • 在 application.cfg:

      SurfaceColorSpace = "standard"
      
    • 在 C++ 应用程序中的 Application::onConfigure 函数中:

      configuration.defaultSurfaceProperties.colorSpace = "standard";
      

    请参阅 SurfaceColorSpace。

  2. 在 Kanzi Studio 的 Project > Properties 中,将 Color Workflow 属性设置为 Standard。

    ../../_images/project-properties.png ../../_images/color-workflow-legacy.png
  3. 编写着色器以在目标显示器的伽马空间中输出颜色,这很可能是 sRGB。请参阅 着色器 (Shaders)。

将应用程序从标准颜色工作流转换为线性颜色工作流

要将您的应用程序从标准颜色工作流转换为线性颜色工作流:

  1. 通过配置线性颜色工作流,将您的应用程序配置为使用 sRGB 颜色空间:

    • 在 application.cfg:

      SurfaceColorSpace = "srgb"
      
    • 在 C++ 应用程序中的 Application::onConfigure 函数中:

      configuration.defaultSurfaceProperties.colorSpace = "srgb";
      

    请参阅 SurfaceColorSpace。

  2. 在 Kanzi Studio 的 Project > Properties 中,将 Color Workflow 设置为 Linear。

    ../../_images/project-properties.png ../../_images/color-workflow-linear.png
  3. 在 Library > Materials and Textures > Material Types 中,对于每种材料类型,确保将:

    • 绑定不包含不必要的手动添加的 sRGB 转换。

      例如,您不需要使用 linearTosRGB 绑定函数将颜色值从线性色彩空间转换为 sRGB 色彩空间。在线性色彩工作流中,着色器期望颜色输入为线性色彩空间。

    • 着色器在输入或输出时不应用伽马校正。

      在线性色彩工作流程中,着色器期望颜色输入为线性色彩空间,并且它们输出的颜色也在线性色彩空间中。

  4. 在 Library > Resource Files > Images 中,检查每个使用 ASTC、ETC2、JPEG 或 PNG 格式的图像资源是否正确设置了 sRGB Content 属性:

    • 如果图像包含 sRGB 颜色信息,请将 sRGB Content 属性设置为启用。这是默认设置。

      如果您禁用包含 sRGB 颜色信息的图像的 sRGB Content 属性,Kanzi 渲染使用该图像的纹理时可能会比预期更亮。

    • 如果图像包含非颜色信息,例如法线、粗糙度或遮挡贴图,请将 sRGB Content 属性设置为禁用。

      包含非颜色信息的纹理以线性格式存储。通过禁用 sRGB Content 属性,您将 Kanzi 设置为直接将图像数据传递给着色器,而不执行颜色空间转换。

    ../../_images/srgb-content.png
  5. 要获得所需的颜色混合效果,请在项目中根据需要调整部分透明的颜色。

    例如,使用这些颜色笔刷填充的节点在标准颜色工作流模式和线性颜色工作流模式下看起来不同:

    ../../_images/red-green-blue-brushes.png

    Standard 颜色工作流

    Linear 颜色工作流程

    ../../_images/color-brush-blending-legacy.png ../../_images/color-brush-blending-linear.png

另请参阅

应用程序开发

材质类型和材质

着色器 (Shaders)

图像 (Images)

纹理 (Textures)

Bindings expressions 参考