1 伽马相关概念

1.1 人眼对亮度变化的感知

​ 人眼对亮度变化的感知不是线性的,如下图,人眼对亮区的亮度变化不太敏感,对暗区的亮度变化较敏感。另外,我们可以想象一下,在一个黑暗的房间里,由 1 根蜡烛到 2 根蜡烛的变化,我们很容易感知到,但是由 100 根蜡烛到 101 根蜡烛的变化,我们就不容易感知到。因此,对于固定的存储空间,我们应该给暗区分配更多的存储空间,而给亮区少分配些空间,这样能让更多的细节在暗区呈现,而亮区不必呈现太多细节(因为人眼感知不到亮区的细微变化,呈现太多细节只会浪费空间)。

1.2 伽马编码和伽马解码

1)伽马函数

​ 伽马函数公式如下,因其指数部分 γ 读音为伽马(gamma)而来。

​ 当 0 < γ < 1 时,伽马函数的图像从左往右逐渐平缓,通常作为伽马编码处理;当 γ > 1 时,伽马函数的图像从左往右逐渐陡峭,通常作为伽马解码处理。如下是 γ 值为 0.45 和 2.2 的函数图像。

2)伽马函数在图像捕捉****和显示中的应用

​ 一般情况下,一个像素使用 8 位存储,可以表示 256 种颜色。为了尽可能线性化人眼感知的亮度变化(人眼对暗区的亮度变化更敏感,需要使用更多的存储空间,对亮区的亮度变化不太敏感,可以少分配些空间),对相机采集到的图像进行伽马编码处理后,再存入 jpeg 等格式图片文件中,在读取图片文件时,通过伽马解码处理后再显示,如下图所示。

​ 在早期,CRT(Cathode Ray Tube,阴极射线管)几乎是唯一的显示设备,它有一个特性,输入电压和显示亮度不是线性关系,而是伽马函数关系,并且其 γ 值刚好是伽马编码函数的 γ 值的倒数,这正好补偿了图像捕捉设备的伽马编码造成的亮度非线性问题。因此,显示设备只需要输入线性变化的电压,就可以还原线性变化的亮度,而不需要进行伽马解码处理。现在 CRT 设备很少见了,并且后来的显示设备有着不同的伽马曲线(γ 值不同),但人们仍在硬件上做了调整来提供兼容性。

​ 注意:透明通道不参与伽马编码和伽马解码。

3)sRGB 颜色标准

​ 微软联合爱普生、惠普制定了 sRGB 颜色空间标准,推荐相机的伽马编码函数的 γ 值为 0.45,显示器的伽马解码函数的 γ 值为 2.2(因为 2.2 × 0.45 ≈ 1)。绝大多数的摄像机、PC 和打印机都使用了 sRGB 标准。

1.3 颜色空间

​ Unity 中材质渲染的颜色空间分为伽马空间(默认)和线性空间,如下。

​ 伽马空间中,Unity 不会对 Shader 的输入和输出进行任何处理,因此,输入的像素可能是非线性的,输出的像素经过显示器的伽马解码处理后可能会得到非预期的亮度,通常表现为场景整体变暗。

​ 线性空间中,Unity 会把输入纹理设置为 sRGB 模式,在该模式下,硬件在对纹理进行采样时会自动进行伽马解码,在 Shader 写入颜色缓冲前自动进行伽马编码(HDR 除外)。

​ 用户可以在【Edit→Project Settings→Player→Other Settings→Rendering→Color Space】中设置颜色空间,如下。

2 伽马对亮度和混合的影响

​ 当颜色空间使用默认在伽马空间时,如果不进行伽马矫正,可能会出现场景整体偏暗、混合异常等问题。本节实验完整资源见→Unity3D伽马校正对比实验

2.1 伽马对亮度的影响

​ 新建一个场景,调整相机位置和旋转角度分别为 (0, 0, -1.5)、(0, 0, 0),调整直射光旋转角度为 (45, -90, 0),使得直射光从右上角 45° 射向左下角;新建一个 Sphere,调整其位置为 (0, 0, 0),新建一个材质,重命名为 DiffuseMat,设置其 Shader 为【Legacy Shaders / Diffuse】,将该材质拖拽给 Sphere;设置环境光为全黑(在【Window→Rendering→Lighting→Environment→Ambient Color】中设置),使得渲染只受漫反射影响。伽马空间和线性空间中 Sphere 渲染如下。

