Gamebryo完整实现HDR及分析

来源:互联网 发布:centos 6.7网卡安装 编辑:程序博客网 时间:2024/06/06 03:13

今天要用GameBryo实现HDR,大家一起研究学习

由于公司的万恶网络不能上传图片,就忍了:

 

首先介绍的HDR实现中需要封装一个AuxBuffer,其继承于NiRenderClick,对于HDR过程的一个步骤(Click),里面

能获得以下几个东西:

 

(1) NiRenderedTexturePtr m_spTex; 渲染目标,一张纹理,其可以作为下一个步骤的输入。
(2) NiMeshScreenElementsPtr m_spGeom; 屏幕元素,当前步骤面对的目标屏幕,

上面可以使用上层纹理和相应的材质,shader.

 

了解这个之后,就开始了HDR的流程了。

 

1、构建整个流程重要的渲染纹理。

 

m_kHDRScene --->场景正常渲染,保持整个场景的FP Texture格式是D3DFMT_A16B16G16R16F这样保存的颜色值就

可以突破0-1的限制。

m_kHDRSceneScaled-->缩小后的纹理,缩小为原来的1/4,作为一阶段的纹理来源。
m_akToneMaps[4]-->计算场景的亮度值用的系列贴图,大小为(1x1, 4x4, 16x16, 64x64)。
m_pkAdaptedLumCur,m_pkAdaptedLumLast-->光适应值,过渡贴图,比如从比较亮的地方突然过渡到比较暗的地方,必须
做出光的适应。
m_kBrightPass-->保存了m_kHDRScene通过Bright-Pass Filter后的,只剩下了亮度高的部分。
m_kBloomSource,m_akBlooms-->光晕效果贴图。
m_kStarSource-->星光效果贴图。
m_kOutputBuffer-->最后混合后的输出。

这里我们封装了CreateAuxBuffer函数,其承担了各个click的创建工作。这里有必要解释下GB的RenderClick:
A render click represents a single rendering operation to a single render target group. Multiple render clicks can happen in sequence to produce a single rendering effect.
一个Click关联一个渲染目标,多个渲染目标作为一个序列构成一个效果,其实GB里面的RenderStep管理Click。

 

 

构建好RenderTextures后,下面就根据需求构造相应的RenderClick.HDR都是把前一个步骤处理的结果作为后一个后一个步骤的来源:

m_kHDRScene结果---->m_kHDRSceneScaled结果---->m_akToneMaps结果--->m_pkAdaptedLumLast/m_pkAdaptedLumCur
m_kHDRSceneScaled结果--->m_kBrightPass结果---->m_kStarSource结果---->m_kBloomSource结果
我们提供通用函数来构建CreateAuxBufferGeom,其把来源纹理的纹理作为本次处理Click屏幕的一层ShaderMap,并加入相关联的材质

 

 

 

此过程调用代码:

 

 2、HDR渲染开始

 

(1)将Scene渲染到我们新的RT上,由于RT是就是m_kHDRScene的贴图,我们能够保存超过0-1的数据。

然而超过0-1的数据时如何保证的呢,我们会遍历相应的场景节点,对需要进行HDR处理的亮光部分,创建相应的纹理也就是

D3DFMT_A16B16G16R16F.代码如下,大家都会:

 

 

(2)将m_kHDRScene渲染到m_kHDRSceneScale上,也就是缩小到1/4,这样的作用是在下面的处理能提高不少速度.

我们来看相应的Shader代码:

 

 

这里就是按照gakSampleOffsets的偏移值采样16个texel,然后计算均值,gakSampleOffsets的生成代码也比较简单:

 

 

(3)Draw quad to create final luminance tone map ,构建m_akToneMaps[4],计算场景的亮度值用的系列贴图,大小为(1x1, 4x4, 16x16, 64x64)。

 

在你的程序能缩放场景强度之前,你需要确定场景在开始时有多亮。目的是为平均场景亮度作个好的估计,以最小化计算所需的时间消耗数量。减少采样纹理可以提升计算速度,但是较少采样会面临丢失亮区域的风险。在这个例子中最接近的方法是首先按1/4 x 1/4比例缩放场景,使用平均每个4 x 4的纹理块减少采样。这个缩放纹理也用来建立光照效果的资源纹理,因此缩放操作的精确度是很重要的,以避免镜头在场景中移动出现闪烁现象。

 

下面的亮度方程方法用来测量平均场景亮度和完成色调映射的白纸特征Photographic Tone Reproduction for Digital Images

平均场景亮度用来最后计算所有采样像素平均对数值的逆对数。Delta包含一个小值来操作纯黑纹理情况。这个方程实现了测量亮度方法的四个像素着色过程,如下:

