>>分享Android开发相关的技术 书籍支持  卫琴直播  品书摘要  在线测试  资源下载  联系我们
发表一个新主题 开启一个新投票 回复文章 您是本文章第 18996 个阅读者 刷新本主题
 * 贴子主题:  Android OpenGL 学习笔记 回复文章 点赞(0)  收藏  
作者:flybird    发表时间:2020-05-15 08:21:15     消息  查看  搜索  好友  邮件  复制  引用

   1、什么是 OpenGL?

   OpenGL 是个专业的3D程序接口,是一个功能强大,调用方便的底层3D图形库。 OpenGL  的前身是 SGI 公司为其图形工作站开的 IRIS GL。IRIS GL 是一个工业标准的3D图形软件接口,功能虽然强大但是移植性不好,于是 SGI 公司便在 IRIS GL 的基础上开发 OpenGL  。具体详细的介绍请 点击这里 。

2、OpenGL 的发展历程

  1992年7月 发布了 OpenGL 1.0 版本,并与微软共同推出 Windows NT 版本的 OpenGL 。

  1995年 OpenGL 1.1 版本面市,加入了新功能,并引入了纹理特性等等。

  一直到 2009年8月Khronos小组发布了 OpenGL 3.2,这是一年以来 OpenGL进行的第三次重要升级。

具体特点及功能、 OpenGL 现状、发展历程、 OpenGL 规范、编程入门请 点击这里 。

3、OpenGL  ES 简介

       Android 3D  引擎采用的是 OpenGL ES 。 OpenGL ES 是一套为手持和嵌入式系统设计的3D 引擎API ,由Khronos 公司维护。在PC 领域,一直有两种标准的3D API 进行竞争, OpenGL  和 DirectX 。一般主流的游戏和显卡都支持这两种渲染方式,DirectX 在Windows 平台上有很大的优势,但是 OpenGL 具有更好的跨平台性。

  由于嵌入式系统和PC 相比,一般说来,CPU 、内存等都比PC 差很多,而且对能耗有着特殊的要求,许多嵌入式设备并没有浮点运算协处理器,针对嵌入式系统的以上特点,Khronos 对标准的 OpenGL  系统进行了维护和改动,以期望满足嵌入式设备对3D 绘图的要求。

4、     Android OpenGL ES 简介

Android 系统使用 OpenGL  的标准接口来支持3D 图形功能,android 3D  图形系统也分为 java  框架和本地代码两部分。本地代码主要实现的 OpenGL  接口的库,在 Java  框架层,javax.microedition.khronos.opengles  是 java  标准的 OpenGL  包,android.opengl 包提供了 OpenGL  系统和 Android GUI  系统之间的联系。

5、Android 支持 OpenGL 列表
  • 1、GL
  • 2、GL 10
  • 3、GL 10 EXT
  • 4、GL 11
  • 5、GL 11 EXT
  • 6、GL 11 ExtensionPack
我们将使用 GL10 这个类开始接触 OpenGL ,探索3D 领域。

6、一步一步实现自己的 Renderer 类

