IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> Gamma校正 -> 正文阅读

[游戏开发]Gamma校正

Gamma校正

目录

  1. Gamma校正
  2. 韦伯定律
  3. 线性工作流
  4. Unity中颜色空间
  5. 资源导出问题

我的铁哥们(一辈子的朋友哈哈)韩世麟老师相当简洁准确易懂的讲解Gamma校正和线性工作流
https://www.bilibili.com/video/BV15t411Y7cf?from=search&seid=2451983306845066261
下面是我根据韩老师的讲授内容做的笔记

为什么需要Gamma校正:

① 人的视觉对光强度的感知是非线性的
在这里插入图片描述
这两条明度条,人眼认为上方的条由黑到白是均匀过渡的,是“感觉”。于是我们规定上方的明度条50%处的灰阶为美术上所谓的“中性灰”。
下方的条,才是物理上真正的亮度(灰阶)均匀过渡。是“科学”。

在这里插入图片描述
也就是说,在科学物理的视角中,下方的条的中点处的光强度是纯白色的50%。上方的条的中点处的光强度(灰阶)是纯白色的21.8%。
在这里插入图片描述

② 数字图像所能采集和回放的灰阶层数有限,需要节省(带宽)
在这里插入图片描述
8位空间下,总共能分配的灰阶只有256阶,也就是说,当亮部(亮度:中性灰到纯白)分配了大于128个灰阶时,能分配给暗部的灰阶就不够了,导致在暗部会出现一部分区域全黑的灰阶断层现象。

举个例子:

在这里插入图片描述

我们将 物理光强线性增加的灰阶物理光强非线性增加但是人眼看着舒服的灰阶 分别作为直角坐标系的x轴和y轴,白色曲线用于将线性的转换为非线性的。俗称非线性转换。
在这里插入图片描述

然后,如果我们做一次Gamma校正,即将原本0.218的物理中灰映射到0.5的美术中灰上,那么就可以得到人眼要的效果。
在这里插入图片描述
在这里插入图片描述

Gamma校正是什么

Y = X ^ Gamma,0<Gamma<1,曲线上拱,图片变亮,Gamma>1,曲线下压,图片变暗。

	注:对图片进行两次Gamma校正,且两次的Gamma值互为倒数,图片亮度不变,输入等于输出。

根据韦伯定律,当所受刺激越大时,需要增加的刺激也要足够大才会让人感觉到明显变化,但是只适用于中等强度的刺激。

当我们要存储颜色信息到磁盘中时,根据韦伯定律,因为人眼对暗比高亮更敏感,所以用gamma<1的指数函数变换使得敏感部分获得更多的数据位。 储存信息时要进行非线性变换(曲线上拱);相反,在将颜色信号还原在屏幕上时,要进行线性转换,曲线下压,以满足人眼的视觉合理性。
在这里插入图片描述
我们目前所使用的真彩格式RGBA32,每个颜色通道只有8位用于记录信息,为了合理使用带宽和存储空间,需要进行非线性转换。目前我们所普遍使用的sRGB颜色空间标准,他的传递函数 gamma值为2.2(2.4)
注:这个2.2的值是根据1996年之前CRT时代人们对CRT亮度和电压的关系得到的。(Maybe?)

线性工作流

一、介绍

在生产的各个环节,正确使用gamma编码及 gamma解码,使得最终得到的颜色数据与最初输入的物理数据一致。
如果是使用 Gamma空间的贴图,在传给着色器前需要从 Gamma空间转到线性空间。
在非线性空间下渲染,颜色叠加等操作时,亮度会过曝
在这里插入图片描述
在这里插入图片描述

二、流程

在这里插入图片描述
用我自己的话来说:(橙色框)
① 首先输入引擎的贴图分两种线性空间Linear Texture 它的Gamma值是1(比如法线,noise,Mask,LightMap等一些不需要RGB值作为颜色信息或者美术用途的贴图,也可以说是由计算机计算产生的纹理贴图,),和传统的非线性sRGB Texture 它的Gamma值是0.45(在输入引擎前做过GammaCorrection,因为在别的创作工具中它们是作为最后的输出结果,需要呈现给人眼看,同时为了符合人眼对真实的感受,同时也为了满足人眼对暗部变化更敏感的特点,详见上文的为什么需要Gamma校正,做过一次先编码Gamma,在解码Gamma的操作,总之为了合理储存信息、满足屏幕的输出合理性加之要使Gamma为1,输出的贴图的Gamma值为0.45)。

② 对Gamma值为0.45的sRGB进行去除Gamma校正的操作,使其Gamma值为1,对Gamma为1的Linear Texture 不做任何操作。然后在shader中进行光照计算。

③ 光照等计算完毕,再次进行Gamma校正(这一步和别的创作工具中是一样的,先编码在解码)。

④输出为符合现实的图像

非橙色框
① 贴图Gamma为.45,没有Remove Gamma Correction,在shader中计算,Gamma被视作1,在经过一视同仁的屏幕解码2.2的压暗操作,最后显示的颜色会偏暗。

Unity中的颜色空间

在这里插入图片描述
在这里插入图片描述
Substance Paint ——>Unity
在这里插入图片描述
PhotoShop ——>Untiy
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
下图是photoshop经过Gamma校正后混合 与 直接混合的结果,Gamma校正后的重叠区域会变暗,而直接混合则会正确显示混合结果
在这里插入图片描述

注:知乎上我觉得赞同的回答,显示器的gamma值是为了能够使得整个系统的输入输出呈线性就好了。 人眼特性+充分利用存储空间的考虑->gamma编码 ; gamma编码+全系统输入为1的考虑->显示器的gamma值取什么。

Linear(无贴图)
在这里插入图片描述

Gamma(无贴图)

在这里插入图片描述
在这里插入图片描述

