Bump Mapping是在象素级别扰动物体表面法向量的一种光照技术,通过改变光照计算(light calculation)模拟物体的"Bumps".Bump mapping最初由Jim Blinn发表的一篇名为"Simulation of Wrinkled Surfaces"的论文.Blinn使用了一种灰度高度图(grayscale height map)来模拟物体表面法向量的扰动.
那么何为bump map?又如何建立bump map呢?
Bump map就是包含将应用于3D model上的浮雕信息(relief information)的一种纹理图.Relief information有几种表现形式,之一为elevation或height map,存储了每个象素的高度变量,通常以grayscale格式存储;之二为normal map,存储了纹理图每个象素的normal vector.此种情况下常把RGB值作为normal vector的3D坐标.
简而概之:Bump mapped rendered surface = Base_texture + Bump_mapped texture
关于Bump mapping的原理和算法在nehe lesson22和Emboss Bump Mapping by Michael I. Gold, nVidia Corp. [.ppt, 309K] 已有详细讲解,不再赘述.仅对一些要点及本人学习过程中遇到的一些问题做番解释.
C = (L·N)*Dl*Dm (1)
- L is light vector
- N is normal vector
- Dl is light diffuse color
- Dm is material diffuse color
(L·N) = (Fd + (H1-H0)) (2)
(H1-H0)即为我们建立的Bump_mapped texture.但是公式2中的(H1-H0)该如何实现呢?
在nehe教程中是这么创建的:
第一张图具有原始height map一半的明亮度(H0 = RGB/2);
第二张图具有原始height map反转图一半的明亮度(invertH1 = (255-RGB)/2);
第一遍绘制时使用H0,第二遍绘制时使用invertH1(切记,需对该纹理坐标朝光源方向做微小的偏移),同时采用"Additive blending"纹理混合模式(glBlendFunc(GL_ONE, GL_ONE), H = H0 + invertH1 * perturbed).若对invertH1不进行偏移,混合后为一(127,127,127)的灰度图.大家不妨一试 .此二图混合后,值大于0.5模拟了面向光源的表面,小于0.5则对应背向光源.
下一要点是计算light vector for each vertex
所有的vectors必须在同一坐标系下,object or world space.若把成千上万的片元(fragments)法向量(defined in object space)转换到world space(light is usually defined in the space),则需要大量的运算,so it is a better choice that transform the light position from world to local space using the inverse transformation matrix.
顺便介绍一下tangent space.
Tangent space一般由一组向量定义局部坐标系统(TBN, Normal vector, Tangent vector, Binormal vector),如下图所示:
T平行纹理U方向,B同时垂直于T和N.首先在已知纹理坐标U,V的前提下,在object space计算所有vertices的tangent space.
结合上面所述,我们就可计算light vector(已从world space转换到object space)在每个vertex的tangent space中的分量:
反转图的偏移方向由[LrelX 0 LrelZ]确定,对应纹理坐标方向U,V.
如果用multiTexture处理H0和invertH1,需硬件支持并对每个纹理单元进行相应的纹理信息设置(纹理图象,过滤器,环境,坐标及矩阵)
对GL_TEXTURE0_ARB指定当前纹理映射功能:
glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE);
glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE);
对GL_TEXTURE1_ARB指定当前纹理映射功能:
glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD);
glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD);
GL_COMBINE_EXT, GL_COMBINE_RGB_EXT, GL_ADD在OpenGL 1.2 Reference Manual有解释http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.aix.doc/libs/openglrf/glTexEnv.htm
在multitexture处理bump mapping中,有几行代码一直不解:
//disable second texture unit
glActiveTextureARB(GL_TEXTURE1_ARB);
glDisable(GL_TEXTURE_2D);
//bind base texture to texture unit 0
glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, BASETEXTURE);
glActiveTextureARB(GL_TEXTURE1_ARB);
glDisable(GL_TEXTURE_2D);
//bind base texture to texture unit 0
glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, BASETEXTURE);
请大虾们指点一番了
此文是本人学习当中的一些点滴,夹杂些许个人对此技术的理解,不当之处还望指出!
切记,切记,不可全信^_^
Embossed Bump Mapping是Bump Mapping中最简单的一种,缺乏实用性,只能用于diffuse lighting中,但不失为了解Bump Mapping的Primer technique.还有三种Bump Mapping技术,有待以后进一步挖掘(前进的动力啊,sigh),现把四种相关技术列表如下:
- Embossed Bump Mapping
- Perturbed UV Bump Mapping
- Perturbed Normals Bump Mapping
- Dot Product Bump Mapping
see also:
- 你不应该使用256x256的纹理,这会让处理变得缓慢。
- 一个具有凹凸贴图的立方体是不常见的,这和你的视角有关,因为三角面过于大了,如果要获得很好的视觉效果,你需要很大的纹理贴图,这必然会降低渲染速度。你可以把模型 创建为一些小的三角形,从而使用小的纹理,来获得好的效果。
- 你应该先创建颜色纹理,接着把它转换为具有深度的凹凸纹理
- 凹凸纹理应该锐化,这可以取得更好的效果,在你的图像处理程序中可以完成这个操作。
- 凹凸贴图的值因该在50%灰度图上波动(RGB=127,127,127), 亮的值代表凸起,暗的值代表凹陷。
- 凹凸贴图可以为纹理图大小的1/4,而不会影响外观效果。