zoukankan      html  css  js  c++  java
  • gamma correction / /alpha blend

    http://www.cambridgeincolour.com/tutorials/gamma-correction.htm

    gamma needs more to describe darkness less bits for brighter range

    因为只有8bits 我们眼睛感知颜色不是线性感知的 如果颜色线性过来 我们感受到的暗部会丧失细节 所以需要更多位来描述暗部 所以需要input gamma encode一下

     用gamma encode存储图片是为了有效利用更多bit存储我们眼睛更为敏感的暗部

    即使最后会被dispaly gamma pow回线性 图片细节 暗部细节

    gamma correction 是指pow0.45  即encode

    之后还有个display gamma 叫decode 是pow2.2 这个是显示器做的 可以从显示器的设置里改  我们就当成显示器不改设置的话 默认会做pow2.2

    正确的流程是这样的

    1.Texture 通常都是gamm space 的所以不用软件特殊处理,打开看颜色正常的就是gamma space  (encoding gamma 1/2.2) 

    raw texture 颜色有些暗 (既没有encdoe又没有decode的val) (http://www.cambridgeincolour.com/tutorials/gamma-correction.htm)这里有例子

    0.5 pow2.2 =0.21 pow0.45 =0.73 所以encode变亮 

     读入的时候 把srv tex设置成srgb格式,这样就会被从gamma space 转入linear space(pow2.2一次) 这样用于光照计算那步就是对的 就不用再转了 

    (此pass的destination format如果设置为srgb 结果就会再被pow0.45 为了给之后display pow2.2用 或者不指定dest srgb在第三步那里统一做p0.45

    (前面pass不要指定srgb destion 第三步那里做因为你要确保display的输入是gamma p0.45压过的  

    (如果你为了去band artifacts可以把前面指定srgb 那种错误叫roping 但之后的采样要接着srv srgb通常用于pp里面

    2.光照需要在线性空间计算  realtime rendering Page143 有sample 这里不做修改

    3.最终颜色校正加个后处理 pow(1/2.2) (display gamma p2.2 by device realtime rendering Page143)

    为什么需要这步转换呢

    因为人眼感知的颜色是非线性空间的 gamma space 

    power law encoding--percepual uniformity 感知一致

    为什么又要转线性空间

     8bit的srv 值在0-1 minimizes banding artifacts, 会有roping 指定srv有助于改善这一点 反走样。。

    mipmap light calculate这两步线形颜色空间计算结果 开了gammacorrect(p0.45)是不对的

    gamma涉及所有要把values加减乘除运算的地方

    http://www.cnblogs.com/minggoddess/p/4277680.html

    hdr不是8bit存储所以不需要srgb dest

    如果没有hdr 后处理需要srgb unity既然这么说 说明在没有hdr的情况下 它把pp前面的pass用了srgb//这个周一去确认一下

    在支持此功能的平台opengles3.0 metal unity 用了srgbtarget会主动处理blend和msaa的 看起来就像realtimer3说的dx10的行为 dx9据说blend和msaa是错的

    hdr的流程就是srgb srv 之后都不设置srgb target 因为float已经是线性空间了 在最后做一次gamma correction就可以了 转到gammaspace p0.45

    这句我说的不贴切 应该说fp16这种浮点空间 本身是线性的 不需要再对颜色值做到gamma2.2的非线性转换 这种转换是灭有必要的,这种说法更准确些 因为。。。把一个值做了pow0.45的转换就说它在gamma空间了  不管放哪个rt上存着 这个值还是在gamma空间的  只是在fp上这种encode的操作完全没有必要了 除非原本过来的值在gamma下面 要把它转回来 但绝对没有必要再encode了!

    Conversion to or from sRGB space is automatically done by D3DX10 or D3DX9 texture-load functions.

    If a format with _SRGB has an A channel, the A channel is stored in Gamma 1.0f data; the R, G, and B channels in the format are stored in Gamma 2.2f data.

    alpha 通道不参与encode decode

    ------------------------------

    又过了一个项目

    通常拿到的未经处理的texture是gamma空间的(p0.45 亮) ,需要转到线性空间 (p2.2)(diffuse 转normal不转),用这种贴图做 linear space的颜色计算。

    这样光照+就不会过亮,锯齿会少,mipmap我记得也是要做的 还有msaa的什么问题

    ============

    之后需要确认下unity linearspace都做了什么操作 把那些rt设置成srgb了 难道是所有。。。

    ================

    我感觉 我做了这么多项目 到现在gammacorrection还是没弄对 这次一定不能再错了

    ========

    这个项目的gamma做对了

    包括ui 这个项目ui是在线性空间做的 没有encode了 这样的缺点就是 暗部细节丢失

    如果用srp 能把unity linear space的最后一张rt 不用srgb format

    ui的tex用srgb 在gamma 空间做blend 虽然数学上不太好 也许可以和ps里结果一直 这样的好处是 暗部细节在 gamma一变 混合出来的结果就不是美术在ps里调的结果了(这句不对 因为powervr的onchip mem的精度是32bits)

    综上还是觉得前者比较好

    ======

    由于后者仍然无法重现 ps混合结果

    所以我选ps工作空间gamma1.0 游戏ui写到srgb(省带宽 

    ======================

    又一个项目 gamma又是错的:

    在hdr下 unity设置选了gamma space

    没有tonemapping 映射回去

    顺路看了下PPV1 的写法 要吐槽一下

    他们在 bloom prefilter 有一次encode

    在uber bloom那里有encode 和decode

    在移动平台他们一律是整型rt

    非移动平台hdr rt

    但是这几句呢 包在gamma space这个宏里。。。

    再在文档里跟你说hdr要配合线性space使用。。一个通用引擎就做到这样 可以么。。

    一度让我怀疑我对这部分的理解有问题!

    当然他们在ppv2里就改好了 

    好多好多项目 都是在有问题的管线里面 把资源调出来 然后再换linear的时候傻眼了。。。

    =================

    unity gamma space 下 即使 texture importer 勾了srgb 也不会在read的时候 decode gamma

    只有player setting linear space的时候   texture importer 勾了srgb 才会read的时候decode gamma

    =====================

    unity 在gamma space下 做的事情是 每次存到rgba8的时候都encode下 用的时候decode下

    linear space做的事情是 texture importer decode srgb

    =====================================

    //
    // 摘要:
    // Color space conversion mode of a RenderTexture.
    public enum RenderTextureReadWrite
    {
    //
    // 摘要:
    // Default color space conversion based on project settings.
    Default = 0,
    //
    // 摘要:
    // Render texture contains linear (non-color) data; don't perform color conversions
    // on it.
    Linear = 1,
    //
    // 摘要:
    // Render texture contains sRGB (color) data, perform Linear<->sRGB conversions
    // on it.
    sRGB = 2
    }

    unity create texture的时候可以指定这个参数 选linear==不做任何操作

    选srgb会做encode decode转换

    就是说 creatRT 是float的时候  选linear

    是rgba8的时候 对于要保证数据计算在linearspace的rt 这里选srgb

    =======================

    unity 

    Linear space backbuffer用了srgb做了一次encode

    Gamma space backbuffer没用srgb 所以会有一次色差。。

    确认结果了 

    确实是gamma 是rgba8

    linear是rgba8srgb

    linera

    gamma(感谢HZ提供数据)

    这意味着 linera 写入时 多了一次encode 这就能解释为什么unity在linear空间的白一些  它写入最终结果的时候比gamma多了一次encode

    通常大家 把gamma空间 改到线性空间的时候 ui会遇到个问题 alpha blend的结果 变得很淡 实际上根据各种理论的实际的确认 alpha是不会有变化的 (理论的话 我blog之前有讲)(除非你拆成了两个通道 还勾选了alpha那张图的srgb 这点很容易排除改正)

    那为什么混合结果会变得更白呢 ,是rgb通道 写入时 encode了

    改这个问题有两个办法 1.写入的backbuffer的format 改成linear 原本是srgb 在设置选linear space时 这个不知道在项目层面好不好拿到接口来改

    2.把color(rgb) decode一次 增加了运行时的计算量 结果可以对上

    正如 刚入行时 我一个lead所说 太阳底下 无新鲜之事(其实我忘记他说的是不是 他是巫毒巫蛊程序。。。和前面那句表达的完全相反。。。。。)

    我好棒

    我用了这么久

    总觉得dest的rt不一样这个事情 我关注过 并且写blog了 我现在连二级索引都找不到了吗。。。。

    但不管怎么说 以前走过 再走会更快吧

    我终于开始接受自己认可自己了

    =================

    用1.在源码里把 backbuffer 那张rt改了 能解决这个问题 这是一种向前兼容的做法 

    管线一半linear 一半gamma的 对UI artists比较友善。。但个人还是倾向纯线性吧 这样不用改管线 但ui artists的做法要这样

    这个方法 多层混合可能无法解决,就直接在这

    用1.0空间

    存的时候 如果不想要band artifects就存srb

    也可以不存 unity中与此对应

    这两种存的方式 不会有alpha blend结果差异的问题 

    差的那次pow2.2用工具刷一遍资源

  • 相关阅读:
    js/css 伪类, 获取伪类样式
    JS 盒子模型
    python坑之input获取字符串
    configpraser模块
    类的特殊成员&反射&异常处理
    面向对象
    员工信息表
    re正则表达式
    PyCharm教程
    递归实现jsonTree
  • 原文地址:https://www.cnblogs.com/minggoddess/p/5888808.html
Copyright © 2011-2022 走看看