【Unity3D日常开发】Unity3D的Color Space(颜色空间)【全解析】

推荐阅读

大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。

一、前言

Edit→Player Settings→Other Settings→Rendering→Color Space(颜色空间)

先放一张图感受一下:
在这里插入图片描述
在Unity打包选项中,有一个Color Space的选项,有GammaLinear两个选项。

主要作用是设置Unity是否对输入的默认贴图进行转换处理,法线贴图不存在这个问题。

Gamma时,Unity不会在后台将图片进行转换,输入的即使是经过矫正的图片,Unity也不会处理,比如Remove Gamma Correction去除伽马校正Gamma Correction伽马校正都不会发生,除非自己手动实现。

Linear时,Unity就会进行统一线性空间的流程,也就是Gamma Correction,对于sRGB纹理,Unity 会利用GPU对图片进行采样,剔除矫正Remove Gamma Correction,转换到线性空间,然后再传给Shader处理,处理后的图片会再加上Gamma矫正,再显示在屏幕上。

简而言之就是Gamma不会对输入和输出进行处理,Linear会对sRGB纹理进行剔除矫正,转换到线性空间,再传给Shader处理

那接下来,我们就来了解一下Gamma和Linear的原理,以及支持Linear颜色空间的纹理类型,还有支持线性空间的硬件和特性。

二、正文

2-1、纹理与Linear

Unity在导入贴图的导入设置面板中sRGB(Color Texture)选项,勾选它,告诉Unity这是一张sRGB贴图,需要对sRGB编码才可以获得用于光照计算的数据,不勾选,表示这是一张线性贴图,这张贴图的颜色数据可直接用于光照计算。

当然,除了sRGB(Color Texture)选项,其他的类型,比如Normal Map、Light Map都是Linear,设置好类型Unity自己会处理它们。
在这里插入图片描述
在这里插入图片描述

那什么时候才会用到sRGB贴图呢?

比如在导出贴图时,会对提供色彩信息的贴图,比如Albedo和Specular Color做sRGB编码,这样做的目的是为了让贴图看起来更舒服,更符合人眼感知的方式。

所以,这种情况就可以导出sRBG贴图来使用。但是对于法线贴图、金属度贴图这类用于存储数值信息的贴图,是不做sRBG编码的,所以就当线性贴图来使用。

2-2、什么是sRGB

上述说的解码Gamma只是理想状态下机制。

然而每一台显示器的解码值Gamma值并不统一,会导致同一张图片再不同的显示器上看起来不一样。

解决方案是引入Color Profile(色彩配置文件),也就是RGB数值与颜色波长之间的对应关系。

图片都再带有一个Color Profile,显示器收到这个文件后,根据显示器自己的Color Profile后转换为屏幕输出该特定波长所需的RGB值。

也就是说Color Profile既有波长这个量值,也有Gamma矫正。

sRGB是一种最常见的Color Profile,是微软联合惠普等厂商联合制定的色彩标准。

sRGB色彩空间就是Gamma色彩空间。

2-3、硬件特性支持

主要由两个硬件特性来支持:

sRGB Frame Buffer

  • 将Shader的计算结果输出到显示器前左gamma校正
  • 作为纹理被读取时会自动把存储的颜色从sRGB空间转换到线性空间
  • 调用ReadPixels()、readBackImage()时,会直接返回sRGB空间下的颜色
  • sRGB Frame Buffer只支持每通道8bit的格式,不支持浮点格式
  • HDR开启后会先把渲染结果绘制到浮点格式的FB中,最后绘制到sRGB FB上输出
    sRGB Sampler
  • 将sRGB的贴图进行线性采样的转换
  • 使用硬件特性完成sRGB贴图的线性采样和shader计算结果的gamma校正,比起在shader里对贴图采样和计算结果的校正要快。

2-4、线性空间 Linear Space

在现实世界中,光的强度增加一倍,那么亮度也会增加一倍,这是线性关系。

为了保证数学上准确,光照计算应该在线性空间执行,意即sRGB格式的输入值需要先做sRGB解码——在贴图的导入设置面板中有**sRGB(Color Texture)**选项。

