OpenGL ES的1.0

来源:互联网 发布:淘宝标题优化技巧视频 编辑:程序博客网 时间:2024/05/18 13:09

OpenGL ES的1.0

在这份文件中

  1. 创建与GLSurfaceView活动
  2. 画上GLSurfaceView的形状
    1. 定义一个三角形
    2. 画出三角形
  3. 应用投影和相机视图
  4. 添加运动
  5. 响应触摸事件

相关样本

  1. API的演示 - 图形
  2. OpenGL ES的1.0示例
  3. TouchRotateActivity

另请参阅

  1. 3D与OpenGL
  2. OpenGL ES 2.0的

本教程演示了如何创建一个简单的Andr​​oid应用程序使用的OpenGL ES 1.0 API来执行一些基本图形操作。您将学习如何:

  • 使用GLSurfaceViewGLSurfaceView.Renderer创建活动
  • 创建和绘制图形对象
  • 定义一个投影屏幕几何纠正
  • 定义相机视图
  • 旋转的图形对象
  • 使图形触摸互动

Android框架的OpenGL ES 1.0/1.1和OpenGL ES 2.0 API的支持。您应该仔细考虑的OpenGL ES API(1.0/1.1或2.0)的版本是最适合您的需要 。欲了解更多信息,请参阅 选择OpenGL API的版本。如果您希望使用的OpenGL ES 2.0,OpenGL ES 2.0的教程。

在开始之前,您应该了解如何创建一个基本的Android应用程序 。如果你不知道如何创建一个应用程序,后续的Hello World教程将使你熟悉这个过程。

创建与GLSurfaceView活动

要开始使用OpenGL,你必须实现一个GLSurfaceView和 GLSurfaceView.RendererGLSurfaceView是主视图类型的应用程序,使用OpenGL和GLSurfaceView.Renderer 控制在该视图中绘制的是什么。(欲了解更多有关这些类的信息,请参阅与 OpenGL的3D文件。)

