HDRPipeline DX9

 HDR这个词汇在我看过的书或资料中多次出现,从《Real-time Rendering》到SDK里面的偶尔出现,一直对其是一种莫名的感觉,HDR是什么,High Dynamic Range,范围很广,为什么要HDR呢?因为了更好的画面。这些很浅显的认识让我一直云里雾里。终于在DX9的sample中有这么个简单的HDR教学实例,确实让我了解很多。在网上看到3d本身渲染的未经过HDR处理的图片和经过HDR处理过的图片比较起来,HDR所带来的图片确实让我折服。因为HDR处理后的图片让人感到身临其境的感觉。记得很多次拍照片,回来看的时候总觉得不是当时看到的那种感觉,现在我才终于知道因为不经过处理的照片是LDR(Low
Dynamic Range)的,也就是照片记录不了大世界的HDR。所以我们感觉不一样。聊了一会后让我们开始认识HDR吧。

 

HDR的英文就是High Dynamic Range,也就是高动态范围。这是指的一个场景汇中最亮区域和最暗区域之间的光亮范围。在我们所处的世界中,这个范围是很广的,或者说光亮的梯度很多。但是我们的显示器,我们颜色表示确很小,255个亮度梯度变化。如果将HDR的场景,直接不经处理的传递给LDR,我们将会失去超过LDR的那部分信息。这样我们就得不到近似我们世界的大范围场景了。那我们应该怎么做的,从照相机发明一来,摄影师们早就发现这个问题,并且相处了处理这种问题的方案。这个方案也类似于我们将要讲述的HDRpipeline。那就是从场景中找出能大体表示场景总体亮度的灰度颜色(Key
Value),然后将亮度范围根据KeyValue重新映射到相机的亮度范围内。其中包含了很多冲洗照片的标准过程。我们的程序也将使用类似的思路来完成HDR往LDR的映射。

 

相关素材(tonemap.pdf)请到我的资源中下载。

 

回到程序。我们的大体思路是,首先让程序中较亮的部分感染其邻近的颜色,这样能让图片较亮的部分呈现类似我们世界的现象感染其邻近区域。染色后,再将我们图片通过某种变换映射到LDR中。

我们大体分4个部分。

  1. 首先将场景渲染到一个高精度高范围的纹理(也就是HDR)中,这样我们能真实的记录场景的颜色和亮度。但这个纹理拿去显示同样和LDR一样,因为显示器把超出1的部分截断,所以即使你有完整的数据也别想着可以显示出来。我们还需要把HDR纹理转换到LDR纹理中。
  2. 我们将得到的场景的HDR图进行亮度求值,我们使用Down Samples(降低样本,也就是大图片平均到小图片)方法求出整个场景的平均亮度,和最大亮度。我们同样采用Down Samples的方法是为了减小计算量,因为我们要进行很多次颜色填充,所以填充量让程序很吃力,为了减少计算负担,经常采用Down Samples的方法。首先我们采用rgb中最大的分量表示该色素的亮度。我们计算平均亮度是使用几何平均的方法。也就是说使用不是使用n个样本相加再除以个数的方法,而是采用n的样本亮度相乘然后开n方根。几何平均亮度也可以采用log平均方法,这两种几何平均方法是等价的。
  3. 我们需要从场景出截出比较亮的区域。首先我们设定一个较亮区域的亮度门限值,如0.8。我们将HDR图片Down Sample并截出较亮的区域。并进一步进行Down Samples。然后采用高斯模糊方法(一种经常用于图片模糊化的模糊方法)对图片进行模糊化,这样将能让较亮区域感染其邻近区域。得模糊后的图片,Bloom图片。
  4. 我们得到这些基本部件后,就可以进行我们最关键的一步,将HDR映射到LDR。首先是作者采用标准Bilinear对Bloom图片进行取值,其实一般不必这么做,因为现在绝大多数显卡已经完全硬件支持Bilinear了。然后把取得的这些颜色添加到HDR中颜色中,得到新的HDR颜色。然后用新的HDR颜色映射到LDR。首先求出新的HDR颜色的亮度值,然后用该亮度除以先前求出的平均亮度得到解调后的新亮度。调节后的新亮度需要再次调节,这样非常亮的地方才能不至于丢失。有两种方法。如下图中的两个公式。其中L(x,y)是讲过调节的亮度值。Ld(x,y)是最后的亮度值。第一个公式是最简单的,第一个公式可以让较亮的区域缩放大约1/L(x,
    y)。而让较暗的区域几乎没有改变。第一个公式保证HDR映射到LDR的范围中。但较亮的区域会让细节难以辨别。第二个公式克服了这个问题。其中的L(White)是图片中的最大亮度。

 

 

最后我要说一下我的经验,在这次学习和编程中重新认识了下MS系统中光栅化和纹理读取的矛盾。

  1. 如果想用顶点XYZRHW格式的四边形,并采用Bilinear过滤将四边形的纹理正确的渲染到屏幕,我们需要将四边形往左上方向偏移0.5,因为Bilinear取值是用以该点的纹理坐标为中心,边长为1的方格中求值。为了将这个求值方格正确的对齐到相应的纹理方格中,我们只需要将把屏幕0.0点对应的纹理坐标改为0.5,0.5就可以了。为了实现这个,我们需要将四边形往左上偏移0.5,这样在0.0的纹理就变成0.5,0.5.(详细资料请参考:Directly Mapping Texels to Pixels)
  2. 进行DownSample的时候,偶数采样和奇数采样有差别。如果偶数降采样。也就是如2x2区域降采样到一个像素。第一个偏移量为0.5。而奇数采样第一个偏移量为1.因为偶数采样的时候采样点在方格角落处,而奇数采样中采样点在方格中心。如下图,如果采用经验1的方法,那么我们看看将2x2降采样到1个像素是怎么的情况。

 

