转自http://blog.163.com/mt_lty/blog/static/592999522010163435446/
纹理实际上是一个二维数组,它的元素是一些颜色值。单个的颜色值被称为纹理元素(texture elements)或纹理像素(texel)。每一个纹理像素在纹理中都有一个唯一的地址。这个地址可以被认为是一个列(column)和行(row)的值,它们分别由U和V来表示。
纹理坐标位于纹理空间中。也就是说,它们和纹理中的(0,0)位置相对应。当我们将一个纹理应用于一个图元时,它的纹理像素地址必须要映射到对象坐标系中。然后再被平移到屏幕坐标系或像素位置上。
Direct3D直接将纹理空间中的纹理像素
映射到屏幕空间中的像素,跳过了中间过程,从而提高了效率。这一映射过程实际上是一个相反的(inverse)映射。也就是说,对于屏幕空间中的每一个像素,我们来计算相应的纹理空间中的纹理像素位置。对那一点上的或那一点周围的纹理颜色进行采样(sample)。采样过程被称为纹理过滤(texture filtering)。
纹理中的每一个纹理像素可以通过它的坐标来声明。但是,为了将纹理像素映射到图元上,对于所有纹理上的所有纹理像素,Direct3D需要有一个统一的地址范围。因此,它使用了一个通用的地址方案,在这个方案中所有纹理像素地址的范围都在0.0到1.0之间,包括0.0和1.0。Direct3D程序用U、V的值来声明纹理坐标,它和用x、y坐标来声明二维迪卡尔坐标系一样。
在这种情况下,不同纹理中的同一纹理地址又可能被映射为不同的纹理像素坐标。如左面插图中的纹理地址(0.0,0.5)。由于纹理的大小有所不同,因此纹理地址将会映射为不同的纹理像素。左边的纹理1,大小为5x5,纹理地址(0.0,0.5)映射到纹理像素(0,2);右边的纹理2,大小为7x7,纹理地址(0.0,0.5)映射到纹理像素(0,3)。
左图展示了一个简单的纹理像素映射的过程:
我们要给图中左边的像素确定一定的颜色。像素四个角的地址被映射到对象空间中的图元上,这时,像素的形状会有一些变形,这是由图元的形状和观察的角度造成的。然后,与像素角相对应的图元表面上的几个角被映射到纹理空间中。这一映射过程再次使像素的形状产生变形。像素最终的颜色值就由该像素映射到的区域中的纹理像素计算而得。在设置纹理过滤方法时,要决定Direct3D使用什么方法来得到像素的颜色。
程序可以直接将纹理坐标分配给顶点。这一能力使我们能够控制将一个纹理的哪些部分映射到一个图元上。现在假定我们要创建一个矩形图元,它的大小恰好与下图中纹理的大小一样。我们要将整个纹理都映射到一整堵墙上,那么分配给图元顶点的纹理坐标就应该是(0.0,0.0)、(1.0,0.0)、(1.0,1.0)和(0.0,1.0)。
现在我们要将墙的高度缩小一半。我们可以将纹理变形以适应墙的变化,也可以在分配纹理坐标时只使用纹理的下面一半。
如果使用纹理变形或缩放的方法,那么所使用的纹理过滤方法就会对图象的质量产生影响。详细内容见“纹理过滤”。
如果采用分配纹理坐标的方法,那么分配给图元顶点的纹理坐标就应该是(0.0,0.0)、(1.0,0.0)、(1.0,0.5)和(0.0,0.5)。Direct3D会将纹理的下面一半应用到墙上。
有时,一个顶点的纹理坐标可能比1.0大。当分配给顶点的纹理坐标不在0.0到1.0(包括它们)范围内时,就要设置纹理寻址模式了。