1  HDR基本概念

高动态范围光照(High Dynamic Range Imaging,简称HDRI或HDR),是一种表达超过了显示器所能表现的亮度范围的图像映射技术,已成为目前游戏应用不可或缺的一部分。通常,显示器能够显示R、G、B分量在[0, 255]之间的像素值。而256个不同的亮度级别显然不能表示自然界中光线的亮度情况。比如,太阳的亮度可能是一个白炽灯亮度的几千倍,是一个被白炽灯照亮的桌面的亮度的几十万倍,这远远超出了显示器的亮度表示能力。

  想象在一个房间中,刺眼的阳光从窗外照进来,若使用常规方法渲染这个房间,房间中白色的墙壁的颜色是(255, 255, 255),阳光的颜色也是(255, 255, 255),墙壁将表现得和窗外的阳光颜色一样。很明显,这和我们现实看到的差异很大,现实场景中阳光要比墙壁刺眼很多,我们需要使用某种技术对阳光的亮度和墙壁的亮度进行处理,让其在显示器上的效果接近现实效果。

  简单的将高范围的亮度按比例缩放后映射到[0, 255]是不可行的,比如将[0, 511]的范围按照2:1映射到[0, 255],虽然表示的亮度范围扩大了,但是将导致色带(Color Banding)问题,色带如图1所示。

  

图1 左图有色带问题,右图显示正常

  在有限的亮度范围内显示自然界中相当宽广的亮度范围,正是HDR技术所要解决的问题。

2  HDR渲染步骤

  1)将整个场景渲染到一张浮点纹理上(16bit或32bit都可以);

  2)色调映射(Tone Mapping);

  3)渲染泛光(Bloom)效果;

  4)将泛光和色调映射的结果进行叠加。

  第一步很简单,只需要硬件支持浮点纹理即可,比较重要的是本文重点介绍的2、3两步,最后将2、3两步的结果进行叠加,形成最终效果图。

【显示设备上[0, 255]的亮度范围在着色器程序中使用[0, 1]的浮点数表示,下文的亮度和颜色值表示均使用着色器程序的标准。在算法中都用到了亮度的计算,每个像素的亮度的计算方法是L=0.27R+0.62G+0.06B】

3  色调映射

  色调映射是在有限动态范围媒介上近似显示高动态范围图像的技术。对于人眼来说也有类似的映射方式,因为人眼对亮度的感知范围远低于自然界的亮度范围,只能感知到某个范围内的光照。和显示设备不同的是,人眼对光的感知范围是动态变化的,例如从光亮的室外环境突然走入一个黑暗的室内环境,刚刚开始一片漆黑,过一会儿才可以看清周围环境,人眼的这个调节过程叫做光适应(Light Adaptation)。所以要模拟出真实的光照效果,除了表现出合适的光照,还需要模拟出人眼对光线的调节过程。

  最简单的色调映射是将亮度超过1的值置为1,这种做法会出现文章开始提到的墙壁和阳光一样亮的问题;另一种简单的色调映射是将每个像素的除以最高亮度像素的亮度值,可以很好的将所有像素的亮度映射到[0, 1]之间,这种方法会导致场景中某些特别亮的像素会导致场景中的其他部分特别暗。比较好的方式是采用平均亮度值进行调节,由于平均亮度值反映了场景中的整体亮度,所以受到场景中少部分过亮或过暗的像素影响不大。

3.1  计算平均亮度

  计算平均亮度的公式为:

该公式先对亮度取对数,平均后再进行幂运算。之所以不是直接对亮度平均,而是取了对数,是为了防止过亮的像素对整体造成的影响过大,该公式来源于参考文献1。

  计算平均亮度的最简单的方法是遍历所有像素,用上述公式求平均值。该方法需要CPU完成,效率不高,DirectX的“HDRLighting”例子采用了一种基于GPU加速的方法,利用像素着色器多次DownSampling,最后求得平均值,具体流程如下:

  1)首先将场景渲染到纹理中,在此基础上,对该纹理取样并计算相应像素亮度的ln()值并进行平均(相当于上述公式去掉exp),存入64*64的纹理中;

  2)对上一步的纹理4*4 DownSampling,生成16*16的纹理;

  3)对上一步的纹理4*4 DownSampling,生成4*4的纹理;

  4)对上一步的纹理4*4 DownSampling,生成1*1的纹理,并计算其exp()值。

最后生成的1*1的纹理中的像素为公式中要求的平均亮度Lavg。

3.2  光适应

  为了模拟人眼对于不同光强会自动调节适应范围的效果,只需要对这一帧求出的平均亮度Lavg与上一帧的平均亮度Lavg进行插值即可,当然这个插值不是线性插值,“HDRLighting”中的代码如下:

float fNewAdaptation = fAdaptedLum + (fCurrentLum - fAdaptedLum) * ( 1 - pow( 0.98f, 30 * g_fElapsedTime ) );

其中,fAdaptedLum为上一帧的Lavg,fCurrentLum为当前帧的Lavg,g_fElapsedTime为当前帧和上一帧的时间间隔,fNewAdaptation为最终Lavg的计算结果。