使用GLSurfaceView创建活动:

  1. 启动一个新的Andr​​oid项目,该项目目标的Andr​​oid 1.6(API等级4)或更高。
  2. 将项目命名为HelloOpenGLES10和确保它包括一个称为HelloOpenGLES10活动 。
  3. 修改HelloOpenGLES10类如下:
    package com.example.android.apis.graphics;import android.app.Activity;import android.content.Context;import android.opengl.GLSurfaceView;import android.os.Bundle;public class HelloOpenGLES10 extends Activity {      private GLSurfaceView mGLView;      @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);                // Create a GLSurfaceView instance and set it        // as the ContentView for this Activity.        mGLView = new HelloOpenGLES10SurfaceView(this);        setContentView(mGLView);    }        @Override    protected void onPause() {        super.onPause();        // The following call pauses the rendering thread.        // If your OpenGL application is memory intensive,        // you should consider de-allocating objects that        // consume significant memory here.        mGLView.onPause();    }        @Override    protected void onResume() {        super.onResume();        // The following call resumes a paused rendering thread.        // If you de-allocated graphic objects for onPause()        // this is a good place to re-allocate them.        mGLView.onResume();    }}  class HelloOpenGLES10SurfaceView extends GLSurfaceView {    public HelloOpenGLES10SurfaceView(Context context){        super(context);                // Set the Renderer for drawing on the GLSurfaceView        setRenderer(new HelloOpenGLES10Renderer());    }}
    1. 注:你会得到一个HelloOpenGLES10Renderer引用编译错误。这是预期的结果;下一步将修复这个错误。

      如上图所示,此活动使用单一GLSurfaceView作为其视图。请注意,这个活动实现暂停和恢复的关键生命周期的回调 。

      HelloOpenGLES10SurfaceView的代码在上面的例子中仅仅是GLSurfaceView的一个实例,因此不是例子必须的。不过,如果你想您的应用程序能够监测和响应触摸屏事件(我们猜测你会这样做),你做你必须继承GLSurfaceView来添加触摸事件侦听器,您将会在Reponding to Touch Events中学习如何做。

      为了在GLSurfaceView绘制图形,你必须定义一个继承GLSurfaceView.Renderer的类。在接下来的步骤,您将创建一个renderer类来完成这个OpenGL应用程序。

    2. 创建一个新的文件 HelloOpenGLES10Renderer类,它实现GLSurfaceView.Renderer 接口 :
      package com.example.android.apis.graphics;import javax.microedition.khronos.egl.EGLConfig;import javax.microedition.khronos.opengles.GL10;import android.opengl.GLSurfaceView;public class HelloOpenGLES10Renderer implements GLSurfaceView.Renderer {    public void onSurfaceCreated(GL10 gl, EGLConfig config) {        // Set the background frame color        gl.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);    }        public void onDrawFrame(GL10 gl) {        // Redraw background color        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);    }        public void onSurfaceChanged(GL10 gl, int width, int height) {        gl.glViewport(0, 0, width, height);    }  }
      1. 这继承GLSurfaceView.Renderer接口使用OpenGL绘图方法而必须提供的最简代码结构 :

        • onSurfaceCreated()被调用一次当 GLSurfaceView 创建后。
        • onDrawFrame()GLSurfaceView重绘时调用
        • onSurfaceChanged()被调用当GLSurfaceView发生的几何的变化,例如当设备的屏幕方向的变化。

        如需有关这些方法的更多信息,请参阅与 OpenGL的 3D文档。

      上面的代码示例创建了一个简单的Andr​​oid应用程序显示一个灰色的屏幕,使用OpenGL ES 1.0调用。虽然这个应用程序没有做任何事情非常有趣,通过创建这些类,你必须奠定开始绘制与OpenGL ES 1.0的图形元素所需的基础。

      如果你是熟悉的OpenGL ES API的,这些类应该给你足够的信息来使用的OpenGL ES 1.0 API和创建图形。但是,如果您需要更多的帮助开始使用OpenGL的头下一节一些更多的提示。

      画上GLSurfaceView的形状

      一旦你已经实现了GLSurfaceView.Renderer,下一步就是绘制它的东西 。本节说明如何定义和画一个三角形。

      定义一个三角形

      OpenGL允许您使用在三维空间的坐标来定义对象。所以,在你可以画一个三角形之前,你必须定义它的坐标。在OpenGL中,要做到这一点的典型方式是定义坐标的顶点数组。

      默认情况下,OpenGL ES的假设了一个坐标系,就是[0,0,0](X,Y,Z)指定为GLSurfaceView框架中心 ,[1,1,0]是框架的右上角和[ - 1,-1,0]是框架的左下角。

      定义一个三角形的顶点数组:

      1. 在你的HelloOpenGLES10Renderer类中,添加新的成员变量,包含一个三角形状的 顶点:
        private FloatBuffer triangleVB;
      2. 创建一个方法,initShapes()用以填充该成员变量:
        private void initShapes(){            float triangleCoords[] = {            // X, Y, Z            -0.5f, -0.25f, 0,             0.5f, -0.25f, 0,             0.0f,  0.559016994f, 0        };                 // initialize vertex Buffer for triangle          ByteBuffer vbb = ByteBuffer.allocateDirect(                // (# of coordinate values * 4 bytes per float)                triangleCoords.length * 4);         vbb.order(ByteOrder.nativeOrder());// use the device hardware's native byte order        triangleVB = vbb.asFloatBuffer();  // create a floating point buffer from the ByteBuffer        triangleVB.put(triangleCoords);    // add the coordinates to the FloatBuffer        triangleVB.position(0);            // set the buffer to read the first coordinate        }
        这种方法定义了一个三相等的立体三角形。
      3. 修改onSurfaceCreated()方法来初始化您的三角形:
            public void onSurfaceCreated(GL10 gl, EGLConfig config) {            // Set the background frame color        gl.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);                // initialize the triangle vertex array        initShapes();    }

          注意:形状和其他静态对象在onSurfaceCreated()初始化一次,以便获得最佳性能 。避免在onDrawFrame()初新的对象,因为这会导致系统重新创建每个重绘对象,从而减慢您的应用程序。

        现在已经定义了一个三角形的形状,但如果您运行的应用程序后,什么也没有出现。什么?您应该告诉OpenGL绘制三角形,你将会在下一节学会如何做。

        画出三角形

        你必须告诉OpenGL您使用的顶点数组,在你可以画出你的三角形之前。在这些步骤后,你可以调用绘图API来显示三角形。

        绘制三角形:

        1. glEnableClientState()方法必须添加到onSurfaceCreated()的底部,使得可以使用顶点数组。
                  // Enable use of vertex arrays        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
          经过这一步,您已经准备在OpenGL视图中绘制三角形的对象。
        2. 下面的代码添加到您的onDrawFrame()方法末尾,以绘制的三角形。
          // Draw the triangle        gl.glColor4f(0.63671875f, 0.76953125f, 0.22265625f, 0.0f);        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, triangleVB);        gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3);
        3. 运行的应用程序!你的程序应该是这个样子:

        图1。三角没有投影或相机视图绘制。

        有这个例子中的几个问题。首先,它没有给你友好的印象。其次,三角形是有点压扁,还有当您更改设备的屏幕方向时将改变其形状。它的形状歪斜的原因,是因为这个对象渲染在一个不是正方形的屏幕上。您将在下一节中使用投影和相机视图解决这一问题。

        最后,因为三角形是固定的,系统在完全相同的地方重绘对象多次,这方法不是最有效地利用OpenGL图形的方法。在Add Motion节,你会做出这种形状的旋转,从而证明这种使用方法的处理能力 。

        应用投影和相机视图

        显示图形的基本问题之一是显示,Android设备通常不是方形的,默认情况下,OpenGL的希望您画在一个正方形上,以便能够在不是方形的屏幕上使用统一的坐标系统。为了解决这个问题,你可以申请一个OpenGL投影模式和相机视图(眼点)来改变图形对象的坐标,使他们有正确的比例在任何显示器上 。关于OpenGL的坐标映射的详细信息,请查阅 Mapping Coordinates for Drawn Objects.

        运用投影和相机视图转换到您的三角形:

        1. 修改您的onSurfaceChanged()的方法使支持GL10.GL_PROJECTION模式,计算屏幕比例和应用作为改造对象的坐标的比例。
            public void onSurfaceChanged(GL10 gl, int width, int height) {      gl.glViewport(0, 0, width, height);            // make adjustments for screen ratio      float ratio = (float) width / height;      gl.glMatrixMode(GL10.GL_PROJECTION);        // set matrix to projection mode      gl.glLoadIdentity();                        // reset the matrix to its default state      gl.glFrustumf(-ratio, ratio, -1, 1, 3, 7);  // apply the projection matrix  }  
        2. 接下来,修改您的onDrawFrame( )方法来套用 GL_MODELVIEW模式,并使用 GLU.gluLookAt ()设置一个眼点
              public void onDrawFrame(GL10 gl) {        // Redraw background color        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);                // Set GL_MODELVIEW transformation mode        gl.glMatrixMode(GL10.GL_MODELVIEW);        gl.glLoadIdentity();   // reset the matrix to its default state                // When using GL_MODELVIEW, you must set the view point        GLU.gluLookAt(gl, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);                        // Draw the triangle        ...    }
        3. 运行更新的应用程序,你应该看到像这样:

        图2。三角绘制与应用投影和相机视图。

        现在,您已经应用了这种转变,三角形的三个边都相等的,而不是早期版本中的压扁的三角形 。

        添加运动

        虽然十分激动用OpenGL ES创建了一个静态图形对象,没准你想至少一些对象移动 。在本节中,您将添加运动到您的三角形旋转。

        要添加您的三角形旋转:

        1. 修改您onDrawFrame()方法,以旋转的三角形对象 :
              public void onDrawFrame(GL10 gl) {        ...            // When using GL_MODELVIEW, you must set the view point        GLU.gluLookAt(gl, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);                    // Create a rotation for the triangle        long time = SystemClock.uptimeMillis() % 4000L;        float angle = 0.090f * ((int) time);        gl.glRotatef(angle, 0.0f, 0.0f, 1.0f);                        // Draw the triangle        ...    }
        2. 运行应用程序和您的三角形应该围绕其中心旋转。

        响应触摸事件

        像旋转的三角形那样按照预设程序使物体移动是可以得到一些注意,但你是否想用户拥有与OpenGL图形的交互呢?在本节中,您将学习如何监听触摸事件,让用户能够和你的 HelloOpenGLES10SurfaceView对象交互

        使您的OpenGL应用程序触摸互动的关键是继承GLSurfaceView覆盖onTouchEvent()方法来监听触摸事件。然而,在你开始之前,你要修改的渲染类显示三角形的旋转角度。之后,您将修改HelloOpenGLES10SurfaceView处理触摸事件并把这些数据传递到您的渲染类。

        使您的旋转三角形响应触摸事件:

        1. 修改您 HelloOpenGLES10Renderer类,加入一个新的公共成员使您的HelloOpenGLES10SurfaceView类是能够传递新的旋转值到您的渲染:
          public float mAngle;
        2. 在您onDrawFrame()方法,注释掉代码产生的一个角度,更换新角度变量mAngle
                  // Create a rotation for the triangle (Boring! Comment this out:)        // long time = SystemClock.uptimeMillis() % 4000L;        // float angle = 0.090f * ((int) time);        // Use the mAngle member as the rotation value        gl.glRotatef(mAngle, 0.0f, 0.0f, 1.0f); 
        3. 在你的HelloOpenGLES10SurfaceView类中,添加下面的成员变量 。
              private final float TOUCH_SCALE_FACTOR = 180.0f / 320;    private HelloOpenGLES10Renderer mRenderer;    private float mPreviousX;    private float mPreviousY;
        4. HelloOpenGLES10SurfaceView构造方法,设置mRenderer成员让您拥有一个处理旋转输入和设置渲染模式RENDERMODE_WHEN_DIRTY的类
              public HelloOpenGLES10SurfaceView(Context context){        super(context);        // set the mRenderer member        mRenderer = new HelloOpenGLES10Renderer();        setRenderer(mRenderer);                // Render the view only when there is a change        setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);    }
        5. 在你的HelloOpenGLES10SurfaceView类中,重写onTouchEvent( )方法来侦听触摸事件并将它们传递给你的渲染 。
              @Override     public boolean onTouchEvent(MotionEvent e) {        // MotionEvent reports input details from the touch screen        // and other input controls. In this case, you are only        // interested in events where the touch position changed.        float x = e.getX();        float y = e.getY();                switch (e.getAction()) {            case MotionEvent.ACTION_MOVE:                    float dx = x - mPreviousX;                float dy = y - mPreviousY;                    // reverse direction of rotation above the mid-line                if (y > getHeight() / 2) {                  dx = dx * -1 ;                }                    // reverse direction of rotation to left of the mid-line                if (x < getWidth() / 2) {                  dy = dy * -1 ;                }                              mRenderer.mAngle += (dx + dy) * TOUCH_SCALE_FACTOR;                requestRender();        }        mPreviousX = x;        mPreviousY = y;        return true;    } 

          注:触摸事件返回该像素的坐标于OpenGL坐标是不一样的 。触摸坐标[0,0]是屏幕的左下角和[max_X,max_Y]是屏幕右上角的最高值。为了配合触摸事件OpenGL的图形对象,您必须转换触摸坐标为OpenGL的坐标。

        6. 运行应用程序和你的手指或光标在屏幕上拖动,旋转的三角形。

        对于OpenGL的触摸事件功能的另一个例子,请看TouchRotateActivity.

本人的英语水平不高,只能把Google翻译错误的地方改了一下,希望对大家有用,如果看不懂还是去官网看源文档吧....(*^__^*) 嘻嘻……



Portions of this page are reproduced from work created and shared by the Android Open Source Project and used according to terms described in the Creative Commons 2.5 Attribution License.  
原文来自http://developer.android.com/resources/tutorials/opengl/opengl-es10.html
原创粉丝点击