1、 What`s Bump Mapping?
Bump Mapping通过改变几何体表面各点的法线,使本来是平的东西看起来有凹凸的效果,是一种欺骗眼睛的技术:)。
我们知道,如果几何体表面有高低不平的凹凸,那么表面上各点的法线方向就会不同, 那么当光照射到这些点上时,各点光照产生效果就不一样,那么我们最终看到的各点就是凹凸不平的。如果几何体表面是平的,但是各点的法线方向各不相同,当用光照模型进行光照计算后,我们看到最终渲染出来的图会是什么样呢?会看到高低不平的凹凸效果。
Bump Mapping把各象素法线相关的信息存于一张Texture中,各象素的法线就是通过从这张Texture中Sample得到的信息,进行一定的计算得到。根据Sample的方法和计算的方法不同,分为了Bump Mapping,Normal Mapping,Parallax Mapping,Parallax Occulision Mapping,Relief Mapping等等。
Bump Mapping这种思想最早是由图形学届大牛中的大牛Jim Blinn提出的,后来的Normal Mapping, Parallax Mapping,Parallax Occulision Mapping,Relief Mapping等等,均是基于同样的思想,只是考虑得越来越全面,产生的效果越来越好。
2、 Why Bump Mapping?
如果要在几何体表面表现出凹凸不平的细节,那么在建模的时候就会需要很多的三角面,如果用这样的模型去实时渲染,出来的效果是非常好,只是性能上很有可能无法忍受。Bump Mapping不需要增加额外的几何信息,就可以达到增强被渲染物体的表面细节的效果,可以大大地提高渲染速度,因此得到了广泛的应用。
3、 Bump Mapping
Jim Blinn在1978发表了一篇名为:“Simulation of Wrinkled Surfaces”,提出了Bump Mapping这个东东。Bump Mapping通过一张Height Map记录各象素点的高度信息,有了高度信息,就可以计算HeightMap中当前象素与周围象素的高度差,这个高度差就代表了各象素的坡度,用这个坡度信息去绕动法向量,得到最终法向量,用于光照计算。坡度越陡,绕动就越大。那么,根据HeighMap如何计算Normal呢?
设当前象素纹理坐标为(u,v),切线空间中切向量为T(对应纹理空间U方向),负法线为B(对应纹理空间V方向),Height(u,v)表示纹理坐标(u,v)处的高度值。
du=1/HightmapWidth,dv = 1/Hightmap Height所有计算均是在切线空间,计算公式如下:
u_gradient = Height(u-du, v) - Height (u+du, v) (U方向的坡度)
v_gradient = Height(u, v-dv) - Height (u, v+dv) (V方向的坡度)
New_Normal = Normal + (T * u_gradient) + (B * v_gradient)(Normal是当前象素切线空间的Normal)。用shader片断如下:
float u_gradient = tex2D(HeightMap,texcoord+float2(-du,0) )-
tex2D(HeightMap,texcoord+float2(+du,0));
float v_gradient = tex2D(HeightMap,texcoord+float2(-dv,0))-
tex2D(HeightMap,texcoord+float2(dv,0));
float normal = normal + Tangent*u_gradient+Binormal*v_gradient;
4、 Normal Mapping
Normal Mapping也叫做Dot3 Bump Mapping,它也是Bump Mapping的一种,区别在于Normal Mapping技术直接把Normal存到一张NormalMap里面,从NormalMap里面采回来的值就是Normal,不需要像HeightMap那样再经过额外的计算。
NormalMap一般都是由HeightMap离线生成,建模工具(如Max,Maya)一般都支持导出模型的NormalMap,一般都是由高模导出NormalMap,在渲染的时候用低模+高模导出的NormalMap,在PixelShader采样出Normal值,中运用某种光照模型,运行逐象素光照。
值得注意的是,NormalMap存的Normal是基于切线空间的,因此要进行光照计算时,需要把Normal,Light Direction,View direction统一到同一坐标空间中。一般的做法是在VS中把Light Direction和View Direction变换到Tangent Space,通过硬件Rasterrize后,在PS中便统一到切线空间,可以直接计算。Normal Map的Shader网上可以搜出一堆,这里就不贴啦。
5、 Parallax Mapping
当使用Normal Mapping技术时,并没有把视线方向考滤进去。在真实世界中,如果物体表面高低不平,当视线方向不同时,看到的效果也不相同。Parallax Mapping就是为了解决此问题而提出的。
Parallax Mapping首先在一篇名为“Detailed Shape Representation with Parallax Mapping”的文章中提出。它的基本思想如下图示(本图来自Parallax Mapping with Offset Limiting: A PerPixel Approximation of Uneven Surfaces)。在图示的视线方向,如果表面是真正的凹凸不平的,如real surfacer所示,那么能看到的是B点,因此用于采样法线的正确纹理坐是TB而不是TA。
因此,我们需要对纹理坐标作偏移,为了满足实时渲染的要求,采用了取近似偏移的方法(如下图示),这种近似的算法已经可以达到比较好的效果。具体的offset计算可以参考:“Parallax Mapping with Offset Limiting: A PerPixel Approximation of Uneven Surface”,里面有详细的讲解。
6、 Parallax Occlusion Mapping
Parallax Occlusion Mapping是对Parallax Mapping的改进,DirectX SDK中有个Sample专门讲这个,相关细节可以参看此Sample. Parallax Occlusion Mapping中实现了Self Shadow,还计算了比较精确的offset,复杂度比Parallax Mapping大,但是实现效果更好。
7各种Mapping的比较。
|
高度图 |
法线图 |
随视点变化 |
自阴影 |
性能 |
Bump Mapping |
需要 |
不需要 |
否 |
无 |
快 |
Normal Mapping |
|
需要 |
否 |
无 |
快 |
Parallax Mapping |
需要 |
需要 |
是 |
否 |
较快 |
Parallax Occlusion Mapping |
需要 |
需要 |
是 |
是 |
慢 |