​ 由于球体的渲染只受漫反射影响,并且直射光从右上角 45° 射向左下角,因此右边的渲染才更符合要求。另外,左侧图像相比右侧图像,整体偏暗一些。

2.2 伽马对混合的影响

​ 新建一个场景,创建 3 个 Quad 和 3 个材质,将这些材质分别拖拽到 3 个 Quad 中,将以下 Shader 绑定到这些材质中,将边缘渐变的圆形图片拖拽到 3 个材质中,调整 3 个材质的颜色分别为红、绿、蓝。

​ SimpleBlend.shader

Shader "MyShader/SimpleBlend" {
Properties {
_MainTex ("Main Tex", 2D) = "white" {}
_Color ("Color Tint", Color) = (1, 1, 1, 1)
} SubShader {
Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"} Pass {
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha CGPROGRAM #include "UnityCG.cginc" #pragma vertex vert_img
#pragma fragment frag sampler2D _MainTex;
fixed4 _Color; fixed4 frag(v2f_img i) : SV_Target {
return fixed4(_Color.rgb, tex2D(_MainTex, i.uv).a);
} ENDCG
}
} FallBack "Transparent/VertexLit"
}

​ 伽马空间和线性空间中 3 个 Quad 的渲染如下。

​ 左侧图片边缘较硬,右侧图片边缘较柔和,更符合实际情况。

3 伽马校正策略

​ 在线性空间下,系统自动进行了伽马校正;在伽马空间下,需要用户手动校正。另外,Unity 的线性空间并不是所有平台都支持,如:移动平台就无法使用线性空间。

​ 对非线性的输入纹理,进行伽马解码校正如下:

float3 tex = pow(tex2D(_Tex, i.uv).rgb, 2.2);

​ 在片元着色器输出前,进行伽马编码校正如下:

fragColor.rgb = pow(fragColor.rgb, 0.45);
return fragColor;

​ 注意:当场景中存在半透明物体时,上述校正会导致混合在非线性空间中进行,影响混合效果,一种有效的解决方法是:将伽马编码校正放在屏幕后处理中进行。

​ 声明:本文转自【Unity3D】伽马校正

【Unity3D】伽马校正的更多相关文章

  1. 【图形学】我理解的伽马校正(Gamma Correction)

    http://blog.csdn.net/candycat1992/article/details/46228771/ 写在前面 我相信几乎所有做图像处理方面的人都听过伽马校正(Gamma Corre ...

  2. 【视频开发】伽马校正(gamma correction)学习笔记

    我相信几乎所有做图像处理方面的人都听过伽马校正(Gamma Correction)这一个名词,但真正明白它是什么.为什么要有它.以及怎么用它的人其实不多.我也不例外.  最初我查过一些资料,但很多文章 ...

  3. 图像处理gamma修正(伽马γ校正)的原理和实现算法

    ☞ ░ 前往老猿Python博文目录 ░ 本文转自博客园:淇淇宝贝的文章<图像处理之gamma校正>,原文链接:https://www.cnblogs.com/qiqibaby/p/532 ...

  4. 伽马变换(一些基本的灰度变换函数)基本原理及Python实现

    1. 基本原理 变换形式 $$s=cr^{\gamma}$$ c与$\gamma$均为常数 可通过调整$\gamma$来调整该变换,最常用于伽马校正与对比度增强 2. 测试结果 图源自skimage ...

  5. 图像增强算法(直方图均衡化、拉普拉斯、Log、伽马变换)

    一.图像增强算法原理 图像增强算法常见于对图像的亮度.对比度.饱和度.色调等进行调节,增加其清晰度,减少噪点等.图像增强往往经过多个算法的组合,完成上述功能,比如图像去燥等同于低通滤波器,增加清晰度则 ...

  6. 基础图像处理之混合空间增强——(Java:拉普拉斯锐化、Sobel边缘检测、均值滤波、伽马变换)

    相信看过冈萨雷斯第三版数字图像处理的童鞋都知道,里面涉及到了很多的基础图像处理的算法,今天,就专门借用其中一个混合空间增强的案例,来将常见的几种图像处理算法集合起来,看能发生什么样的化学反应 首先,通 ...

  7. C++数字图像处理(1)-伽马变换

    https://blog.csdn.net/huqiang_823/article/details/80767019 1.算法原理    伽马变换(幂律变换)是常用的灰度变换,是一种简单的图像增强算法 ...

  8. 对比度增强(二):直方图正规划与伽马变换 cv.normal()函数使用及原理

    直方图正规化: 图像为I,宽为W,高为H,I(r,c)代表I的第r行第c列的灰度值:输出图像记为O,为使得输出图像的灰度值在[Omin,Omax]范围里,可用如下公式:                 ...

  9. OpenCV计算机视觉学习(3)——图像灰度线性变换与非线性变换(对数变换,伽马变换)

    如果需要处理的原图及代码,请移步小编的GitHub地址 传送门:请点击我 如果点击有误:https://github.com/LeBron-Jian/ComputerVisionPractice 下面 ...

  10. Gamma correction 伽马校准及 matlab 实现

    matlab 内置实现:imadjust Gamma Correction gamma correction formula : .^(gamma) or .^(1/gamma)? 用以调整图像光照强 ...

