一、基础知识:

GL_TRIANGLE_STRIP比GL_TRIANLGES 快100% ~ 200%。

建议:尽可能地使用GL_TRIANGLE_STRIP替代GL_TRIANGLES

二、使用方法:

1.首先以框架入手,我们一般在Android上画一个3D的图形,需要在MainActivity的OnCreate函数中加入如下代码,用来进入我们的3D场景界面:

       glView = new GLSurfaceView(this);// 创建一个GLSurfaceView       glView.setRenderer(new MyGLRenderer(this));// 使用定制的渲染器        setContentView(glView);

其中,glView为GLSurfaceView glView的引用对象,在MainActivity中的成员变量中声明:

private GLSurfaceView glView;// 使用GLSurfaceView 


2.接下来实现3D场景中的绚烂器(GLSurfaceView.Renderer):

public class MyGLRenderer implements  GLSurfaceView.Renderer {  // 实现代码}


①构造函数的编写:

// Constructor with global application contextpublic MyGLRenderer(Context context) {this.context = context;// 设置所用图形的数据数组缓冲区cube = new TextureCube();}


其中,TextureCube 为我们自己的纹理类,需要自己实现,后面会有实现。context和cube分别为成员变量:

private Context context;// 应用的上下文句柄private TextureCube  cube;

②重载函数onSurfaceCreated,创建绚烂器时需要初始化的部分皆在此:

// Call back when the surface is first created or re-created@Overridepublic void onSurfaceCreated(GL10 gl, EGLConfig config){// 启用阴影平滑gl.glShadeModel(GL10.GL_SMOOTH);// 设置背景颜色gl.glClearColor(0.2f, 0.4f, 0.52f, 1.0f);// 设置深度缓存gl.glClearDepthf(1.0f);// 启用深度测试gl.glEnable(GL10.GL_DEPTH_TEST);// 所作深度测试的类型gl.glDepthFunc(GL10.GL_LEQUAL);// 告诉系统对透视进行修正gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);// 禁止抖动以取得更好的性能gl.glDisable(GL10.GL_DITHER);// 设置纹理cube.loadTexture(gl, context);// 加载纹理gl.glEnable(GL10.GL_TEXTURE_2D);// 纹理使能}


以上一些功能的打开和声明,都可以在我博客之前的一些文章中找到,不在详述。

最重要的一句就是 cube.loadTexture(gl, context); 加载纹理。

③重载函数onSurfaceChanged,当屏幕旋转(横屏变为竖屏)时,调用。当然,在初始化的时候也是要调用的:

// Call back after onSurfaceCreated() or whenever the window's size changes@Overridepublic void onSurfaceChanged(GL10 gl, int width, int height){if(height == 0)// 防止被零除{height = 1;}// 重置当前的视图区域gl.glViewport(0, 0, width, height);// 选择投影矩阵gl.glMatrixMode(GL10.GL_PROJECTION);// 重置投影矩阵gl.glLoadIdentity();// 设置视图区域的大小GLU.gluPerspective(gl, 45.0f, (float)width/(float)height,0.1f,100.0f);// 选择模型观察矩阵gl.glMatrixMode(GL10.GL_MODELVIEW);// 重置模型观察矩阵gl.glLoadIdentity();}


④重载函数onDrawFrame,此为一个回调函数,用来更新场景中的各个对象:

// Call back to draw the current frame.@Overridepublic void onDrawFrame(GL10 gl){// 清除屏幕和深度缓存gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);// 重置当前的模型观察矩阵gl.glLoadIdentity();gl.glTranslatef(0.0f, 0.0f, -5.0f); // 向屏幕里移动5个单位gl.glScalef(0.8f, 0.8f, 0.8f);// 缩小80%// 绕X轴旋转立方体 gl.glRotatef(xrot, 1.0f, 0.0f, 0.0f);// 绕Y轴旋转立方体gl.glRotatef(yrot, 0.0f, 1.0f, 0.0f);// 绕Z轴旋转立方体gl.glRotatef(zrot, 0.0f, 0.0f, 1.0f);     // 正方体cube.draw(gl);// 每次刷新之后更新旋转角度xrot += 0.3f;yrot += 0.2f;zrot += 0.4f;}

3.接下来实现3D场景中绚烂器的纹理类(TextureCube):

// 生成一个带纹理的立方体// 这里指定义一个面的顶点,立方体的其他面通过平移和旋转这个面来渲染public class TextureCube {// 实现代码}



①构造函数的编写:

private float[] vertices = { // 定义一个面的顶点坐标-1.0f, -1.0f, 0.0f,  // 0. 左-底-前1.0f, -1.0f, 0.0f,   // 1. 右-底-前-1.0f,  1.0f, 0.0f,  // 2. 左-顶-前1.0f,  1.0f, 0.0f    // 3. 右-顶-前};float[] texCoords = { // 定义上面的面的纹理坐标        0.0f, 1.0f,  // A. 左-下        1.0f, 1.0f,  // B. 右-下         0.0f, 0.0f,  // C. 左-上         1.0f, 0.0f   // D. 右-上    };int[] textureIDs = new int[1]; // 纹理-ID数组// 构造函数,设置缓冲区public TextureCube(){// 设置顶点数组,顶点数据为浮点数据类型。一个浮点类型的数据长度为四个字节    ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);    vbb.order(ByteOrder.nativeOrder()); // 使用原生字节顺序    vertexBuffer = vbb.asFloatBuffer(); // 将字节类型缓冲区转换成浮点类型    vertexBuffer.put(vertices);         // 将数据复制进缓冲区    vertexBuffer.position(0);           // 定位到初始位置     // 设置纹理坐标数组缓冲区,数据类型为浮点数据    ByteBuffer tbb = ByteBuffer.allocateDirect(texCoords.length * 4);    tbb.order(ByteOrder.nativeOrder());    texBuffer = tbb.asFloatBuffer();    texBuffer.put(texCoords);    texBuffer.position(0);}


②加载图像函数的实现(loadTexture):

// 加载一个图像到GL纹理public void loadTexture(GL10 gl, Context context) {gl.glGenTextures(1, textureIDs, 0);// 生成纹理ID数组gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[0]);// 绑定到纹理ID// 设置纹理过滤方式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);// 构造一个输入流来加载纹理文件"res/drawable/nehe.bmp"InputStream ins = context.getResources().openRawResource(R.drawable.nehe);Bitmap bmp;try {// 读取并将输入流解码成位图bmp = BitmapFactory.decodeStream(ins);} finally {try {ins.close();}catch(IOException e) {}}// 根据加载的位图为当前绑定的纹理ID建立纹理GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0);}


③绘图函数的实现(draw):

// 绘图public void draw(GL10 gl){gl.glFrontFace(GL10.GL_CCW);    // 正前面为逆时针方向    gl.glEnable(GL10.GL_CULL_FACE); // 使能剔除面    gl.glCullFace(GL10.GL_BACK);    // 剔除背面(不显示)        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);    gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);  // 使能纹理坐标数组    gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texBuffer); // 定义纹理坐标数组缓冲区        // 前    gl.glPushMatrix();    gl.glTranslatef(0.0f, 0.0f, 1.0f);    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);    gl.glPopMatrix();        // 左    gl.glPushMatrix();    gl.glRotatef(270.0f, 0.0f, 1.0f, 0.0f);    gl.glTranslatef(0.0f, 0.0f, 1.0f);    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);    gl.glPopMatrix();        // 后    gl.glPushMatrix();    gl.glRotatef(180.0f, 0.0f, 1.0f, 0.0f);    gl.glTranslatef(0.0f, 0.0f, 1.0f);    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);    gl.glPopMatrix();    // 右    gl.glPushMatrix();    gl.glRotatef(90.0f, 0.0f, 1.0f, 0.0f);    gl.glTranslatef(0.0f, 0.0f, 1.0f);    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);    gl.glPopMatrix();    // 顶    gl.glPushMatrix();    gl.glRotatef(270.0f, 1.0f, 0.0f, 0.0f);    gl.glTranslatef(0.0f, 0.0f, 1.0f);    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);    gl.glPopMatrix();    // 底    gl.glPushMatrix();    gl.glRotatef(90.0f, 1.0f, 0.0f, 0.0f);    gl.glTranslatef(0.0f, 0.0f, 1.0f);    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);    gl.glPopMatrix();        // 恢复原来的状态    gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);     gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);    gl.glDisable(GL10.GL_CULL_FACE);}

备注说明:

在纹理映射的时候,特别要注意顶点数组和图像纹理数组的数值和顺序,如果顺序不对的话,很可能出现画出来的是个三角形,或者图像是很怪的那种。

三、效果展示:

四、代码下载地址:http://download.csdn.net/detail/ypist/5242701

参考文章: http://blog.csdn.net/seniorwizard/article/details/7816179

本文博客源地址:http://blog.csdn.net/ypist

更多相关文章

  1. Android(安卓)RadialGradient 放射渲染
  2. Kotlin For Android介绍
  3. Android-SQLite使用总结
  4. android opengl es添加纹理,绘制立方体纹理,立方体使用不同纹理
  5. [Android]【安卓】Json数据的快速拼装和解析
  6. Android(安卓)Donut Makefile分析之一 (build/envsetup.sh)
  7. Android培训班(83)Dalvik虚拟机的初始化
  8. Message Looper Handler三者之间的关联
  9. Android(安卓)Zygote源码分析

随机推荐

  1. 关于Android中的几个文件目录
  2. Android activity四大启动模式详解
  3. 十分钟教你玩转Android动画【Android】
  4. Android屏幕背光调整机制
  5. 单独安装VS2012装mono for android
  6. Android—fragment无法remove
  7. android.app.Activity 的介绍
  8. 【Android之隐藏状态栏、设置全屏、取消
  9. Android字体跟颜色
  10. 搞定android JNI