zoukankan      html  css  js  c++  java
  • Android OpenGL 学习笔记 --开始篇

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://terryblog.blog.51cto.com/1764499/346996

    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 ESOpenGL ES是一套为手持和嵌入式系统设计的3D引擎API,由Khronos公司维护。在PC领域,一直有两种标准的3D API进行竞争,OpenGL  DirectX。一般主流的游戏和显卡都支持这两种渲染方式,DirectXWindows平台上有很大的优势,但是 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(0000);
              
              
      // 设置深度缓存
              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(00, width, height);
       
    • 6、场景画出来了,接下来我们就要实现场景里面的内容,比如:设置它的透视图,让它有种越远的东西看起来越小的感觉,代码如下:
      //设置投影矩阵
              gl.glMatrixMode(GL10.GL_PROJECTION);
              
      //重置投影矩阵
              gl.glLoadIdentity();
              
      // 设置视口的大小
              gl.glFrustumf(-ratio, ratio, -11110);
              
      // 选择模型观察矩阵
              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, -11110); 此方法,前面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类绘制的三角形和四边形的代码:
     
    OpenGL 参考代码
    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.5f0.0f-6.0f);
             
    //设置旋转
            gl.glRotatef(rotateTri, 0.0f1.0f0.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, 03);
            
            gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
            
            
    //绘制三角形结束
            gl.glFinish();
            
            
    /***********************/
            
    /* 渲染正方形 */
            
    // 重置当前的模型观察矩阵
            gl.glLoadIdentity();
            
            
    // 左移 1.5 单位,并移入屏幕 6.0
            gl.glTranslatef(1.5f0.0f-6.0f);
            
            
    // 设置当前色为蓝色
            gl.glColor4f(0.5f0.5f1.0f1.0f);
            
    //设置旋转
            gl.glRotatef(rotateQuad, 1.0f0.0f0.0f);
            
            
    //设置和绘制正方形
            gl.glVertexPointer(3, GL10.GL_FIXED, 0, quateBuffer);
            gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 
    04);
            
            
    //绘制正方形结束
            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(00, width, height);
            
    //设置投影矩阵
            gl.glMatrixMode(GL10.GL_PROJECTION);
            
    //重置投影矩阵
            gl.glLoadIdentity();
            
    // 设置视口的大小
            gl.glFrustumf(-ratio, ratio, -11110);
            
    // 选择模型观察矩阵
            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(0000);
            
            
    // 设置深度缓存
            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 还有更多的东西需要我们去探索,努力吧。

    本文出自 “Terry_龙” 博客,请务必保留此出处http://terryblog.blog.51cto.com/1764499/346996

    ——————————如果不豁出性命的话,也是无法开创未来的。
  • 相关阅读:
    已知圆心,半径,角度,求圆上的点坐标
    js-JavaScript高级程序设计学习笔记10
    js-关于性能优化的一些学习总结
    css-css权威指南学习笔记2
    css-a与a:link的一些认识
    css-IE中的border-radius和box-shadow
    css-css权威指南学习笔记1
    css-文本超出后显示省略号
    js-JavaScript高级程序设计学习笔记9
    js-JavaScript高级程序设计学习笔记8
  • 原文地址:https://www.cnblogs.com/thirller/p/3669037.html
Copyright © 2011-2022 走看看