纹理映射
纹理映射,又称纹理贴图,是把一幅图像贴到三维物体的表面的过程。在基于图像的三维建模系统中,纹理映射包含两个步骤:首先,利用图像序列和网格模型生成一张纹理图像,这张纹理图像又被称为 纹理地图集(TextureAtlas); 然后,建立纹理地图集中的 纹理像素 (Texel)和 网格模型顶点 之间的映射关系。
1 纹理地图集的生成
纹理地图集可参照Callieri等[42]提出的算法实现,算法的输入是一个真实物体的三维模型和一个已知摄像机参数的RGB图像集。执行流程分为4步:可见性计算、面片生成、纹理块打包、颜色匹配和连续性优化。
2 纹理映射
纹理映射 具体来说,就是将 纹理像素(u,v) 和物体 空间顶点(x,y,z) 的对应[43],就是寻找映射函数 f ,使得(u,v)= f (x,y,z)。
其中uv纹理坐标系的取值范围在[0,1],一般取纹理图像左下角为(0,0),右上角为(1,1)。
纹理坐标uv的定义 和纹理尺寸以及形状没有关系 。对于任何一个纹理,它的u和v的值都是从0到1,例如uv(0,0)代表纹理的左下角,uv(0.5,0.5)代表纹理的中心的,uv(1,1)代表纹理的右上角。
当知道一个三角形三个顶点对应到纹理上的uv坐标后,就可以通过 重心坐标 来计算出该 三角形内任意一点 所对应的 uv 。然后通过uv坐标即可在 纹理上采样到对应的颜色值 ,这样就把该图映射到了物体上。
对于拥有复杂结构的三维物体来说,直接计算二维纹理空间和三维物体之间的映射关系比较复杂,一般采用 Bier 和 Sloan 提出的两步纹理映射法[23]。两步纹理映射法采用一个 中介曲面作为过渡 ,将纹理空间到物体空间的映射分为 纹理空间到中介曲面 ,和 中介曲面到物体空间 两步映射。常见的中介曲面有平面、球面、圆柱面等。以圆柱面为例,对于圆柱面纹理映射[44],由圆柱面的参数方程定义,可以得到纹理映射函数。如果参数方程如下所示:
那么,给定圆柱面上一点(x, y, z),可以用下式反求参数:
Pietroni等人[45]选择一个抽象的基网格域作为中介曲面,基网格域中每个子区域是一个单位长度的等边三角形。这种方法能够保留原始网格的拓扑信息,而且造成的几何变形较小[46]。
3 openGL加载纹理
为了使纹理图像可用于OpenGL管道中的着色器,需要从图像(.jpg、.png、.gif或.tiff)中提取颜色,并将其放入OpenGL纹理对象(OpenGL内置结构)。许多读取和处理图像文件的C++库,包括Cimg、Boost GIL和Magick++。 SOIL2 是专门为OpenGL设计的库,利用其加载纹理到OpenGL程序的一般步骤:
(a)使用SOIL2实例化OpenGL纹理对象,并将图像文件中的数据读入其中;
(b)调用glBindTexture()使新创建的纹理对象处于活动状态;
(c)使用glTexParameter()函数调整纹理设置。结果是现在可用的OpenGL纹理对象的整数ID。
进行纹理处理开始于声明GLuint变量,这是用于保存引用OpenGL对象的整数ID。接下来,调用SOIL_load_OGL_texture()来实际生成纹理对象,该函数接受图像文件名作为其参数之一。这些步骤在以下函数中实现:
GLuint loadTexture(const char *texImagePath) {
GLuint textureID;
textureID = SOIL_load_OGL_texture(texImagePath,
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,