转载请注明出处为KlayGE游戏引擎,本文的永久链接为http://www.klayge.org/?p=2639

HDR post process几乎存在于所有PC桌面引擎中,也开始在一些高端移动平台上得到了支持。HDR太常见了,以至于这年头如果看到一个不带HDR的真实感实时渲染,就会觉得很突兀。(比如,在SIGGRAPH展会上,看了Qualcomm的展台,再看ARM和Imagination的,就有一种回到dx8时代的感觉。大部分原因就来自于Mali和PowerVR缺乏很好的HDR。)在这方面,KlayGE的目标是在不同平台上,都能尽量多地复用HDR post process里的组件,同时效果也尽量接近。首先让我们看一张只有LDR的图。

Dragon with LDR

啥都支持的平台

代表的平台有D3D11 level 10+,OpenGL 3+。支持包括B10G11R11F在内的各种浮点纹理。在这样的平台上,KlayGE的HDR流程是这样的。注意红字标出来的数据格式。

Full HDR pipeline

如果支持compute shader 5,就会进一步选择更短的那条code path。这是个完整的HDR支持,包含所有需要的组件。下图是个完整HDR的结果,特别增强了光照。

Dragon with Full HDR

支持ABGR16F但不支持R16F的平台

代表平台是D3D11 level 9.3,OpenGL 2.0,早期的shader model 2硬件,以及Adreno 3xx和Tegra 4这样的高端OpenGL ES 2/3的移动GPU。这样的平台基本不支持R32F,而且最奇葩之处在于支持四通道的ABGR16F,却不支持单通道和两通道的R16F。如果这时候把所有本来是R16F的都扩充到ABGR16F,显然带宽、存储空间和速度都会受到很大影响。所以在这样的平台上,更好的方法是用前几天提到过的,把float编码到四个8bit。当然,这样的平台也往往不支持G10B11R11F,所以输入改为ABGR16F的格式。

No R16F HDR

从这张图可以看出,compute shader的code path被去掉了,FFT的lens flare也没有了。Image statistic的部分,组件本身不变,只是输出的R16F和R32F被编码到了ABGR8。从效果上来说,这个简化并没有带来结果的任何不同,仍然是100%的HDR效果。需要注意的是,由于那个float编码的方法只适用于[0, 1)的范围,所以需要对数据做些调整。Adaptive luminance可以用/16。Sum of log(luminance)由于可能有负值,所以不但要/16,还要+0.5。读取这样的纹理,除了解码,还得逆向计算得到原始的float值。

任何浮点纹理都不支持的平台

代表平台是D3D11 level 9.1/9.2,OpenGL 1.x,绝大部分OpenGL ES 2和PowerVR和Mali等一部分OpenGL ES 3移动设备。由于没有渲染到浮点纹理的能力,输入部分只能用LDR。虽说有个技巧是用A2BGR10的格式,输出颜色的时候/4,来模拟一点点的HDR能力。但这意味着几乎需要修改所有的pixel shader,以换取微弱的效果提升。有种得不偿失的感觉啊。所以这里我仍用的ABGR8这样的格式,完全放弃了HDR的渲染。如果支持sRGB,也会尽量使用到。

No FP HDR由于没有了HDR的输入,自适应亮度调整也变得没有必要。所以image statistic那条分支被直接砍掉,tone mapping的时候也不做亮度调整,仅仅保留 bloom和blur shift。这样虽然只能算作fake HDR了,但由于有了bloom,效果上也比光秃秃的LDR好些。这个技巧其实出现在10年以前,是当早期的桌面GPU不支持浮点纹理使用的障眼法。这年头由于孱弱的移动设备而被再次提起。只有bloom的效果如下。

Dragon with only Bloom

总结

通过对浮点纹理的编码,并相应地砍掉了一些组件,KlayGE的HDR post process终于能在各种配置的平台上执行了,而且保持了尽量多的HDR效果。