OpenGL ES2.0 生成Mipmap纹理

时间:2021-01-20 03:57:14

原文地址:http://xiaxveliang.blog.163.com/blog/static/297080342013467552467/

在开发一些相对较大的场景时,如:一片铺满相同草地纹理的丘陵地形,如果不采用一些技术手段,就会出现远处的丘陵较近处的丘陵相比更加的清晰的视觉效果,而这种效果与真实世界中近处的物体清晰远处物体模糊的效果是相违背的。

这是因为采用“透视投影”进行三维场景的绘制过程中,会产生近大远小的效果,而远处的丘陵与近处丘陵在绘制过程中采用的却是同一幅纹理图。如图12所示为未采用Mipmap纹理贴图和采用Mipmap纹理贴图后的运行效果图。

OpenGL ES2.0 生成Mipmap纹理

未采用Mipmap纹理贴图的运行效果图

OpenGL ES2.0 生成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方法中给出。

2glTexParameter*方法介绍

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_NEARESTGL_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_FILTERGL_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_EDGEGL_REPEAT值的含义如表4-1所示

4-1纹理的截取与重复

param

含义

GL_CLAMP_TO_EDGE

截取纹理

GL_REPEAT

重复纹理

(3) GL_REPEATGL_CLAMP_TO_EDGE的含义介绍

一般我们给定纹理的在ST方向的纹理坐标时都是在[0,1]之间的,但纹理在ST方向的坐标值也是可以大于1的,当给定纹理的在ST方向的坐标值分别为[0,4]时,在纹理坐标的ST方向上,若设置纹理重复方式均为GL_REPEAT重复方式,那么运行效果图如图4-1所示。

OpenGL ES2.0 生成Mipmap纹理

4-1  纹理的 S T 方向均为 GL_REPEAT 重复方式

当给定纹理的在ST方向的坐标值分别为[0,4]时,在纹理坐标的ST方向上,若设置纹理重复方式均为GL_CLAMP_TO_EDGE截取方式,那么运行效果图如图4-2所示。

OpenGL ES2.0 生成Mipmap纹理

4-2  纹理的 S T 方向均为 GL_CLAMP_TO_EDGE 重复方式

5GLES20.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