Android为OpenGL  ES支持提供了GLSurfaceView组件,这个组件用于显示3D图形。GLSurfaceView本身并不提供绘制3D图形的功能,而是由GLSurfaceView.Renderer来完成了SurfaceView中3D图形的绘制。

归纳起来,在Android中使用OpenGL  ES需要三个步骤:

1、创建GLSurfaceView组件,使用Activity来显示GLSurfaceView组件。

2、为GLSurfaceView组件创建GLSurfaceView.Renderer实例,实现GLSurfaceView.Renderer类时需要实现该接口里的三个方法:

  abstract  void  onDrawFrame(GL10  gl):Renderer对象调用该方法绘制GLSurfaceView的当前帧。

  abstract  void  onSurfaceChanged(GL10  gl , int  width  ,int  height):当GLSurfaceView的大小改变时回调该方法。

  abstract  void  onSurfaceCreated(GL10  gl  ,  EGLConfig  config):当GLSurfaceView被创建时回调该方法。

3、调用GLSurfaceView组件的setRenderer()方法指定Renderer对象,该Renderer对象将会完成GLSurfaceView里3D图像的绘制。

从上面的介绍不难看出,实际上绘制3D图形的难点不是如何使用GLSurfaceView组件,而是如何实现Renderer类。实现Renderer类时需要实现三个方法,这三个方法都有一个GL10形参,它就代表了GLOpen  ES的“绘制画笔”,我们可以把它想象成Swing  2D绘图中的Graphics,也可以想象成Android  2D绘图中的Canvas组件-----当我们希望Renderer绘制3D图形时,实际上是调用GL10的方法来进行绘制的。

当SurfaceView被创建时,系统会回调Renderer对象的onSurfaceCreated()方法,该方法将可以对OpenGL  ES执行一些无须任何改变的初始化,例如:

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
  // 关闭抗抖动
  gl.glDisable(GL10.GL_DITHER);
  //设置系统对透视进行修正
  gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
  gl.glClearColor(0, 0, 0, 0);
  //设置阴影平滑模式
  gl.glShadeModel(GL10.GL_SMOOTH);
  //启用深度测试
  gl.glEnable(GL10.GL_DEPTH_TEST);
  //设置深度测试的类型
  gl.glDepthFunc(GL10.GL_LEQUAL);
}

GL10就是OpenGL  ES的绘图接口,但实际上他也是GL11的实例,可通过(gl  Instansof  GL11)判断它是否为GL11接口的实例。

glDisable(int  cap):该方法用于禁用OpenGL  ES某个方面的特性,上例中代码用于关闭抗抖性,这样可以提高性能。

glHint(int  target  , int mode):该方法用于对OpenGL  ES某方法进行修正。

clearColor(float  red  ,  float green  ,  float  blue  , float  alpha):该方法设置OpenGL  ES“清屏”所用的颜色,四个参数分别设置红、绿、蓝、透明度值;0为最小值,1为最大值。例如设置gl.glClearColor(0 ,  0 , 0 , 0):就是用黑色“清屏”。

glShadeMode(int  mode):该方法用于设置OpenGL  ES的阴影模式,此处设为阴影平滑模式。

glEnable(int  cap):该方法与glDisable(int  cap)方法相对,用于启用OpenGL  ES某方面的特性,此处用于启动OpenGL  ES的深度测试,所谓“深度测试”,就是让OpenGL  ES负责跟踪每个物体在Z轴上的深度,这样就可避免后面的物体遮挡前面的物体。

当SurfaceView组件的大小发生改变时,系统会回调Renderer对象的onSurfaceChanged()方法,因此该方法通常用于初始化3D场景。例如如下初始化代码:

@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;
  //调用此方法设置透视视窗的空间大小
  gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
}

上面的方法中用到了GL10的一些初始化方法,此处做简要说明:

glViewport(int  x , int  y  ,  int  width ,  int  height):设置3D视窗的位置与大小。其中前两个参数指定该视窗的位置,后两个参数指定该视窗的宽、高。

glMatrixMode(int  mode):设置视图的矩阵模型。通常可接受GL10.GL_PROJECTION、GL10.GL_MODEVIEW两个常量值。

  当调用glMatrixMode(GL10.GL_PROJECTION):代码后,指定将屏幕视为透视图(要想看到逼真的三维物体,这是必要的),这意味着越远的东西看起来越小;当调用glMatrixMode(GL10.GL_MODEVIEW):代码后,即将当前矩阵模式设为模型视图矩阵,这意味着任何新的变换都会影响该矩阵中的所有物体。

glLoadIdentity():相当于reset()方法,用于初始化单位矩阵。

glFrustumf(float  left  , float  right , float  bottom , float  top , float  zNear  ,  float  zFar):用于设置透视投影的空间大小。前路两个参数用于设置X轴上的最小坐标值、最大坐标值;中间两个参数用于设置Y轴上的最小坐标值、最大坐标值;后面两个参数用于设置Z轴上所能绘制的场景的深度的最小值、最大值。

注:三维坐标系统与二维坐标系统并不相同,而二维坐标系统上的坐标值通常就直接使用系统的像素数量;但三维坐标系统的坐标值则取决于glFrustumf()方法的设置。

GLSurfaceView上的所有3D图形都是有Renderer的onDrawFrame(GL10  gl)方法绘制出来的,重写该方法时就要把所有3D图形都绘制出来,该方法通常以如下形式开始:

 

@Override
public void onDrawFrame(GL10 gl) {
  // 清除屏幕缓存和深度缓存
  gl.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_BUFFER_BIT);
}

更多相关文章

  1. 【Android 初学】5、控件--ImageView的使用方法
  2. Android优秀开源组件项目集合
  3. [置顶] 我的Android进阶之旅------>Ubuntu下不能识别Android设备
  4. Android-Jni线程(三)— JNI全局回调java方法
  5. android 对图像进行矩阵变换(Martix)的使用笔记
  6. Android和蓝牙GPS结合的方法
  7. [ ]在Android系统上使用busybox——最简单的方法
  8. Android 四大组件Broadcast

随机推荐

  1. Android裁剪图片总结
  2. 解决Glide4.0和圆角裁剪CenterCrop冲突
  3. android webview 使用js加载json文件失败
  4. Android下相机的调用
  5. android notification 的总结分析
  6. Android(安卓)Scroll 详解
  7. android 设置 button 不同状态的图片
  8. 2010.12.29(2)——— android GridView
  9. 解决问题:Could not find method android(
  10. 关于Android studio的build.gradle的内容