在 Android 中我们使用 GLSurfaceView 来显示 OpenGL 视图,该类位于 android.opengl 包里面。它提供了一个专门用于渲染3D 的接口 Renderer 。接下来我们就来一步步构建自己的 Renderer 类。
  • 1、为 Renderer 类赶回命名空间

    import  android.opengl.GLSurfaceView.Renderer;  
  • 2、新建一个类来实现 Renderer 接口,代码如下:

    public   class  ThreeDGl  implements  Renderer
    {
    }  
  • 3、如上代码所写,程序实现了 Renderer 类,则必须重写以下方法

    public   void  onDrawFrame(GL10 gl)
    {
    }

    public   void  onSurfaceChanged(GL10 gl,  int  width,  int  height)
    {}

    public   void  onSurfaceCreated(GL10 gl, EGLConfig config)
    {}  
  • 4、当窗口被创建时需要调用 onSurfaceCreate ,我们可以在这里对 OpenGL 做一些初始化工作,例如:

             //  启用阴影平滑
             gl.glShadeModel(GL10.GL_SMOOTH);
            
             //  黑色背景
             gl.glClearColor( 0 ,  0 ,  0 ,  0 );
            
             //  设置深度缓存
             gl.glClearDepthf( 1.0f );                            
             //  启用深度测试
             gl.glEnable(GL10.GL_DEPTH_TEST);                        
             //  所作深度测试的类型
             gl.glDepthFunc(GL10.GL_LEQUAL);                            
            
             //  告诉系统对透视进行修正
             gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);

    glHint 用于告诉 OpenGL 我们希望进行最好的透视修正,这会轻微地影响性能,但会使得透视图更好看。
    glClearColor 设置清除屏幕时所用的颜色,色彩值的范围从 0.0f~1.0f 大小从暗到这的过程。
    glShadeModel 用于启用阴影平滑度。阴影平滑通过多边形精细地混合色彩,并对外部光进行平滑。
    glDepthFunc 为将深度缓存设想为屏幕后面的层,它不断地对物体进入屏幕内部的深度进行跟踪。
    glEnable 启用深度测试。
  • 5、当窗口大小发生改变时系统将调用 onSurfaceChange 方法,可以在该方法中设置 OpenGL 场景大小 ,代码如下:

      // 设置OpenGL场景的大小
    gl.glViewport( 0 ,  0 , width, height);  
  • 6、场景画出来了,接下来我们就要实现场景里面的内容,比如:设置它的透视图,让它有种越远的东西看起来越小的感觉,代码如下:

             // 设置投影矩阵
             gl.glMatrixMode(GL10.GL_PROJECTION);
             // 重置投影矩阵
             gl.glLoadIdentity();
             //  设置视口的大小
             gl.glFrustumf( - ratio, ratio,  - 1 ,  1 ,  1 ,  10 );
             //  选择模型观察矩阵
             gl.glMatrixMode(GL10.GL_MODELVIEW);    
             //  重置模型观察矩阵
             gl.glLoadIdentity();    

    gl.glMatrixMode(GL10.GL_PROJECTION); 指明接下来的代码将影响 projection matrix (投影矩阵),投影矩阵负责为场景增加透视度。
    gl.glLoadIdentity(); 此方法相当于我们手机的重置功能,它将所选择的矩阵状态恢复成原始状态,调用  glLoadIdentity(); 之后为场景设置透视图。
    gl.glMatrixMode(GL10.GL_MODELVIEW);   指明任何新的变换将会影响 modelview matrix (模型观察矩阵)。
    gl.glFrustumf( - ratio, ratio,  - 1 ,  1 ,  1 ,  10 ); 此方法,前面4个参数用于确定窗口的大小,而后面两个参数分别是在场景中所能绘制深度的起点和终点。
  • 7、了解了上面两个重写方法的作用和功能之后,第三个方法 onDrawFrame 从字面上理解就知道此方法做绘制图操作的。嗯,没错。在绘图之前,需要将屏幕清除成前面所指定的颜色,清除尝试缓存并且重置场景,然后就可以绘图了, 代码如下:

    //  清除屏幕和深度缓存
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT  |  GL10.GL_DEPTH_BUFFER_BIT);
    //  重置当前的模型观察矩阵
    gl.glLoadIdentity();

  • 8、Renderer 类在实现了上面的三个重写之后,在程序入口中编写如下代码

         Renderer render = new  ThreeDGl( this );
         /**  Called when the activity is first created.  */
        @Override
         public   void  onCreate(Bundle savedInstanceState) {
             super .onCreate(savedInstanceState);
            GLSurfaceView gview = new  GLSurfaceView( this );
            gview.setRenderer(render);
            setContentView(gview);
        }

      即可将我们绘制的图形显示出来。
下面分享一段使用Renderer类绘制的三角形和四边形的代码:

package  com.terry;

import  java.nio.IntBuffer;

import  javax.microedition.khronos.egl.EGLConfig;
import  javax.microedition.khronos.opengles.GL10;

import  android.opengl.GLSurfaceView.Renderer;

public   class  GLRender  implements  Renderer{

     float rotateTri,rotateQuad;
     int  one = 0x10000 ;
    
     // 三角形的一个顶点
      private  IntBuffer triggerBuffer = IntBuffer.wrap( new   int []{
             0 ,one, 0 ,      // 上顶点
              - one, - one, 0 ,     // 左顶点
             one, - one, 0      // 右下点
     });
    
     // 正方形的四个顶点
      private  IntBuffer quateBuffer = IntBuffer.wrap( new   int []{
            one,one, 0 ,
             - one, - one, 0 ,
            one, - one, 0 ,
             - one, - one, 0
    });
    
