一、纹理的概念
纹理(texture) 在游戏制作里面指贴图,计算机图形学中的纹理既包括通常意义上物体表面的纹理即使物体表面呈现凹凸不平的沟纹,同时也包括在物体的光滑表面上的彩色图案。
OpenGL中的纹理可以用来表示图像,照片,甚至由一个数学算法生成的分形数据。每个二维的纹理都由许多小的纹理元素组成,它们是小块的数据,类似于我们前面讨论过的片段和像素。要使用纹理,最常用的方式是直接从一个图像文件加载数据。
二、添加纹理
添加纹理分为以下几个步骤
打开纹理开关
创建纹理
绑定纹理
设置纹理参数
生成纹理
设置纹理顶点数据
1. 打开纹理开关
// 启动纹理坐标数据
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
//打开纹理
gl.glEnable(GL10.GL_TEXTURE_2D);
2. 创建纹理
先要创建纹理名称数组
//纹理名称数组
int [] textureids = new int[1];
//创建纹理
gl.glGenTextures(1, textureids, 0);
传入3个参数
void glGenTextures(
int n, //数量
int[] textures, //纹理名称数组
int offset //偏移量
);
3. 绑定纹理
前一个参数固定,后一个传入数组元素
//绑定纹理
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureids[0]);
(1)有两个参数需要设置下,当纹理比被渲染区域大或者小时,要设置纹理放大或者缩小情况下,OpenG纹理过滤模式
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_NEAREST);
有以下几种
- GL_NEAREST————最近邻过滤
- GL_NEAREST_MIPMAP_NEAREST————使用MIP贴图的最近邻过滤
- GL_NEAREST_MIPMAP_LINEAR————使用MIP贴图级别之间插值的最近邻过滤
- GL_LINEAR————双线性过滤
- GL_LINEAR_MIPMAP_NEAREST————使用MIP贴图的双线性过滤
- GL_LINEAR_MIPMAP_LINEAR————三线性过滤(使用MIP贴图级别之间插值的双线性过滤)
2. 在使用纹理的时候,有时候会出现超过纹理边界的问题,GL_TEXTURE_WRAP系列参数用来设置当这些超出边界时应该怎样处理。
gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_WRAP_S,GL10.GL_REPEAT);
gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_WRAP_T,GL10.GL_REPEAT);
- GL_TEXTURE_WRAP_S————S方向(X方向)
- GL_TEXTURE_WRAP_T————T方向(Y方向)
第三个参数有以下几种
- GL_REPEAT————重复边界的纹理
- GL_CLAMP————opengl就在一个2X2的加权纹理单元数组中使用取自边框的纹理单元。这时候的边框如果没有设置的话,应该就是原纹理的边界的像素值
- GL_CLAMP_TO_EDGE————边框始终被忽略。位于纹理边缘或者靠近纹理边缘的纹理单元将用于纹理计算,但不使用纹理边框上的纹理单元
- GL_CLAMP_TO_BORDER————如果纹理坐标位于范围[0,1]之外,那么只用边框纹理单元(如果没有边框,则使用常量边框颜色,我想常量边框颜色就是黑色)用于纹理
5. 生成纹理
先获取到Bitmap
mBitmap=BitmapFactory.decodeResource(getResources(), R.drawable.texture_img);
然后调用GLUtils的texImage2D方法,传入4个参数。
// 生成纹理
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, mBitmap, 0);
后三个参数含义如下
- level———— 提供多种分辨率的纹理. 如纹理只有一种分辨率,level 则设置为0.
- bitmap————Bitmap对象
- border————边框,设置为0
6. 设置纹理顶点数据
新建纹理浮点数组
float texCoords[] = {
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
};
需要按照图示方式连接,再获取纹理缓冲数组
//获取纹理缓冲数组
TextureBuffer= Utils.getFloatBuffer(texCoords);
这个其实就是把float转成floatBuffer,分配的内存大小为数组的长度乘以4.
最后设置纹理顶点数据
// 设置纹理顶点数据
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, TextureBuffer);
简单总结一下。
create 纹理id
int [] textureids = new int[1];
glGenTextures() 可以一次生成多个,后续操作纹理全靠这个id
绑定纹理
glBindTexture() 操作纹理,传入纹理id作为参数,每次bind之后,后续操作的纹理都是该纹理
glTexParameteri()指定纹理格式。这里包括纹理横向和纵向的重复方式
GL_TEXTURE_WRAP_S
GL_TEXTURE_WRAP_T
和纹理在放大和缩小(同样纹理离远和离近)时的处理,这种设置主要是为了避免同一个纹理反复使用时,远处的纹理反而比近处的清晰
GL_TEXTURE_MAG_FILTER
GL_TEXTURE_MIN_FILTER
给纹理传入图像数据
GLUtils.texImage2D()
此纹理相关设置已经结束。后续想使用或者操作这个纹理,只要再glBindTexture这个纹理的id即可.
demo
int[] textureHandle = new int[1];
GLES20.glGenTextures(1, textureHandle, 0);
int TextureID = textureHandle[0];
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, TextureID);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);