前日在gameRes看到了DX HDR的一份翻译,结果完全看不懂。一怒之下,决定浏览源代码。果然,源代码才是最详细最精确的文档所在。
HDR的意思是高动态范围光照,起初有点直观的理解是:将光照渲染到R32G32B32的浮点纹理上,获得全范围的亮度,然后再通过调制,将其映射到256级的[0,1]之间。如果按照传统的非HDR做法,亮度大于1的值将会clamp成1,因此1和1.5之间所显示的亮度是相同的,缺少了对比度。HDR的做法,是通过浮点纹理保存任意范围的亮度,然后映射到[0,1]之间,这样可以保留对比度,使得场景更加自然。
![hdr.JPG](/images/cppblog_com/darkdestiny/hdr.JPG)
如上所示,HDR技术的第一步,是把场景渲染到一张浮点纹理上,比如R32G32B32(使用16bit的更快),这张sceneHDR大小通常是512×512的。
接下来,为了效率,将sceneHDR缩放到128×128的浮点纹理smallScene中。需要提前说明的是,自渲染场景之后,接下来的渲染都是post-process了,也就是说,所有的缩放都是基于post-process完成的。
在渲染至128×128的纹理的时候,要使用较好的滤波器算法,最基本也要用scale3×3吧。
然后,要使用tone map算法,取得比较可信的场景平均亮度。关于tone map算法,其实就是经历一定的中间结果直至最终结果,而不是一下子就从source中获取最终结果。
tone map算法是为了获取亮度,因此使用格式R32F/R16F,建立一串的逐步缩小的纹理:32×32,8×8,2×2,1×1。首先从smallScene中获取颜色值,然后根据某些公式转化成灰度/亮度,渲染到32×32中,剩下的tone map,从上一级获取颜色值,然后渲染到下一级中,直至1×1,这样,就在1×1的tone map中得到了场景平均亮度。在这种down scale的情形下,一定要选择较好的滤波器,而不是点取。
额外的,为了模拟人眼对亮度变化的适应过程,到这个时候,可以根据当前的适应度和当前场景平均亮度,计算新的适应度。
获取场景平均亮度,就是为了从场景中过滤出发光部分,也就是亮度大于平均亮度的部分。这里你可以直观的做比较,也可以根据某些更有意义的算法,得出发光图。算法主要是根据smallScene和1×1的tone map,渲染到brightMap中。
接下来的两个步骤,具有很大的类同,区别只是滤波器/算法不同而已,就是分别以brightMap为source,将光亮处的星状效果和模糊效果渲染到纹理starMap,bloomMap中。后3个纹理的格式,可以是整数格式,也可以是浮点格式,主要看光亮超范围的情形了。
额外的,此处可以用更多的pass对starMap和bloomMap做再处理,以达到更好更柔和的效果。
最终的,finalPass来临了,就是将512×512的sceneHDR+a*starMap+b*bloomMap渲染到屏幕上,看情况使用合适的滤波器。
posted on 2006-10-11 12:58
LOGOS 阅读(1653)
评论(1) 编辑 收藏 引用