1、如果unity使用了gamma工作流,那么无论图片是勾选还是不勾选srgb,那么unity是不做任何处理,不做2.2的变线性,也不做处理之后的1/2.2的操作。
2、如果unity使用了linear工作流,那么如果图片选择了srgb模式,那么unity则为其做2.2的降线性处理,然后在输出的时候,自动进行1/2.2的处理。
而如果图片不勾选srgb模式,那么unity不会为其做2.2的降线性,而在处理之后,缺依然保留做1/2.2的操作。那么图片最终会变亮了。
依然原本图片就是srgb空间,在拍摄或者ps中,就已经做了一次1/2.2的操作。而又因为我们没有勾选srgb,所以没有做2.2的降线性,而在最后输出结果,unity自动做了一次1/2.2的操作,所以连续做了两次1/2.2的操作,于是图片变亮了。
3、如何区分一个图片是否要勾选srgb呢?如果是选用unity的gamma工作流,我们够不够选无所谓,因为unity不会为为我们做任何事情。都是按照怎么输入,怎么来的处理。
而如果是线性工作流,那么则需要人为的操作了,则需要人为判断这个图片是否需要勾选srgb。
4、哪些图片需要勾选srgb呢?勾选了srgb实际上给unity暗示了什么?
对于在线性工作流下,也就是unity使用了linear模式,那么对于那些美术给的漫反射贴图,则是直接在ps中绘制的,而在ps中绘制的图片,则是存储为srgb空间的(与美术商量好)。也就是存储在了(1/2.2的空间中)上曲线中。那么此时导入unity之后,就要知道这个图是非线性的图了。那么则要勾选srgb。
而其他的图,比如法线图、mask图、噪声图,程序纹理,都是线性的图,那么为了避免勾选srgb而造成unity帮我们做了一次2.2的操作,所以要明确告诉unity,这个你不需要转线性了,我自己已经是线性的图了。

手动进行Gamma校正
Gamma
在这里插入图片描述

fixed4 frag(v2f i) : SV_Target {
                fixed3 tangentLightDir = normalize(i.lightDir);
                fixed3 tangentViewDir = normalize(i.viewDir);

                fixed4 packedNormal = tex2D(_BumpMap, i.uv0.zw);
                fixed3 tangentNormal;

                tangentNormal = UnpackNormal(packedNormal);
                tangentNormal.xy *= _BumpScale;
                tangentNormal.z = sqrt(1.0 - saturate(dot(tangentNormal.xy, tangentNormal.xy)));

                fixed3 albedo = GammaToLinearSpace(tex2D(_MainTex, i.uv0).rgb * _Color.rgb);

                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;

                fixed3 diffuse = _LightColor0.rgb * albedo * max(0.0, dot(tangentNormal, tangentLightDir));

                fixed3 halfDir = normalize(tangentLightDir + tangentViewDir);
                fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0.0, dot(tangentNormal, halfDir)), _Gloss);

                fixed3 col = LinearToGammaSpace((ambient + diffuse + specular).rgb * unity_ColorSpaceDouble) ;

                return fixed4(col, 1.0);
            }

经过上面代码的调整,先变暗再提亮,似乎与Gamma校正的流程相反了,是为什么呢,我觉得我还是一知半解而已,希望有好兄弟或者大佬解惑。unity_ColorSpaceDouble作用是根据所处空间(Gamma 为 2异或Linear 为 0.4左右)提供一个值,提亮混合后的颜色。Gamma空间下的Linear效果如下:
在这里插入图片描述
遇到的一些问题:GammaToLinearSpace()和LinearToGammaSpace()两个方程容易搞混,我去找了一下UnityCG.cginc,如下

inline float GammaToLinearSpaceExact (float value)
{
    if (value <= 0.04045F)
        return value / 12.92F;
    else if (value < 1.0F)
        return pow((value + 0.055F)/1.055F, 2.4F);
    else
        return pow(value, 2.2F);//看灰色的return,调用的GammaToLinearSpaceExact ,rgb大于1时,pow 2.2曲线下压变暗
}

inline half3 GammaToLinearSpace (half3 sRGB)
{
  
    return sRGB * (sRGB * (sRGB * 0.305306011h + 0.682171111h) + 0.012522878h);

    // Precise version, useful for debugging.
    //return half3(GammaToLinearSpaceExact(sRGB.r), GammaToLinearSpaceExact(sRGB.g), GammaToLinearSpaceExact(sRGB.b));
}

inline float LinearToGammaSpaceExact (float value)
{
    if (value <= 0.0F)
        return 0.0F;
    else if (value <= 0.0031308F)
        return 12.92F * value;
    else if (value < 1.0F)
        return 1.055F * pow(value, 0.4166667F) - 0.055F;
    else
        return pow(value, 0.45454545F); //pow 1/2.2,曲线上突变亮
}

inline half3 LinearToGammaSpace (half3 linRGB)
{
    linRGB = max(linRGB, half3(0.h, 0.h, 0.h));
    return max(1.055h * pow(linRGB, 0.416666667h) - 0.055h, 0.h);

    // Exact version, useful for debugging.
    //return half3(LinearToGammaSpaceExact(linRGB.r), LinearToGammaSpaceExact(linRGB.g), LinearToGammaSpaceExact(linRGB.b));
}

先于此搁笔,夜深了,凌晨3点了。

参考文章链接:
https://blog.csdn.net/wodownload2/article/details/105124113/
https://blog.csdn.net/candycat1992/article/details/46228771
https://zhuanlan.zhihu.com/p/36507196
给自己留个档
https://zhuanlan.zhihu.com/p/66558476里面是整个校正流程,快去看(对自己说的

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2021-07-22 23:06:05  更:2021-07-22 23:06:13 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/20 13:15:45-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码