1.样本平均值 log() 值到一个64 x 64 纹理中。
2.按比例缩小到16 x 16。
3.按比例缩小到4 x 4。
4.按比例缩小到1 x 1并在结果上执行一个exp()操作。

保存一个1 x 1的纹理,计算需要平均亮度值,计算工作能被视频卡完全处理而不需要AGP总线传输。

 

代码如下:

 

 

(4)曝光控制:

 

暴光控制是找出一个适当的低动态范围的HDR场景视图的方法。在物理镜头系统中,光圈调整光线进入系统的数量极限。该方法使用计算机图像来模拟通常叫做色调映射的暴光控制。它引用映射一个HDR图像空间到低动态范围空间中以适合于视频显示的方法。不同于暴光控制,色调映射时所有高范围数据是有效的;所以,依赖于操作,图像比使用传统的摄像机可能包含更多的来自亮区和暗区的细节。

 

在平均场景亮度计算之后,HDR场景纹理能被按照目标平均亮度缩放,表现在下面方程式的alpha上:

这个方程式为最终场景简单的产生一个围绕物体平均亮度的场景亮度中心的线性缩放;然而,这个结果值还尚未被压缩到适合于可视化屏幕的低动态范围0.0 1.0。下面的色调映射操作完成期望的压缩。

人类视觉系统不能对光线环境亮度的变化作出瞬间调整,这种特性容易被稍微扩展的色调映射计算模拟。通过色调映射公式用使用者当前适当亮度值替代平均场景亮度。这个适当亮度值存储在1 x 1的纹理中并调整每一帧缓慢追踪测量场景的亮度,如下代码片段所示: float fNewAdaptation = fAdaptedLum + (fCurrentLum - fAdaptedLum) * ( 1 - pow( 0.98f, 30 * g_fElapsedTime ) );例如,如果摄像机是固定的,适合的亮度最后将匹配标准的亮度,色调映射的输出和适配器无效时输出的结果一致。可是,如果摄像机焦点移动到不同亮度量级的区域,在整个视野调整到新光照环境过程中图像将出现暴光过度或暴光不足,适应性模式在这个例子中不是预期的人类适应性的真实模式,它至少比一个半小时的全黑适应要好的多。

 

这个部分我主要通过 m_pkAdaptedLumCur,m_pkAdaptedLumLast两个Click去控制,其对应的材质shader为:

 

 

 

(5)光亮过滤器

色调映射执行两处代码;一处是在渲染中作为最终着色器的一部分传给合成的耀光纹理到场景中,一处是作为光亮过滤器的一部分。光亮过滤器使用色调映射首先测定哪个最终场景图像区域将被照亮,然后排除剩余数据。由于HDR光照效果与当前暴光相关,这些效果能在色调映射图像上完成并直接到场景输出。这个程序优势在于能用整数纹理产生眩光。

下面的代码片段展示了光亮过滤器在减去黑暗区域之前首先映射场景到希望的中等灰度的亮度的物体。色调映射操作从稍微修改的最终方程中转换了场景的亮度到0.0 ~span>1.0f范围之间。不是用亮度增量来区分亮度,而是用一个偏移值替换公式中的一个量。当偏移值增加,独立在场景亮区和暗区的部分也相应增加。

 

 

 

(6)光晕效果

 在完成光晕之前,光亮过滤器图像已被缩小和模糊到原始场景纹理1/8 x 1/8比例,光晕处理只是一个简单的水平线与垂直线的光亮过滤器场景中的高斯模糊的两次分别处理。纹理首先被沿着水平线模糊,然后水平模糊后的纹理沿着垂直方向模糊以完成这个处理。作为最终场景的一部分,光晕纹理缩小到使用双线性过滤和场景直接输出的后缓冲尺寸。

 

光晕的shader代码也比较简单,对前面活动的BrightPass贴图进行水平,垂直模糊就OK。。

 

相应的C++代码:

 

 

(7)星光效果

星光效果可能需要对每个星光光线至少三次以上的渲染。星光模式可以有不同星光类型的特征,包括光线数目,光线方向,和色彩偏移,一次渲染全部单独方向的光线,穿过单独光线纹理的平均纹理值用于建立最终的合成的星光纹理。这个合成纹理是缩小的和直接到最终场景的图像。相对应的shader代码,大家大可以做出不同的改变

 

 

 

(8)最终结果输出,这是等待已久的。

 

shader代码如下:

 

 

对Star后的结果进行Bloom,后得到的贴图,做出平衡光过渡,混合。得到最后结果。。。其实每个阶段相应的处理

都是可以优化和调参数得到更好效果的。我已把HDR移进我的客户端,最后要和美术交流得出最终的解决方案。大家

如有什么意见可以提出:shadowgor@gmail.com

 

 

原创粉丝点击