Gama Space 和 Linear Space 学习
可以参考:
1.http://blog.csdn.net/ngrandmarch/article/details/46407017
2.http://blog.csdn.net/candycat1992/article/details/46228771
关键是文2,但文2许多东西都只是“作者知道,读者不知道,但作者以为读者知道”,文1可以辅助理解。
首先文1的内容应该是正确的,我再加几点帮助在文1的基础上理解文2提到的几个观点。
0.线性纹理输出屏幕上,因为colorbuffer到屏幕的影响(硬件),得到的颜色会是(0-1)^2.2.
1.sRGB格式意思是0-1映射到(0-1)^(1/2.2)=(0-1)^0.45,也就是说sRGB格式的图片是非线性纹理。
2.如果sRGB格式的纹理不经过色值缩放直接经过shader输出到colorbuffer,因为colorbuffer到屏幕上需要进行col^(2.2),所以屏幕上刚好是原来的颜色。
3.但是,如果sRGB格式的纹理的色值在shader里进行了缩放,比如文2中的颜色混合,那输出到屏幕的结果是:((0-1)^0.45 * scale)^2.2,这个显然是错误的,毕竟我们想要的是(0-1)*scale。
4.采用sRGB格式的本质原因是颜色的精度太低,而人的眼睛对暗部分变化比较敏感,所以需要让更多的精度来表示暗的部分,所以搞了个0.45次方映射:(0-1)=>((0-1)^0.45),后者的范围依然是(0-1)只是更多位数来表示暗的部分了:0.18^0.45=0.5=>有一半精度表示0-0.18之间的亮度,一半表示0.18-1之间的亮度。
下面看unity的gama space 和 linear space:
5.但是,unity的linear space帮我们做了一些处理:对输入纹理先进行^2.2变换到线性空间,然后进行shader处理,当输出到colorbuffer时再^0.45回归sRGB格式即gama空间,这样shader里的缩放等处理都是对原色值进行线性处理了。但是呢,这里默认了输入纹理是sRGB,如果你的输入是线性的,那就直接出错了!,可以通过勾选纹理设置的bypass srgb sample来越过^2.2和^0.45的空间转换处理,现在Unity默认都把图片搞成sRGB格式,所以linear space是正确的显示。
6.unity的gamma space没有做任何事情,即没有做输入转换到线性空间和输出转回gamma空间,这个时候,对于线性纹理,输出会是((0-1)*scale)^2.2,对于sRGB格式:((0-1)^0.45 * scale)^2.2,都特么是错的。前者很容易矫正,但sRGB格式可以更好的表现暗域,这估计也是unity默认转成sRGB格式的原因。
7.unity默认对纹理都搞成sRGB格式(通过勾选纹理设置的bypass srgb sample课可以搞成线性的),并且在PC上可以选择linear space,手机上只能选择gama space,这意味着我们的手游需要gama矫正:
在采样时先转线性空间:
float3 diffuseCol = pow(tex2D( diffTex, texCoord ), 2.2 );
然后在输出时再转gama 空间:
fragColor.rgb = pow(fragColor.rgb, 1.0/2.2);return fragColor;,
但是但是,因为片段着色器的结果并不是直接写得colorbuffer里面的,所以我们做的线性空间转回gama空间做早了,这有可能会出问题!因为gama 矫正的正确操作是(unity linear space做的):
一切工作都是为了“保证所有的输入都转换到线性空间,并在线性空间下做各种光照计算,最后的输出(最最最最后的输出)进行伽马校正后再显示”。这个最后的输出是colorbuffer。
但事实上,即使我们不进行gama矫正也没什么,因为我们的shader又不是万能的,调整各种参数满足表现就好了嘛,又不是动态变化的。不过如果你的shader的亮度看起来不如意,有可能是没进行gama矫正导致的,知道就好。
8.存疑:
1.所谓sRGB格式是存储的格式还是读到GPU里的格式?按说unity不会直接改导入图片的信息,那应该是GPU读原始纹理后进行处理的格式了,但没看到文档不敢揣测。
答:unity不会改导入图片的信息,但图片被导入后会根据设置在Library目录生成一个对应的文件,给游戏使用,所以sRGB就是存储的格式。
2.许多游戏场景因为没有gama矫正而变暗,为什么?
答:其实这点我没查到原理,仅根据公式推:因为当scale在0-1之间时,scale^2.2比scale小,所以偏暗。
Gama Space 和 Linear Space 学习的更多相关文章
- User space 与 Kernel space
学习 Linux 时,经常可以看到两个词:User space(用户空间)和 Kernel space(内核空间). 简单说,Kernel space 是 Linux 内核的运行空间,User spa ...
- Kernel Space与User Space(转)
对于刚刚接触Linux的菜鸟来说,可能会不理解大家常说的Kernel Space和User Space是什么意思,我简单搜了一下,发现阮一峰写过一个比较简洁的介绍,贴下来给大家: 学习 Linux 时 ...
- 关于sed中的Pattern Space和Hold Space的随笔
首先是一部分概念和示例,这部分转自:http://coolshell.cn/articles/9104.html Pattern Space 第零个是关于-n参数的,大家也许没看懂,没关系,我们来看一 ...
- JVM内存区域划分Eden Space、Survivor Space、Tenured Gen,Perm Gen解释
以下内容转自:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=29632145&id=4616836 jvm区域总体分两 ...
- JVM内存区域划分Eden Space、Survivor Space、Tenured Gen,Perm Gen解释(转)
jvm区域总体分两类,heap区和非heap区.heap区又分:Eden Space(伊甸园).Survivor Space(幸存者区).Tenured Gen(老年代-养老区). 非heap区又分: ...
- JVM内存区域划分Eden Space,Survivor Space,Tenured Gen,Perm Gen
jvm区域总体分两类,heap区和非heap区.heap区又分:Eden Space(伊甸园).Survivor Space(幸存者区).Tenured Gen(老年代-养老区). 非heap区又分: ...
- JVM内存区域详解(Eden Space、Survivor Space、Old Gen、Code Cache和Perm Gen)
JVM区域总体分两类,heap区和非heap区.heap区又分为: Eden Space(伊甸园). Survivor Space(幸存者区). Old Gen(老年代). 非heap区又分: Cod ...
- Permanent Space 和 Heap Space
JVM堆内存 JVM堆内存分为2块:Permanent Space 和 Heap Space. Permanent 即 持久代(Permanent Generation),主要存放的是Java类定 ...
- 法线从object space到eye space的转换((normal matrix)
对于顶点来说,从object Space转换到eye space, 使用model-view矩阵就好了.那么顶点的法线是否也可以直接使用model-view矩阵转化? 通常情况下是不行的. 如下两张图 ...
随机推荐
- 你不是说你会Aop吗?
一大早,小王就急匆匆的跑过来找我,说:周哥,那个记录日志的功能我想请教一下. 因为公司某个项目要跟别的平台做对接,我们这边需要给他们提供一套接口.昨天,我就将记录接口日志的工作安排给了小王. 下面是我 ...
- 设计实现SAM--无服务器应用模型
Author:心谭 From:[Serverless]设计实现SAM--无服务器应用模型 Des: 专注算法与 web 开发的技术博客 什么是SAM? sam全称是:Serverless Applic ...
- 001_解析go语言中的闭包
go语言中的闭包,是大家学习go语言的一个大难点,笔者在学习时候也是痛苦不堪,在来回对比了其它语言的用法,并且查阅了很多网上的文章,终于对闭包有了一个较为清晰的认识,以下就是关于闭包的解析 首先看一个 ...
- Python自动化办公知识点整理汇总
知乎上有人提问:用python进行办公自动化都需要学习什么知识呢? 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很多已经做案例的人,却 ...
- Python 5 行代码的神奇操作
Python 语言实现功能直接了当,简明扼要,今天咱们就来一起看看 Python 5 行代码的神奇操作! 1.古典兔子问题 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语 ...
- 解决 SQLException: Value '0000-00-00 00:00:00' can not be represented as java.sql.Timestamp的问题
连接数据库时 设置:zeroDateTimeBehavior=convertToNull
- Bytom Dapp 开发笔记(一):架构设计
简介 研究比原链已经一年了,用比原链做了几个dapp,而且最近还做了一个基于他们插件钱包的dapp,总结了一些遇到的坑,还有一些技术细节,接下来我会分成三章,从dapp设计架构上,到深入到源码分析去帮 ...
- Windows下使用命令行编译Qt项目(解决DLL丢失问题)
一.前言 我之前用Qt做了个hello world,结果各种报错,一大堆DLL找不到,今天用命令行编译就通过了 二.准备工作 1.Visual Studio(有nmake就行) 2.Qt 3.把qma ...
- 修改mac系统名字&&神秘bogon
问题分析 你是否遇见过突然终端突然出现奇怪 bogon # name @ bogon in ~ [22:31:01] $ 这是因为终端会先向 DNS 请求查询当前 IP 的反向域名解析的结果,如果查询 ...
- C#LeetCode刷题之#39-组合总和(Combination Sum)
目录 问题 示例 分析 问题 该文章已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3663 访问. 给定一个无重复元素的数组 candi ...