Bump Mapping概述
1. 概述
无论是程序员还是美工人员,几乎每个游戏开发者都知道一些3D图形学的知识,因此每个人都或多或少了解一点bump mapping。Bump mapping是在像素级别扰动物体表面法向量的一种光照技术,它一般采用纹理映射作为输入表示扰动的大小。在光照计算时考虑到扰动的法向量,不需要增加额外的几何信息就可以增强被渲染物体的表面细节。
Bump mapping在许多离线渲染系统中已经存在很久了,并且现在也已成为实时渲染引擎的标准。可是,在实时渲染引擎中实现Bump mapping的技术也有很多种,从非常简单的到非常复杂的,不是所有的图形程序员都很熟悉它们。本文的目标就是向Bump mapping初学者介绍最重要的实时技术,解释围绕着这些技术的难题。
2. 最初的方法
Bump mapping最初由Jim Blinn在1978年发明,他发表了一篇名为 “Simulation of Wrinkled Surfaces”的论文。Blinn使用了一种灰度高度图(grayscale height map)来建模物体表面法向的扰动,扰动法向量的大小用某些表面参数(典型的为纹理坐标)的偏微分和高度图来计算。这些微分表示了某些潜在值的变化率,因此,如果高度的微分值很大,则表示高度图中该点坡度很陡。
正如上面所说的,这些扰动的法向量需要加入光照模型中进行计算,这就暗示说所采用的光照模型必须是像素级的("Phong shading"),而不能是顶点级的("Gouraud shading")。这里必须指出"Phong shading"和"Phong's lighting model"是不同的概念,尽管鲜见有人作出区分。Phong shading意思是插值顶点法向量在片元(fragment)级别计算光照公式,而Gouraud shading意思是逐顶点计算光照公式,最后再插值颜色。Phong光照模型(Phong's lighting model)只是一种特定的计算光照的公式,可以在顶点级别也可以在片元级别进行计算。例如OpenGL的标准光照是基于Phong光照模型但使用Gouraud shading。因此,bump mapping可以看作为Phong shading的扩展(使用bump map来扰动法向量),但并不是说你必须用Phong光照模型。
3. 实时技术
下面的几段将讨论bump mapping实现的不同方法,我们从最简单的开始逐渐过渡到最复杂的技术。
3.1 Emboss bump mapping
Emboss bump mapping也是采用一张height map,就像Blinn的最初方法,但它不是计算逐像素扰动的法向量,而是直接计算光照密度。因此,与Blinn的bump mapping技术不同,不能随意选择光照模型。
实现emboss bump mapping的第一步是对height map进行预处理产生两个分离的映射图。第一张图具有原始height map一半的明亮度,第二张具有原始height map反转图一半的明亮度。绘制需要分三步完成(当然可以用多纹理方法一步完成),第一遍绘制使用半明亮度图;第二遍采用反转半明亮贴图,但纹理坐标需要朝着光源方向做微小的偏移,同时采用 “Additive blending”纹理混合模式;最后一遍使用逐顶点的光照模型并将结果与原来的纹理相乘。下图显示了前两步的处理过程。
因为没有计算扰动的法向量,emboss bump mapping只能用于diffuse lighting中,因此这种技术缺乏实用性,但由于几乎不需要任何的特殊硬件支持,它可以用标准OpenGL1.1实现,甚至可以不使用多纹理技术。
3.2 Environment-mapped bump mapping (EMBM)
环境影射bump mapping最初由Bitboys开发,但实际将这种技术带入市场的显卡是Matrox G400。EMBM扰动纹理坐标而不是法向量,其输入纹理是一个二维的DU/DV图像:其中的纹理像素表示应用到U/V纹理坐标上的偏移量。换句话说,存取特定图元的纹理坐标是(U + DU, V + DV),其中U和V分别表示逐顶点插值的纹理坐标,DU和DV则是从bump map中获得。
从扰动的纹理坐标来实现bump mapping效果,你的光照必须来自纹理。典型的是,纹理可以是一个环境映射(因此命名为EMBM),用来存取这些纹理的纹理坐标可以用表面法向量的函数计算获得。环境映射可以是基于视线的也可以不是,并且可以用于仿真散射与镜面光照。因此,逐像素扰动环境映射纹理坐标可以仿真扰动法向量的bump mapping效果而不必真正地计算法向量。
典型的,这种DU/DV bump map产生自一个灰度高度图(grayscale height map),通过查询高度值的微分,可以得到:物体表面越陡,DU/DV就越大。注意偏移是有符号的值,因此需要缩放到0~255这个范围,当运用这个映射进行渲染时,你需要将这个值再映射到-1~1这个范围。
很明显,EMBM也可以应用于环境反射(环境映射的典型用法),这意味着你可以用它来仿真凹凸反射物体。这向着实现真实的bump mapping效果前进了一大步,但是你仍然没有存取扰动的表面法向量,因此从环境图中提取的信息量限制了可以选择的光照模型。
3.3 Normal mapping
Normal mapping是当前最通用的实时bump mapping技术,该技术最初来源于Peercy等人的论文"Efficient Bump Mapping Hardware"。输入纹理是一个normal map,在其不同的颜色通道中记录了扰动的表面法向量。像DU/DV maps一样,normal maps典型地产生于一个高度场,高度值的偏微分可以用于计算扰动表面的坡度,因此也可以用于计算扰动的法向量。法向量的XYZ分量可以被编码进纹理的RGB通道来产生最终的normal map。
上图显示了一个height map以及由它产生的normal map。这个normal map的XYZ分量已经从-1~1的范围放大到0~255范围,向量[0, 0, 1]将被转化为RGB 颜色 [127, 127, 255],因此,这个紫/蓝色是normal map的主色调。
这里有一个非常重要的问题:这些法向量处于哪个坐标系统?它们是相对于最初height map的“地平面(ground plane)”进行计算的,当对一个模型应用这个normal map时,必须假设 [0, 0, 1]法向量对应于最初未扰动的表面法向量。Blinn使用height maps时也会遇到同样的问题,他使用表面纹理坐标的偏微分来构造法向量的坐标系统。这种坐标系统叫做“切空间(tangent space)”——其X和Y坐标轴与UV纹理坐标平行,Z轴垂直于纹理表面,X和Y轴通常叫做"tangent"和"binormal"向量,Z轴对应于未扰动的表面法向量。
Blinn对每个像素计算其切空间用于在模型坐标系统中产生扰动的法向量,Peercy在论文“Efficient Bump Mapping Hardware”中引入了一种更加高效的方法,只在顶点级预先计算tangent 与 binormal 向量,在实际绘制时,每个顶点处的表面点->光源向量(surface-to-light vector)转化到切空间并且进行插值。在像素级别,单位化光源向量,因此现在你有了在同一坐标系统中的光源向量与扰动法向量,随后就可以在切空间中进行光照计算。
一旦具有了像素级别的表面法向量,就可以使用你所喜欢的任意光照模型,早期的显卡比如GeForce 和 Radeon只可以使用扰动的法向量执行简单的点乘操作(通常是三个分量的点乘操作,因此常被称为“Dot3 bump mapping”)。高质量的镜面光照计算很难,因为在这些显卡上不能进行取幂操作,比较新的显卡提供了更加灵活的片元处理功能,允许你用normal map实现更加先进的逐像素光照计算,并且利用表面法线可以实现各种反射折射以及更复杂的光线运算。
3.4 最初的height map方法
最新的显卡支持片元级别的偏微分运算,可以并行地运算四个或更多的fragments blocks(运用多片元管线),因此可以方便地计算相邻像素之间值的变化率。你可以实时地应用这个功能动态转化height map为normal map,这可以解决离线计算normal maps的麻烦,更方便美工人员制作bump map。
实时转化尽管增加了运算负载,但你可以在pixel shader中用height map进行其他目的的计算,不过至少在目前离线计算normal maps仍是明智的选择。
4. Bump Mapping没有的,并且也不是Bump Mapping的技术
4.1 Displacement mapping
Displacement mapping相对于bump mapping来说也使用height map来表示表面的扰动,不同的是displacement mapping实际修改表面的几何信息,而bump mapping只影响表面法向量。换句话说,displacement mapping增加了模型的几何细节,硬件加速的displacement mapping技术目前还很不成熟。
你可以在vertex shader中使用displacement mapping偏移顶点使之沿着法线方向偏移,即使你的显卡足够劲可以同时处理大量的顶点,你仍然需要调整真实顶点的位置。在没有某种自适应tessellation策略的情况下,取得较好可视结果需要处理的面片数目大的惊人,除非displacement map本身也可以实时产生。除此以外,displacement技术一般是不能实时应用的。
4.2 光照模型
经常有人抱怨说“bump mapping使真实的物体看上去像塑料”,尽管有证据支持这种说法(某些游戏应用了bump mapping技术),但不是bump mapping技术使物体看上去像塑料,是光照模型的原因。许多游戏使用了Blinn/Phong光照模型,如果加上镜面光照,看上去确实像塑料,可是如果应用同样的模型而不使用bump mapping,场景仍然看上去像塑料,这有可能更多的是美工的问题。
5. 更加先进的方法
5.1 细节保留
当讨论normal mapping的时候,我们注意到normal maps一般从一个height map生成,然而,采用将表面法向量渲染到纹理的方法,从模型也可以产生normal maps。“细节保留”技术采用了这种方法来实现模型简化,一个高模和一个低模作为输入,将高模的细节保存到一个纹理中,并将这个纹理贴到低模上。这种“细节”可以是任意的表面属性,包括颜色和法向量,如果你采用细节保留技术产生一个normal map,你就可以使用高LOD版本(high-LOD version)的光照信息渲染低LOD版本(low-LOD)的模型。
映射高模模型到低模模型,低模必须要有唯一的UV映射,例如纹理映射时不能有存取两次的图元。对于normal map中的每个图元,你可以计算该图元位置处低模上点的坐标,得到这点的表面法线并且沿着这个法向向量发射一条射线,根据这条射线与高模的相交点可以知道高模的表面法向量并将之存为一个normal map。注意这条射线是双向的,因为高模的表面可能在低模表面之前也有可能在其后。
这种技术也可以被称为"polybump"或"renderbump",前者来自于Crytek,一种细节保留工具“PolyBump”的开发者;后者,众所周知来自于Doom 3。
5.2 自阴影bump map
Bump mapping靠扰动表面法向量来影响光照,但扰动的法向量不会影响任何形式的阴影。因此,一个凸块(bump)将不会在另一个凸块上产生阴影。可是现在已经有方法允许bump maps产生自阴影,其中的一种技术叫做“horizon mapping”。一个horizon map是一种从特定点向各方向记录可见水平高度(the elevation of the visible horizon)的纹理。如果另外的一个点判断低于这个水平高度,可以认为该点相对于特定点不可见,与之相似的是,光源如果低于这个水平高度,就不会照亮对应的特定点。
你可以在切空间对光源向量执行这种可见性检查,就可以产生自阴影bump maps,其主要的缺点是horizon maps占用过多纹理内存,而且计算量很大。上图展示了horizon mapping绘制的情况,这个复杂场景只绘制了一个四边形,绿线表示光源的照射方向。
5.3 Parallax mapping
尽管bump mapping可以极大地增强场景渲染的真实感,但其仍然只是一种基于纹理的技术,这意味着绘制表面始终仍为“平(flat)”的。Displacement mapping技术靠修改实际几何表面来解决这个问题,但是如前所述,在实时绘制系统中目前并不是最实用的技术。视差映射(Parallax mapping)是一种先进的bump mapping技术,在一定程度上可以弥补以上缺陷而不需要displacement mapping那么复杂的运算。摄像机在物体表面平移时,视差映射可以给你一种合适的视差效果,不必修改实际的几何信息。因此,当你低于一定的角度观察一个平面时,虽然可能仍感到它是平的但物体的轮廓不会收到影响。
视差映射,也被称为"offset mapping"或"virtual displacement mapping",也需要一个height map作为输入,这种视差效果可以通过将每个图元处的纹理坐标向眼睛方向偏移一定距离来实现,偏移的长度可以根据该位置处height map的值估算。
对于已存在的bump mapping shader来说,Parallax mapping只增加了较少的指令,但结果却好的多。你的shader程序需要一个height map,这通常不是问题,它可以保存在normal map的alpha通道中,也可以分开保存,甚至你只需要一个height map,用它来实时计算法向量。
5.4 Z-correct bump mapping
如果你想进一步提高渲染效果以实现displacement mapping那样的效果,你就需要使用Pixel Shader来修改渲染图元的Z值,除了使用一个height map作为输入外,必须向着视线方向偏移Z值。这种技术仍然不会改变场景的实际几何信息,但当两个物体接触或相交时,相交处会随着表面的凹凸情况发生变化而不仅仅表示为一条直线。
Z-correct bump mapping有一个很大的缺陷,在pixel shader中修改Z值会禁止图形硬件的早期深度测试优化。早期深度测试优化可以在pixel shader执行前去除深度测试失败的图元,这可以极大地增进性能,如果shader修改了深度值,早期深度测试优化将不会执行。
逐像素的光照计算在处理独立光源之前,通常要计算环境光部分(Z+ambient pass),这部分计算正需要用到早期深度测试优化。因此,禁止深度测试优化可能极大地影响绘制效率,其不利影响甚至超过几条pixel shader指令带来的优化效果。
6. 结论
Bump mapping背后的基本技术就是扰动用于光照计算的表面法向量。Blinn的原始方法需要计算height map的坡度来产生扰动的法向量,这种方法近年来才被用于实时系统。我们还讨论了一些更加实用的bump mapping方法,首先的两种技术是emboss bump mapping 和 EMBM,它们都不是真正计算扰动的法向量,因此这使它们并不灵活,可能不值得大量应用。
我们讨论的第三种技术是normal mapping,它是当前使用的标准方法,normal mapping真正地扰动表面法向量,这意味着理论上其可以应用于任何光照模型。实际上,采用的光照模型受限于显卡的硬件性能与片元处理能力,早期的显卡实现normal mapping相当受限制,仅仅计算散射光照部分,你不得不对每个光源都采取多遍渲染,而更新的显卡可以实现更加专业的光照模型。
之后,我们讨论了一些bump mapping的先进应用。细节保留技术允许你用高LOD模型细节来渲染一个低LOD模型。自阴影的bump maps可以在表面的凹凸块上产生自阴影来增加场景的深度信息。视差映射仿真视差效果增加了更多的深度信息,如果跟随摄像机在物体表面平移,你可以看到更加真实的几何细节。Z-correct bump mapping扰动两个相交物体相交处的轮廓来更进一步增加真实感。
分享到:
相关推荐
用OpenGL实现的凹凸映射的详细VC++代码,含镜面反射
tangent bump mapping developed by dev c++
GLSL bump mapping 讲解及编程
Bump mapping is a normal-perturbation rendering technique for simulating lighting effects caused by patterned irregularities on otherwise locally smooth surfaces. By encoding such surface patterns in ...
使用基于硬件支持的dot3来实现bump效果,基于vc6和ogl编写。只有可编程的显卡才能运行。
在Linux中用CG在OpenGL中实现凹凸映射技术
BUMP
在这次编程任务中,我们会进一步模拟...基础上,仔细阅读该函数中的注释,实现 Bump mapping. 6. 修改函数 displacement_fragment_shader() in main.cpp: 在实现 Bump mapping 的基础上,实现 displacement mapping.
Normal Mapping及3Dc压缩技术研究,谌显,杨克俭,Normal Mapping是当前最通用的实时Bump Mapping技术。采用Normal Mapping技术,不需要增加额外的几何信息就可以增强被渲染物体的表面细节。此��
随着现代电子装置对小型化、轻量化、高性能化、多功能化、低功耗化和低成本化方面的要求不断提高,IC芯片的特征尺寸不断缩小,且集成规模迅速扩大,...同一种功能的芯片而言可以加工成不同的封装形式,仅在Bump和Asse
凹凸纹理(Bump Mapping) 浮雕纹理
6. 修改函数 displacement_fragment_shader() in main.cpp: 在实现 Bump mapping 的基础上,实现 displacement mapping. 7. 双线性纹理插值: 使用双线性插值进行纹理采样, 在 Texture 类中实现一个新方法 Vector3f ...
很好用的Crazy Bump,不需要繁琐的破解,优化后的版本,解决了不能破解的问题。
bump.lua, 一种用于Lua的碰撞 bump.lua 轴线对齐矩形的Lua碰撞检测库。 它的主要特点是:bump.lua 仅对齐轴对齐框( AABB ) 冲突。 如果你需要比( 圆,多边形,等等 ) 更复杂的东西,那么你可以先查看一下 ,看一下。...
外部资源 代码文档和示例 图形库“Three.js using WebGL”: ://threejs.org/ 来自three.js的代码示例: : Three.js 食谱章节:1、3、10 TrackballControls 库,允许与鼠标交互。 图像资产 ...
CG Bump mapping tutorial.
Tutorial 20: Bump Mapping Tutorial 21: Specular Mapping Tutorial 22: Render to Texture Tutorial 23: Fog Tutorial 24: Clipping Planes Tutorial 25: Texture Translation Tutorial 26: ...
凹凸映射和纹理映射非常相似。然而,纹理映射是把颜色加到多边形上,而凹凸映射是把粗糙信息加到多边形上。
1.Tangent Bumpmapping using nVidia's Cg 2.Dynamic Cube Mapping 3.Cube Mapping Demo 4.Multiple levels of detail on Textures 5.Sinusoidal Scrolling (Sine Wave Spline Text) 6.Volition ………… 代码中...
提出了改进自组织迁移算法(Improved Self-Organizing Migrating Algorithm,ISOMA)。该算法通过在迁移过程中引入差分迁移方式来增加种群...利用该算法来求解高维约束问题——BUMP 问题,计算结果表明新算法的有效性。