随机推荐

  1. C++模板显示指定类型时使用引用遇到的问题

    1.问题 这里我想让模板函数接收int和char类型的参数,并进行相加,显示指定参数类型为int. 第一个调用理论上会自动将char类型强转成int类型,后进行相加: 第二个调用理论上会自动将int类 ...

  2. CentOS7挂载webdav添加开机启动

    CentOS7挂载webdav添加开机启动 一.安装davfs2 yum install davfs2 二.挂载 1.新建挂载位置 mkdir -p /guazai chmod +x /guazai ...

  3. [转帖]十分钟掌握 Vim 编辑器核心功能

    https://juejin.cn/post/6929248764746006535 前言 相信不论是前端还是后台多多少少都需要上到服务器上做一些操作,改改配置文件等,大多数 Linux 服务器默认都 ...

  4. [转帖]如何监控Redis性能指标(译)

    Redis给人的印象是简单.很快,但是不代表它不需要关注它的性能指标,此文简单地介绍了一部分Redis性能指标.翻译过程中加入了自己延伸的一些疑问信息,仍然还有一些东西没有完全弄明白.原文中Metri ...

  5. [转帖]RHEL/CentOS 7的systemd target及其中的multi-user.target

    在RHEL/CentOS 6中,使用SysV init和Upstart,通过预定义一组Runlevels(从0到6)表示不同的执行模式. [root@myhost app]# ll /etc/rc.d ...

  6. [转帖]Redis命令详解:Keys

    https://jackeyzhe.github.io/2018/09/22/Redis%E5%91%BD%E4%BB%A4%E8%AF%A6%E8%A7%A3%EF%BC%9AKeys/ 介绍完Re ...

  7. [转帖]深度解读:传奇的Alpha处理器

    https://jishuin.proginn.com/p/763bfbd2cf85 来源:科技新报(台) 长期关心处理器技术发展者,这20年来,很难不每隔一段时间就会偶尔听到「这技术受Alpha影响 ...

  8. Systemd设置ulimit的方式与方法

    Systemd设置ulimit的方式与方法 摘要 Linux安装完成之后前面几件事情一般是处理selinux 以及处理ulimit 其实处理文件打开数有多种方法,之前也总结过, 但是最近因为syste ...

  9. JDK内嵌指令的简单学习

    java 可以使用 java -jar的方式启动服务 日常工作中用到的比较少 javac 可以将.java 文件编译成 .class中间代码 这个工具开发编写代码中是经常需要使用的, jenkins ...

  10. React中css的module

    处理css全局作用 现在有这样一个场景: A页面和B页面都有一个相同的类名 我们在A页面中有引入css. B页面没有css 在我们切换A和B页面的时候. A页面的css也作用在了B页面. 我们只希望A ...