3.3 计算缩放因子

  场景的整体亮度可以通过缩放因子进行调节,公式如下:

其中Lscale(x,y)是当前像素的亮度值。Key是一个常数,Key 的大小决定了映射后场景的整体明暗程度,一般取0.18(在伽马校正理论中,0.18经过校正后大概是0.5,也就是我们感官上的中等灰度级)。Key值的选择可以看作摄像机的曝光程度,我们可以使用这个公式控制自由的摄像机的曝光程度,Key越大整个场景就显得越白。一般来说,高曝光的Key最高为0.72,低曝光的Key最低为0.045,一般程度的曝光Key选择0.18附近的值。

3.4  归一化处理

  到此为止,色调映射已经基本完成,剩下的只需要将Lscale(x,y)映射到[0, 1]范围内即可,公式如下:

其中其中Color(x,y)是当前像素的颜色值。

4  渲染泛光效果

  泛光是一种光学效应,它是指在来自于强光源的光线看起来像是影响到了周围物体。想象一间房间,窗户外面阳光明媚,若往窗外看去,感觉窗户光亮的边缘有一圈模糊,这就是泛光效果。在游戏中适当的增加泛光效果,能够增强画面的真实感。

  渲染泛光效果的思路很简单,主要分为两个步骤,第一步是使用bright-pass filter提取出场景中高亮部分,第二步对高亮部分进行模糊处理。"HDRLighting"中bright-pass filter的代码如下:

 // Determine what the pixel's value will be after tone mapping occurs
vSample.rgb *= g_fMiddleGray/(fAdaptedLum + 0.001f); // Subtract out dark pixels
vSample.rgb -= BRIGHT_PASS_THRESHOLD; // Clamp to 0
vSample = max(vSample, 0.0f); // Map the resulting value into the 0 to 1 range. Higher values for
// BRIGHT_PASS_OFFSET will isolate lights from illuminated scene
// objects.
vSample.rgb /= (BRIGHT_PASS_OFFSET+vSample);

第二步则是对第一步的结果进行模糊,首先对第一步的结果进行2*2或4*4的downsampling,再使用2*2的高斯核心对其进行模糊。其中先对图像downsampling再模糊的做法是利用GPU进行图像模糊的一种提高性能的方法,因为downsampling后图像分辨率降低了,计算量自然就少了;而downsampling后的图片再放大,本身又是一种模糊,可以减少高斯模糊的采样数量。最终效果如图2所示

      

图2 图片来源于微软DirectX SDK中“HDRLighting”例子,左图为过度曝光的场景,中间图片为bright-pass filter处理后的结果,右图为模糊之后的效果

5  融合

  现在需要将色调映射的图像与泛光的图像进行融合。在融合操作中除了常见的α融合外,还有一种叠加(Additive Blending)操作,它可以将两种颜色的值进行加法操作,通常会使得颜色越变越白,这正是我们所要的效果。将色调映射的图像与泛光的图像进行叠加操作,即可生成最终图像。

6、最终效果

  “HDRLighting”中LDR和HDR的效果对比如图3所示。

    

图3 “HDRLighting”中LDR和HDR的效果对比,左图为LDR,右图为HDR

  其他的一些HDR渲染效果如图4-7所示。图4中很明显的观察到汽车窗户的镜面光,图5中蓝色的灯光显得比较亮,但是暗的地方也很清晰;图6和图7来自游戏“孤岛危机”,效果相当不错,其中就有HDR的功劳(当然要做到这样的画质,HDR只是冰山一角)。图6场景明暗得当,透过树叶可以看到天空略微模糊;图7中可以看到爆炸产生的碎片以及车上的显示屏有泛光效果,充分体现了亮度的差别,而这些细节让游戏更加逼真。

图4 Unity3D文档中的HDR渲染效果图1

图5 Unity3D文档中的HDR渲染效果图2

图6 “孤岛危机”截图1

图7 “孤岛危机”截图2

参考文献:

[1]Reinhard, Erik, Mike Stark, Peter Shirley, and James Ferwerda. "Photographic Tone Reproduction for Digital Images". ACM Transactions on Graphics (TOG), Proceedings of the 29th Annual Conference on Computer Graphics and Interactive Techniques (SIGGRAPH), pp. 267-276. New York, NY: ACM Press, 2002.

[2]Akenine-Möller T, Haines E, Hoffman N. Real-time rendering 3 [M].

[3]DirectX 9.0c SDK

[4]http://www.cnblogs.com/cxrs/archive/2013/03/22/hdr%E9%AB%98%E5%8A%A8%E6%80%81%E8%8C%83%E5%9B%B4%E5%85%89%E7%85%A7%E6%B8%B2%E6%9F%93.html

[5]http://wenku.baidu.com/view/fe31607ea26925c52cc5bf97.html

[6]http://www.zwqxin.com/archives/shaderglsl/review-high-dynamic-range.html

