1.1 纹理过滤
像素、片元都是具有面积的,一个像素可能对应物体上的一小块区域,而物体上这个小区域对应于纹理图像上的一个小区域,因此一个像素的颜色可能来自于纹理中的一小个不规则区域,如果纹理的分辨率比较高,则这个区域可能包含多个纹元(纹理中的单元,即纹元),由这几个纹元的颜色确定这个像素的颜色的过程就叫做纹理过滤。
1.2 一个像素一般不会正好对应于一个纹元(texel)。所以像素的颜色无法直接得到,需要经过一定的运算,这个过程就是纹理过滤。
1.3 纹理过滤的几种情况
- GL_TEXTURE_MAG_FILTER,如下左边;
- GL_TEXTUER_MIN_FILTER,如下右边;
纹理过滤的几种方式:
- GL_NEAREST:选择距像素中心距离最小的texel的颜色作为像素的颜色;
- GL_LINAR:选择距像素中心最近的四个texel的加权平均值作为像素的颜色;对于上述第一中情况,将会考虑邻居纹元的颜色;
采样上述方式,远处纹理会出现如下错误。
1.4 MipMap方法
当一个屏幕像素覆盖的纹理区域大于4个纹元甚至更多的时候,采用4个邻居的加权平均值作为像素颜色是不合理的。
1.4.1 mipmap方法
- 首先对纹理进行预处理,生成不同分辨率的版本;
- 纹理过滤时,首先选取合适的分辨率,然后进行Linear过滤;
假设,一个像素覆盖了四个纹元,那么就选择14\frac{1}{4}41那张分辨率的图片就行。如果一个像素覆盖了的纹元数量在4~16之间,那么就在14\frac{1}{4}41和116\frac{1}{16}161分辨率的图片各取一个值做加权平均即可。
1.4.2 对于GL_TEXTURE_MIN_FILTER方式,才需要采用mipmap方式。
如下、各种方式,远处的效果,近处采用的都是相同的方式,主要对比远处,可知GL_LINEAR_MIPMAP_LINEAR效果最优,也被称做三线性过滤。
1.4.3 mipmap层 的选择由系统自动完成,采用计算一个像素与其所覆盖的纹理区域的面积比例(取x、y方向上的最大缩放值),由此选定mipmap层。
1.4.4 mipmap的生成
- 可以调用gluScaleImage()来逐级生成;
- 通过glTexImage2D(GLenum target,GLint level,…)来进行加载;
更常用的方法是,调用如下方法,就可以生成所以mipmap层级并加载。
int gluBuild2DMipmaps(GLenum target,GLint components,GLint width,GLint height,GLenum fromat,GLenum type,const void* data);//在OpenGL3.0之后,这个函数被提升到了核心库中;
glGenerateMimmap(GLenum target);
1.4.5 Mipmap存在的问题
- 如果覆盖区域非常狭长,与正方形相差较大,效果不好。
- 正方形、圆形各个法向尺度一样,为各向同性滤波;
- 克服上述问题,可以采用各向异性滤波,即可以采用长方形来过滤;
如上图,途中黑白格为长方形时,采用各向异性滤波效果最优。
1.5 纹理坐标
做纹理映射,需要知道纹理坐标。纹理坐标可以自己指定、从模型文件中读取,也可以采用OpenGL自动生成纹理坐标。OpenGL中提供了五种自动生成纹理坐标的方式:
- GL_OBJECT_LINEAR :
- 设置三维空间中的一个平面;
- 计算当前顶点与该平面的距离;
- 以此距离作为一维纹理中的纹理位置,如果是二维纹理,则可以为s和t分别设置一个平面;
三维空间中的一个平面由(p1,p2,p3,p4)四个参数即可确定一个平面,即:
p1∗x+p2∗y+p3∗z+p4=0p1 * x + p2 * y + p3 * z + p4 = 0p1∗x+p2∗y+p3∗z+p4=0,三维空间中顶点到平面的距离计算为:
d=p1∗x+p2∗y+p3∗z+p4d = p1 * x + p2 * y + p3 * z + p4d=p1∗x+p2∗y+p3∗z+p4,则GL_OBJECT_LINEAR中的纹理坐标计算:
g=p1∗x+p2∗y+p3∗z+p4∗wg = p1 * x + p2 * y + p3 * z + p4 * wg=p1∗x+p2∗y+p3∗z+p4∗w,一般w为1,即齐次坐标,则g就是距离。
- GL_EYE_LINEAR :
1.5.1 操作步骤为:
指定坐标生成模式
在OpenGL中,(x,y,z,w)表示的是顶点,(s,t,r,q)表示的是纹理坐标,(u,v,w)可以表示纹理坐标。
指定参参考平面的参数:
打开纹理自动生成的开关:
1.5.2 更常用的纹理坐标自动生成为:
- GL_SPHERE_MAP
- GL_REFLECTION_MAP
- GL_NORMAL_MAP
可以实现类似于环境映射的效果,把环境映射到模型表面。