如果勾选开启sRGB,那么在采样时会自动对采样得到的值进行sRGB解码

此外还设置有一个sRGB格式的buffer,GPU会在shader写入color buffer前自动进行sRGB编码

这里用到了两个底层图形API:sRGB SamplersRGB Frame Buffer
在这里插入图片描述

(如果unity使用Gamma颜色空间,sRGB的设置是无效的,因为贴图总是会被线性采样。)

sRGB (Color Texture)设置的意义:这应该总是检查非hdr颜色纹理(如反照率和高光颜色)。如果纹理存储具有特定含义的信息,并且您需要在着色器中获得准确的值(例如,平滑度或金属),请取消选中此框。默认情况下选中此框。

实际在unity 中取消勾选sRGB后图片会变亮,我觉得实际可能是下面这样:(不勾选sRGB的图片会被编码为sRGB格式)

在这里插入图片描述
sRGB只对RGB通道有效,对alpha通道无效

alpha值不参与任何编码gamma、解码gamma的计算,它直接进入shader,被shader读取;

以MetallicSmoothness贴图为例,存储在Alpha通道的Smoothness,本来就是线性的,不论贴图勾不勾选sRGB,都不会影响它,shader能正确读取它的值。

2-5、Gamma和Linear的优缺点

Linear线性色彩空间

Linear线性色彩空间是一种更接近显示光线传播的标识方式,使用线性关系来处理颜色。

在Linerar线性色彩空间中,颜色值的变化更加准确和自然,能够实现更真实世界的光照效果。

Gamma伽马色彩空间

Gamma伽马色彩空间是一种更符合人眼感知的方式,使用非线性关系来处理颜色。

在Gamma伽马色彩空间中,颜色值的变化更加符合人眼的感知特性,能够更好地呈现对比度和亮度等方面的内容。

总结一下

对于需要更真实光照效果的项目,使用Linear线性色彩空间会更合适。默认颜色空间是Gamma伽马色彩空间。

所有需要人眼参与被创作出来的纹理,都应是sRGB(如美术画出来的图)。

所有通过计算机计算出来的纹理(如噪声,Mask,LightMap)都应是Linear。

这很好解释,人眼看东西才需要考虑显示特性和校正的问题。

而对计算机来说不需要,在计算机看来只是普通数据,自然直接选择Linear是最好的。

三、后记

如果觉得本篇文章有用别忘了点个关注,关注不迷路,持续分享更多Unity干货文章。


你的点赞就是对博主的支持,有问题记得留言:

博主主页有联系方式。

博主还有跟多宝藏文章等待你的发掘哦:

专栏 方向 简介
Unity3D开发小游戏 小游戏开发教程 分享一些使用Unity3D引擎开发的小游戏,分享一些制作小游戏的教程。
Unity3D从入门到进阶 入门 从自学Unity中获取灵感,总结从零开始学习Unity的路线,有C#和Unity的知识。
Unity3D之UGUI UGUI Unity的UI系统UGUI全解析,从UGUI的基础控件开始讲起,然后将UGUI的原理,UGUI的使用全面教学。
Unity3D之读取数据 文件读取 使用Unity3D读取txt文档、json文档、xml文档、csv文档、Excel文档。
Unity3D之数据集合 数据集合 数组集合:数组、List、字典、堆栈、链表等数据集合知识分享。
Unity3D之VR/AR(虚拟仿真)开发 虚拟仿真 总结博主工作常见的虚拟仿真需求进行案例讲解。
Unity3D之插件 插件 主要分享在Unity开发中用到的一些插件使用方法,插件介绍等
Unity3D之日常开发 日常记录 主要是博主日常开发中用到的,用到的方法技巧,开发思路,代码分享等
Unity3D之日常BUG 日常记录 记录在使用Unity3D编辑器开发项目过程中,遇到的BUG和坑,让后来人可以有些参考。

猜你喜欢

转载自blog.csdn.net/q764424567/article/details/133927994