1.简介
上一篇已经将一个平面图形绘制出来了,这一次我们将在上一次绘制出来的图形的表面上进行纹理贴图。
图片准备:(宽高须为2的N次方)
最终图片是以Bitmap形式。现在考虑如何把这张图片映射到绘制的平面上?
所以这里也需要一个数组float[] 用于设置纹理坐标数据,纹理坐标数据以图片左上角为(0,0),右下角为(1,1)为基础
上一篇文章已经知道,面数组为{0,1,2,3,4,5}绘制,所以要给组成面的每个顶点,映射一个纹理坐标数据,如下:
float[]{
0f,0f , 0f,1f , 1f,1f, //第一个面的三个点
0f,0f , 1f,1f , 1f,0f
}
这样一张图片就全部映射到绘制的平面上了。
2.代码
public class OtherShader implements GLSurfaceView.Renderer{
FloatBuffer vertextBuffer;
//纹理坐标数据
FloatBuffer textureBuffer;
ByteBuffer faceBuffer;
private float roate;
//使用的纹理
int texture;
Context context;
public OtherShader(Context context) {
this.context = context;
vertextBuffer = floatArray2Buffer(vertex);
faceBuffer = ByteBuffer.wrap(face);
textureBuffer = floatArray2Buffer(text);
}
float[] vertex = new float[]{
-0.5f , 0.5f , 0f ,
-0.5f , -0.5f , 0f ,
0.5f , -0.5f , 0f ,
-0.5f , 0.5f , 0f ,
0.5f , -0.5f , 0f ,
0.5f , 0.5f , 0f
};
byte[] face = new byte[]{
0,1,2,
3,4,5
};
//纹理坐标数据
float[] text = {
0f,0f , 0f,1f , 1f,1f,
0f,0f , 1f,1f , 1f,0f
};
//将顶点颜色数组转换为IntBuffer,是OpenGl ES所需要的,可以不设置顶点颜色
private IntBuffer intArray2Buffer(int[] rect1color) {
IntBuffer intBuffer;
//不用该方法得到IntBuffer,因为Android平台限制,Buffer必须为native Buffer,所以要通过allocateDirect()创建
//并且该Buffer必须是排序的,所以要order()方法进行排序
//intBuffer = IntBuffer.wrap(rect1color);
//因为一个int=4字节
ByteBuffer bb = ByteBuffer.allocateDirect(rect1color.length * 4);
bb.order(ByteOrder.nativeOrder());
intBuffer = bb.asIntBuffer();
intBuffer.put(rect1color);
intBuffer.position(0); //移到第一个点的数据
return intBuffer;
}
//将顶点位置数组转换为FloatBuffer,是OpenGl ES所需要的
private FloatBuffer floatArray2Buffer(float[] rect1) {
FloatBuffer floatBuffer;
//不用该方法得到FloatBuffer,因为Android平台限制,Buffer必须为native Buffer,所以要通过allocateDirect()创建
//并且该Buffer必须是排序的,所以要order()方法进行排序
//floatBuffer = FloatBuffer.wrap(rect1);
//因为一个int=4字节
ByteBuffer bb = ByteBuffer.allocateDirect(rect1.length * 4);
bb.order(ByteOrder.nativeOrder());
floatBuffer = bb.asFloatBuffer();
floatBuffer.put(rect1);
floatBuffer.position(0); //移到第一个点的数据
return floatBuffer;
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
//关闭抗抖动
gl.glDisable(GL10.GL_DITHER);
//修正系统透视
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT , GL10.GL_FASTEST);
//设置阴影平滑模式
gl.glShadeModel(GL10.GL_SMOOTH);
//启用深度测试 记录Z轴深度
gl.glEnable(GL10.GL_DEPTH_TEST);
//设置深度测试的类型
gl.glDepthFunc(GL10.GL_LEQUAL);
//*******启用2D纹理*************
gl.glEnable(GL10.GL_TEXTURE_2D);
//加载纹理
loadTexture(gl);
}
private void loadTexture(GL10 gl) {
Bitmap bitmap = null;
bitmap = BitmapFactory.decodeResource(context.getResources() , R.drawable.bj);
int[] textures = new int[1];
gl.glGenTextures(1 , textures , 0);
texture = textures[0];
gl.glBindTexture(GL10.GL_TEXTURE_2D , texture);
gl.glTexParameterf(GL10.GL_TEXTURE_2D , GL10.GL_TEXTURE_MIN_FILTER , GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D , GL10.GL_TEXTURE_MAG_FILTER , GL10.GL_LINEAR);
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);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D , 0 , bitmap , 0);
if (bitmap != null){
bitmap.recycle();
}
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
//设置3D窗口的大小及位置
gl.glViewport(0 , 0 , width , height );
//将矩阵模式设置为投影矩阵
gl.glMatrixMode(GL10.GL_PROJECTION);
//初始化单位矩阵
gl.glLoadIdentity();
//计算透视窗宽高比
float ratio = (float)width/height;
//设置透视视窗的空间大小 默认为 -1,1,-1,1,-1,1
//gl.glFrustumf(-ratio , ratio , -1 , 1 ,1 , 10);
}
@Override
public void onDrawFrame(GL10 gl) {
//清除屏幕缓存和深度缓存
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
//启用顶点坐标数据
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
//设置当前矩形堆栈为模型堆栈
gl.glMatrixMode(GL10.GL_MODELVIEW);
//启用纹理贴图坐标数组
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
//重置当前的模型视图矩阵
gl.glLoadIdentity();
//如果需要用颜色填充平面,还需要禁用顶点颜色数据
gl.glColor4f(0.2f , 1.0f , 0.2f , 0.0f);
gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
//绕y轴旋转
//gl.glRotatef(roate , 0f , 1f , 0f);
//设置顶点位置数据
gl.glVertexPointer(3 , GL10.GL_FLOAT , 0 , vertextBuffer);
//设置贴图数组
gl.glTexCoordPointer(2 , GL10.GL_FLOAT , 0 , textureBuffer);
//根据顶点绘制平面 //执行贴图
gl.glBindTexture(GL10.GL_TEXTURE_2D , texture);
gl.glDrawElements(GL10.GL_TRIANGLES, faceBuffer.remaining() , GL10.GL_UNSIGNED_BYTE , faceBuffer);
//停止绘制
gl.glFinish();
//停用坐标数据
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
//禁用纹理数组
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
roate+=1;
if (roate == 360){
roate = 0;
}
}
}