zoukankan      html  css  js  c++  java
  • ToneMapping算法简介

    说起Tone Mapping,就不能不提HDR。HDR(High Dynamic Range, 高动态范围)是一种颜色范围,在传统的RGB中,每一个通道的颜色都是从属于[0,1]之间的浮点数范围,0代表纯黑,1代表纯白,超过了1仍然会归为白色;但是在现实光照方程中却没有这个限制,光的强度可以设置为任意大,那么就需要重新设定颜色的范围,这就是HDR。有了HDR,场景中亮的东西可以变得非常亮,暗的东西可以变得非常暗,而且充满细节。
    之前提过的颜色值只能属于[0,1]之间的算法称作LDR(Low Dynamic Range,低动态范围),那么假设我们在计算中采用的是HDR,因为计算机屏幕只能显示[0,1]之间(也就是LDR)的颜色,因此在最终输出颜色的时候需要做一个从HDR到LDR的转换,具体的转换算法就是ToneMapping。
    《LearnOpenGL》中提到了两种ToneMapping的算法,我们对此分别进行说明。
    最简单的色调映射算法是Reinhard ToneMapping。它的实现非常简单,代码如下:

    float3 ReinhardToneMapping(float3 color, float adapted_lum) 
    {
        const float MIDDLE_GREY = 1;
        color *= MIDDLE_GREY / adapted_lum;
        return color / (1.0f + color);
    }
    

    MIDDLE_GREY是默认为灰的颜色,adapted_lum是统计的亮度(具体的计算可以参考Photographic Tone Reproduction for Digital Images这篇论文),我试了一下,它的函数图形如下(默认MIDDLE_GREY和adapted_lum都是1):

    虽然它的做法简单粗暴,亮的变暗,暗的变亮,但是缺点就是把所有的颜色都往中间压缩,整体画面会显得灰暗,下图来自于使用该算法的一个场景:

    后来CryEngine又提出了另一种ToneMapping方法,将亮的部分压平:

    float3 CEToneMapping(float3 color, float adapted_lum) 
    {
        return 1 - exp(-adapted_lum * color);
    }
    

    其中adapted_lum是曝光度,曝光度越高整体越亮,比Reinhard的方法更鲜艳,如下图所示:

    以上就介绍这两种方法,后来人们还提出了更多效果更好的方法,可以参照这篇文章进一步地学习:https://zhuanlan.zhihu.com/p/21983679

  • 相关阅读:
    数据结构HashMap(Android SparseArray 和ArrayMap)
    一篇文章教你读懂UI绘制流程
    死磕安卓前序:MVP架构探究之旅—基础篇
    我就死磕安卓了,怎么了?
    戏说移动江湖开发历程
    姿势摆好,一招学会android的布局优化!
    学习React Native必看的几个开源项目
    开发了几个小程序后,说说我对小程序的看法
    jQuery基础一
    JavaScript基础二
  • 原文地址:https://www.cnblogs.com/wickedpriest/p/13048588.html
Copyright © 2011-2022 走看看