[7]http://zh.wikipedia.org/wiki/%E9%AB%98%E5%8A%A8%E6%80%81%E8%8C%83%E5%9B%B4%E6%88%90%E5%83%8F

高动态范围光照(High Dynamic Range Imaging,简称HDRI或HDR)的更多相关文章

  1. paper 73 :HDR(High Dynamic Range Imaging)在摄影中指高动态范围成像

    HDR(High Dynamic Range Imaging)在摄影中指高动态范围成像.国内的教程基本语焉不详,找到一篇比较详尽的国外教程翻译出来,希望对大家有帮助.^_^ 原文地址:http://p ...

  2. 高动态范围(High-Dynamic Range,简称HDR)

    高动态范围(High-Dynamic Range,简称HDR) 一.HDR介绍 高动态范围(High-Dynamic Range,简称HDR),又称宽动态范围技术,是在非常强烈的对比下让摄像机看到影像 ...

  3. paper 72 :高动态范围(HDR)图像 HDR (High Dynamic Range)

    In standard rendering, the red, green and blue values for a pixel are each represented by a fraction ...

  4. Unity Lighting - High Dynamic Range (HDR) 高动态范围(五)

      High Dynamic Range (HDR) 高动态范围 As well as Color Space, the ‘dynamic range’ of your camera needs to ...

  5. HDR(High Dynamic Range) - 高动态范围

    1. Dynamic Range 动态范围是指一个场景的最亮和最暗部分之间的相对比值   2. Tone-mapping 现实真正存在的亮度差,即最亮的物体亮度和最暗的物体亮度之比为 , 而人类的眼睛 ...

  6. Dynamic range compression

    这段时间终于把手头的东西都搞完了,还剩下一个AEC这个模块,这个模块跟整个系统机制有很大关系,单独的模块意义不大. 另外,刚写完一个分类器,希望能大幅提升音乐流派分类的准确率. 下周正式开搞AEC,把 ...

  7. 动态规划算法(Dynamic Programming,简称 DP)

    动态规划算法(Dynamic Programming,简称 DP) 浅谈动态规划 动态规划算法(Dynamic Programming,简称 DP)似乎是一种很高深莫测的算法,你会在一些面试或算法书籍 ...

  8. Unity3D所使用的第三方工具

    前言 最近在研究Unity3D的结构和原理.关于Unity3D怎么用之类的教程在网上一找一大堆,想看教程之类的就不用看这篇文章了.我想做的是从使用Unity3D所看到的表象(表),摸透其设计原则和组织 ...

  9. 基于Fast Bilateral Filtering 算法的 High-Dynamic Range(HDR) 图像显示技术。

    一.引言 本人初次接触HDR方面的知识,有描述不正确的地方烦请见谅. 为方便文章描述,引用部分百度中的文章对HDR图像进行简单的描述. 高动态范围图像(High-Dynamic Range,简称HDR ...

随机推荐

  1. hdu 4638 树状数组

    思路:将查询区间按右节点的升序排列,然后插入第i个数的时候,若nun[i]+1已经插入,那么就update(pre[num[i]+1],-1):pre[]表示的是该数的位置.同样若 num[i]-1存 ...

  2. jQuery对象和dom对象的辨析和相互转化

    jquery对象和dom对象总是让人感觉很难分清,其实只要做到1对两者概念有明确认识2找出不同点 A DOM 1概念 DOM对象(Document Object Model,文档对象模型)可以把htm ...

  3. Jersey(1.19.1) - Client API, Uniform Interface Constraint

    The Jersey client API is a high-level Java based API for interoperating with RESTful Web services. I ...

  4. 【转载】LinkedIn是如何优化Kafka的

    http://www.wtoutiao.com/p/18d5RY0.html 在LinkedIn的数据基础设施中,Kafka是核心支柱之一.来自LinkedIn的工程师曾经就Kafka写过一系列的专题 ...

  5. hiho拓扑排序专题 ——第四十八、四十七周

    拓扑排序·一 分析: 此题就是求一个有向图中是否存在环. 如存在环则输出"Wrong", 若不存在环, 说明课程安排的合理,输出"Correct". 题中的提示 ...

  6. request常用方法小结

    HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,开发人员通过这个对象的方法,可以获得客户这些信息. req ...

  7. 如何查看JDK是64bit还是32bit

    在eclipse或MyEclipse中创建一个Java Project并运行如下代码: public class Test { public static void main(String[] arg ...

  8. 实现网页页面跳转的几种方法(meta标签、js实现、php实现)

    1.meta标签实现 只需在head里加上下面这一句就行了,在当前页面停留0.1秒后跳转到目标页面  代码如下 复制代码 1 <meta http-equiv="refresh&quo ...

  9. MySQL查询不使用索引汇总

    众所周知,增加索引是提高查询仍然不使用索引,这种情况严重影响性能,这里就简单总结几条如果如果列key均匀分布在1和100之间,下面的查询使用索引就不是很好:select * from table_na ...

  10. css笔记——杂记

    ####文本框内阴影#### input[type=text], textarea, input[type=email], input[type=url]{ box-shadow: inset 2px ...