转载请保留出处:
http://xiaxveliang.blog.163.com/blog/static/297080342013467552467/
在开发一些相对较大的场景时,如:一片铺满相同草地纹理的丘陵地形,如果不采用一些技术手段,就会出现远处的丘陵较近处的丘陵相比更加的清晰的视觉效果,而这种效果与真实世界中近处的物体清晰远处物体模糊的效果是相违背的。
这是因为采用“透视投影”进行三维场景的绘制过程中,会产生近大远小的效果,而远处的丘陵与近处丘陵在绘制过程中采用的却是同一幅纹理图。如图1、2所示为未采用Mipmap纹理贴图和采用Mipmap纹理贴图后的运行效果图。
图1 未采用Mipmap纹理贴图的运行效果图
图2采用Mipmap纹理贴图后的运行效果图
从两幅运行效果图可以看出,图1近处山体与远处山体在视觉效果上清新程度几乎相同,图2远处的山体较近处相比较产生了模糊的效果。
观察了采用生成Mipmap纹理的山体运行效果图后,下面对对Mipmap纹理的生成进行介绍。
与直接进行纹理贴图相比,生成Mipmap纹理不但要经过,纹理id的生成、纹理id的绑定、纹理过滤、指定纹理图像几个阶段还要有一个生成Mipmap纹理的阶段。
此处重点介绍生成Mipmap纹理过程中的,纹理过滤与生成Mipmap纹理两个阶段。
1、代码
生成Mipmap纹理时绑定纹理、纹理过滤阶段的代码如下:
GLES20.glEnable(GLES20.GL_TEXTURE_2D);//启用纹理
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, id); //绑定纹理
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, //设定Mipmap纹理的过滤方式
GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR_MIPMAP_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,设定Mipmap纹理的过滤方式
GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR_MIPMAP_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, //设定纹理S坐标方向的拉伸方式
GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, 设定纹理T坐标方向的拉伸方式
GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bmp, 0); //加载纹理
GLES20.glGenerateMipmap(GLES20.GL_TEXTURE_2D);//生成一组Mipmap纹理图像
其中代码第1行中的GLES20.glEnable(GLES20.GL_TEXTURE_2D)也可以不在此处给出,这句代码也可在GLSurfaceView中的onSurfaceCreated方法中给出。
2、glTexParameter*方法介绍
glTexParameter*方法的作用为设置纹理属性。
函数原型:
void glTexParameterf (int target, int pname, int param)
void glTexParameteri (int target, int pname, int param)
参数的含义:
target——为处于激活状态的纹理单元指定纹理类型。参数为GL_TEXTURE_2D。
pname——指定纹理参数,pname可以为GL_TEXTURE_MIN_FILTER, GL_TEXTURE_MAG_FILTER, GL_TEXTURE_WRAP_S 或者 GL_TEXTURE_WRAP_T。
param——param的值根据pname参数的不同而取不同的值,如表2-1、表2-2所示。
表2-1放大或缩小时的过滤方法
pname参数 | param值 |
GL_TEXTURE_MIN_FILTER GL_TEXTURE_MAG_FILTER | GL_NEAREST、GL_LINEAR、 GL_LINEAR_MIPMAP_LINEAR、 GL_LINEAR_MIPMAP_NEAREST、 GL_NEAREST_MIPMAP_LINEAR、 GL_NEAREST_MIPMAP_NEAREST |
表2-2重复和截取纹理
pname参数 | param值 |
GL_TEXTURE_WRAP_S GL_TEXTURE_WRAP_T | GL_REPEAT GL_CLAMP_TO_EDGE |
3、纹理过滤
(1)代码举例
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, //设定Mipmap纹理的过滤方式
GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR_MIPMAP_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, //设定Mipmap纹理的过滤方式
GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR_MIPMAP_LINEAR);
(2) GL_TEXTURE_MIN_FILTER与GL_TEXTURE_MAG_FILTER的区别
当纹理图中的一个像素对应到待映射图元上的多个片元时,采用MAG采样;反之则采用MIN采样。
(3) 过滤方式下param各个值的含义如下表3-1所列。
表3-1 过滤方式下param各个值的含义
param值 | 含义 |
GL_NEAREST | 在纹理基层上执行最邻近过滤 |
GL_LINEAR | 在纹理基层上执行线性过滤 |
GL_LINEAR_MIPMAP_LINEAR | 在mip层之间执行线性插补,并执行线性过滤 |
GL_LINEAR_MIPMAP_NEAREST | 选择最临近的mip层,,并执行线性过滤 |
GL_NEAREST_MIPMAP_LINEAR | 在mip层之间执行线性插补,并执行最临近的过滤 |
GL_NEAREST_MIPMAP_NEAREST | 选择最临近的mip层,并执行最临近的过滤 |
总之MIPMAP_后面的参数为如何在Mipmap这一组纹理中选择哪一个或者哪几个纹理进行纹理贴图;GL_后面的参数为如何在选定的纹理上进行纹理采样。
4、纹理的重复和截取
(1)代码举例
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, //设定纹理S坐标方向的拉伸方式
GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, //设定纹理T坐标方向的拉伸方式
GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
(2) GL_CLAMP_TO_EDGE与GL_REPEAT值的含义如表4-1所示
表4-1纹理的截取与重复
param | 含义 |
GL_CLAMP_TO_EDGE | 截取纹理 |
GL_REPEAT | 重复纹理 |
(3) GL_REPEAT与GL_CLAMP_TO_EDGE的含义介绍
一般我们给定纹理的在S与T方向的纹理坐标时都是在[0,1]之间的,但纹理在S与T方向的坐标值也是可以大于1的,当给定纹理的在S与T方向的坐标值分别为[0,4]时,在纹理坐标的S与T方向上,若设置纹理重复方式均为GL_REPEAT重复方式,那么运行效果图如图4-1所示。
图
4-1 纹理的 S与 T方向均为 GL_REPEAT重复方式当给定纹理的在S与T方向的坐标值分别为[0,4]时,在纹理坐标的S与T方向上,若设置纹理重复方式均为GL_CLAMP_TO_EDGE截取方式,那么运行效果图如图4-2所示。
图
4-2 纹理的 S与 T方向均为 GL_CLAMP_TO_EDGE重复方式5、GLES20.glGenerateMipmap(GLES20.GL_TEXTURE_2D)方法介绍
GLES20.glGenerateMipmap(GLES20.GL_TEXTURE_2D)为指定的纹理对象生成一组Mipmap纹理,英文API为:generate a complete set of mipmaps for a texture object。
函数原型:
void glGenerateMipmap (int target)
参数含义:
target——为处于激活状态的纹理单元指定纹理类型。参数为GL_TEXTURE_2D。