时间: 2024-08-02 14:41:07

HDRPipeline DX9的相关文章

vc6 0-请教一下安装了DX9,VC6.0不显示函数的问题

问题描述 请教一下安装了DX9,VC6.0不显示函数的问题 请教一下各位大神,我在电脑上安装了DX9 sdk之后,在目录中把include和lib都包含进去了,但是在写的过程中像打"lpD3DDevice->"后没有显示函数的列表,也没有参数提示,这是声明的"LPDIRECT3DDEVICE9"的. 但是声明的"LPDIRECT3DDEVICE"设备后,"lpD3DDevice->"就有函数显示了. 请问一下怎么让

ShadowMap DX9

 ShadowMap基本的思想很简单,首先从聚光灯角度对场景建立并保存场景深度.然后在正常渲染场景中,比较每个渲染点到灯的距离值(或者说到灯的深度值)是否比对应的已经建立在场景深度中的值要大,也就是说要远,如果远证明从当前视点观察的此点在灯角度中看不见,所以该渲染点处于阴影中,否则,不然.   首先分析一下ShadowMap的优劣: 优点: ShadowMap只适合较近距离的阴影投射,由于32位浮点数的精度有限,所以在较远距离下,会将在阴影边界附近出现错误现象.一种是隐隐约约的阴影(即阴影中带有

错误信息-编译DX9程序出现奇怪的错误,请大牛帮忙解决,谢谢

问题描述 编译DX9程序出现奇怪的错误,请大牛帮忙解决,谢谢 1>g:directx 2007included3dx9math.h(787) : error C2143: syntax error : missing ',' before '*' 1>g:directx 2007included3dx9math.h(792) : error C2143: syntax error : missing ',' before '*' 1>g:directx 2007included3dx9m

ParallaxOcclusionMapping( POM ) DX9

ParallaxOcclusionMapping(后面成为POM)是一个不错的高级技术,在我看来它是至今让我印象最深刻的技术.与其说是视差,不如说准确的视线与高度图交点算法.在<Real-time Rendering>中也见过他的前身-ParallaxMapping,但是POM的精确度更高,对于斜视效果也很不错,这将让它在未来的重要技术中占有一席之地.闲话少说,还是重在实质技术.   在DX9的samples中,由ATI提高的POM案例,确实是一个不错的实践机会.看过2006的Dynamic

ShadowVolume DX9

 之前写过ShadowVolume,但是那是老版本(DX8)的DXSDK中的sample.而老版本并不是一个很好的解决方案.而DX9中的ShadowVolume还算是比较可取的方案.在这里主要对DX9中的ShadowVolume中的重点难点进行梳理.详细的细节,必须参考sample中的代码.   DX9中的shadowVolume最大的特点是建立了阴影体网格,而不是之前DX8中的动态生成轮廓边集合.建立阴影体网格最大的好处就是通过GPU来分担原来由CPU负责的轮廓边识别.而且由于新的阴影体积总体

DX9.0与opengl2.0的转换

问题描述 用DX9.0及HLSL写的地形渲染算法对应转换为opengl2.0来实现,有没有高手从事过相关方面的开发经验或相关资料,望不吝赐教... 解决方案 解决方案二:求解啊....解决方案三:使用ANGLE,你可以搜索ANGLE项目.

SkinnedMesh DX9

本想学习PRT技术,但是觉得这个技术太高级,而且就中国现在的技术来看,还未到这个程度.但是PRT技术一定要学,一定要掌握,才能不致于落后国际水平太多.这几天学习了一下骨骼动画.以前记得参加齐鲁软件大赛的时候,用Ogre很简单的就实现了骨骼动画.现在终于可以自己在DX基础上亲手完成这个3d游戏中最重要的技术.   骨骼动画中有许多我们需要注意的.简单屡一下骨骼动画中需要知道的基本知识点. 首先我们需要一个骨架.这些骨架中的骨骼有父子关系,有兄弟关系.父关节的运动是会带动子关节的.就像我们的上臂动会

MultiAnim DX9

这个案例比SkinnedMesh多的我觉得只是与骨骼动画更多的接口的认识.   MultiAnim主要的知识是: 在D3D中,一个动画控制接口有多个轨道,每个轨道上都独立的控制.我们可以控制轨道是否启用,速度,权重,优先级别.然后同个优先级别的每个轨道的动画会按对应的权重进行混合,最后不同优先级别再度混合.   这种独立有条理的结构同时也可以实现一个动画平滑过渡到另一个动画.   这些在我上传的d3dx_skinnedmesh.pdf都提及到了,而且系统全面.这里只总结MultiAnim中给我更

Post Process DX9

这个案例是一个大杂烩,它把很多常用的操作以单独模块的形式进行组装以实现一定的效果.这里面最重要的是所有的这些技术都是后处理技术,也就是在正常渲染完成后对生成的场景帧(或者说纹理,图片)进行加工处理.Post Process与以往案例最大的不同在于将物体的几何信息分别存贮在不同的渲染表面中.这样做的好处,在后处理中仍然能得到需要各种的信息.另外后处理的一个强大之处在于,当场景有多个或多种灯光时,我们不用对物体一一采用各种光照模型,因为很多像素对应的fragment(将要写入这个像素的某个物体小碎片