             private  IntBuffer colorBuffer = IntBuffer.wrap( new   int []{
            one, 0 , 0 ,one,
             0 ,one, 0 ,one,
             0 , 0 ,one,one
    });
    
                    @Override
     public   void  onDrawFrame(GL10 gl) {
         //  TODO Auto-generated method stub
        
         //  清除屏幕和深度缓存
         gl.glClear(GL10.GL_COLOR_BUFFER_BIT  |  GL10.GL_DEPTH_BUFFER_BIT);
         //  重置当前的模型观察矩阵
         gl.glLoadIdentity();

             //  左移 1.5 单位,并移入屏幕 6.0
         gl.glTranslatef( - 1.5f ,  0.0f ,  - 6.0f );
          // 设置旋转
         gl.glRotatef(rotateTri,  0.0f ,  1.0f ,  0.0f );
        
         // 设置定点数组
         gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
         // 设置颜色数组
         gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
        
        gl.glColorPointer( 4 , GL10.GL_FIXED,  0 , colorBuffer);
         //  设置三角形顶点
         gl.glVertexPointer( 3 , GL10.GL_FIXED,  0 , triggerBuffer);
         // 绘制三角形
         gl.glDrawArrays(GL10.GL_TRIANGLES,  0 ,  3 );
        
        gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
        
         // 绘制三角形结束
         gl.glFinish();
        
         /** ******************** */
         /*  渲染正方形  */
         //  重置当前的模型观察矩阵
         gl.glLoadIdentity();
        
         //  左移 1.5 单位,并移入屏幕 6.0
         gl.glTranslatef( 1.5f ,  0.0f ,  - 6.0f );
        
         //  设置当前色为蓝色
         gl.glColor4f( 0.5f ,  0.5f ,  1.0f ,  1.0f );
         // 设置旋转
         gl.glRotatef(rotateQuad,  1.0f ,  0.0f ,  0.0f );
        
         // 设置和绘制正方形
         gl.glVertexPointer( 3 , GL10.GL_FIXED,  0 , quateBuffer);
        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,  0 ,  4 );
        
         // 绘制正方形结束
         gl.glFinish();

         // 取消顶点数组
         gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
        
         // 改变旋转的角度
         rotateTri  +=   0.5f ;
        rotateQuad  -=   0.5f ;
    }

    @Override
     public   void  onSurfaceChanged(GL10 gl,  int  width,  int  height) {
         //  TODO Auto-generated method stub
        
         float ratio  =  ( float ) width  /  height;
         // 设置OpenGL场景的大小
         gl.glViewport( 0 ,  0 , width, height);
         // 设置投影矩阵
         gl.glMatrixMode(GL10.GL_PROJECTION);
         // 重置投影矩阵
         gl.glLoadIdentity();
         //  设置视口的大小
         gl.glFrustumf( - ratio, ratio,  - 1 ,  1 ,  1 ,  10 );
         //  选择模型观察矩阵
         gl.glMatrixMode(GL10.GL_MODELVIEW);    
         //  重置模型观察矩阵
         gl.glLoadIdentity();    
        
    }

    @Override
     public   void  onSurfaceCreated(GL10 gl, EGLConfig config) {
         //  TODO Auto-generated method stub
         //  启用阴影平滑
         gl.glShadeModel(GL10.GL_SMOOTH);
        
         //  黑色背景
         gl.glClearColor( 0 ,  0 ,  0 ,  0 );
        
         //  设置深度缓存
         gl.glClearDepthf( 1.0f );                            
         //  启用深度测试
         gl.glEnable(GL10.GL_DEPTH_TEST);                        
         //  所作深度测试的类型
         gl.glDepthFunc(GL10.GL_LEQUAL);                            
        
         //  告诉系统对透视进行修正
         gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
    }

}

               到此基本对 OpenGL 有一些了解,当然OpenGL 还有更多的东西需要我们去探索,努力吧。


----------------------------
原文链接:https://blog.51cto.com/terryblog/346996

程序猿的技术大观园:www.javathinker.net



[这个贴子最后由 flybird 在 2020-06-04 19:42:44 重新编辑]
网站系统异常


系统异常信息
Request URL: http://www.javathinker.net/WEB-INF/lybbs/jsp/topic.jsp?postID=3261

java.lang.NullPointerException

如果你不知道错误发生的原因,请把上面完整的信息提交给本站管理人员。