Android:OpenGL

本文介绍了Android中OpenGL ES的基本概念及其发展历程,并详细讲解了如何使用OpenGL ES在Android上绘制基本图形,包括创建Renderer类、设置OpenGL环境以及绘制三角形和圆等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Android:OpenGL

1、什么是 OpenGL?

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

2OpenGL 的发展历程

19927发布了OpenGL 1.0版本,并与微软共同推出 Windows NT 版本的OpenGL

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

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

具体特点及功能、OpenGL现状、发展历程、OpenGL规范、编程入门请点击上海IT培训官网 

3OpenGL  ES 简介

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

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

4 AndroidOpenGL ES 简介

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

 5Android 支持 OpenGL 列表

1GL

2GL 10

3GL 10 EXT

4GL 11

5GL 11 EXT

6GL 11 ExtensionPack

我们将使用 GL10 这个类开始接触OpenGL,探索3D 领域。

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

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

a)为 Renderer 类导入命名空间

 

importandroid.opengl.GLSurfaceView.Renderer;

b) 新建一个类来实现 Renderer 接口,代码如下:

 

public class ThreeDGl implements Renderer

{

}

 

c) 如上代码所写,程序实现了 Renderer 类,则必须重写以下方法

 

public void onDrawFrame(GL10 gl)

{

}

public void onSurfaceChanged(GL10 gl, intwidth, int height)

{}

public void onSurfaceCreated(GL10 gl,EGLConfig config)

{}

 

d) 当窗口被创建时需要调用 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 启用深度测试。

 

e) 当窗口大小发生改变时系统将调用 onSurfaceChange 方法,可以在该方法中设置 OpenGL 场景大小 ,代码如下:

 

//设置OpenGL场景的大小

gl.glViewport(0, 0, width, height);

 

f) 场景画出来了,接下来我们就要实现场景里面的内容,比如:设置它的透视图,让它有种越远的东西看起来越小的感觉,代码如下:

 

 

//设置投影矩阵

       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个参数用于确定窗口的大小,而后面两个参数分别是在场景中所能绘制深度的起点和终点。

 

g) 了解了上面两个重写方法的作用和功能之后,第三个方法 onDrawFrame 从字面上理解就知道此方法是做绘制图操作的。在绘图之前,需要将屏幕清除成前面所指定的颜色,清除尝试缓存并且重置场景,然后就可以绘图了,代码如下:

 

// 清除屏幕和深度缓存

gl.glClear(GL10.GL_COLOR_BUFFER_BIT |GL10.GL_DEPTH_BUFFER_BIT);

// 重置当前的模型观察矩阵

gl.glLoadIdentity();

 

h) 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类绘制的三角形和四边形的代码:

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);
    }

}

 

补充案例:

AndroidManifest.xml

<?xml version="1.0"encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

     package="org.gl"

     android:versionCode="1"

     android:versionName="1.0">

    <uses-sdk android:minSdkVersion="9"/>

 

    <application android:icon="@drawable/icon"android:label="@string/app_name">

        <activity android:name=".OpenGlActivity"

                  android:label="@string/app_name">

            <intent-filter>

                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER" />

            </intent-filter>

        </activity>

 

    </application>

</manifest>

 

OpenGlActivity.java

package org.gl;

 

 

import android.app.Activity;

import android.os.Bundle;

 

public class OpenGlActivity extends Activity {

    VortexView vortexView;

    //CView vortexView;//第二个例子,使用本行,请注释上行

    @Override 

    public void onCreate(Bundle savedInstanceState) {  

        super.onCreate(savedInstanceState);  

  

        vortexView = new VortexView(this);

        //vortexView = new CView(this);//第二个例子,使用本行,请注释上行

        setContentView(vortexView);  

    }  

    @Override 

    protected void onPause() {  

        // TODO Auto-generated method stub  

        super.onPause();  

        vortexView.onPause();  

    }  

    @Override 

    protected void onResume() {  

        // TODO Auto-generated method stub  

        super.onResume();  

        vortexView.onResume();  

    }

   

 

}

 

VortexView.java

package org.gl;

 

import android.content.Context;  

import android.opengl.GLSurfaceView;  

import android.util.AttributeSet;  

import android.view.MotionEvent;  

 

public class VortexView extends GLSurfaceView {  

      

    private VortexRenderer renderer;

    public VortexView(Context context,AttributeSet attrs) {  

        super(context, attrs);     

    }  

    public VortexView(Context context){  

        super(context);     

        renderer = new VortexRenderer();  

        setRenderer(renderer);    

    }  

    @Override 

    public boolean onTouchEvent(final MotionEvent event){    

        queueEvent(new Runnable(){  

 

            @Override 

            public void run() {   

                renderer.setColor(event.getX()/getWidth(),event.getY() /getHeight(), 1.0f);  

                renderer.setAngle(event.getX()/10);  

            }  

              

        });  

          

        return super.onTouchEvent(event);  

    }  

      

       

 

VortexRenderer.java

package org.gl;

 

 

/**

 * 程序开始      onSurfaceCreated  --> onSurfaceChanged  --> onDrawFrame  --> onDrawFrame  --> onDrawFrame -->

 * 程序后台唤醒:onSurfaceChanged  --> onDrawFrame  --> onSurfaceChanged  --> onDrawFrame  --> onDrawFrame -->

 *

 * 1) onDrawFrame() 方法会在每帧中被调用,用于描述一个时时绘制的场景,你还可以通过调用 glclear 方法去清空帧缓冲,接着通过其他OpenGl ES 调用去绘制目前的场景。

 * 2) onSurfaceChanged() 方法在surface 大小尺寸改变的时候被调用,它主要设置你的openGL的观察点,你也可以在这里设置一个不会被移动到固定Camera

 * 3) onSurfaceCreated() 方法被调用在开始渲染的时候,OpenGL ES 绘图上下文时都会被重建(当activity暂停和恢复的时候,绘图的上下文也随着丢失和重建.

 */

 

 

import java.nio.ByteBuffer;

import java.nio.ByteOrder;

import java.nio.FloatBuffer;

import java.nio.ShortBuffer;

 

import javax.microedition.khronos.egl.EGLConfig;

import javax.microedition.khronos.opengles.GL10;

 

importandroid.opengl.GLSurfaceView.Renderer;

 

public class VortexRenderer implements Renderer {

    private float red = 0f;

    private float green = 0f;

    private float blue = 0f;

   

    private ShortBuffer indexBuffer;

    private FloatBuffer vertexBuffer;

    private short[] indicesArray = {0, 1, 2};

    private int numberOfVertices = 3;

   

    private float angle;

   

    private void initTriangle(){

       /**

        *allocateallocateDirect方法都做了相同的工作,

        * 不同的是allocateDirect方法 "直接"使用操作系统来分配Buffer.

        * 因而它将提供更快的访问速度。不幸的是,并非所有的虚拟机都支持这种直接分配的方法.

        * Sun推荐将以字节为单位的直接型缓冲区allocateDirect用于与大型文件相关并具有较长生命周期的缓冲区.

        */

       ByteBuffer vbb = ByteBuffer.allocateDirect(numberOfVertices *3 *4);//36;

      

       // ByteOrder nativeOrder() 返回当前硬件平台的字节序.

       vbb.order(ByteOrder.nativeOrder());//返回ByteOrder的字节序, 并赋给ByteBuffer.

      

       /** 为当前的ByteBuffer创建一个CharBuffer的视图。

        * 在该视图buffer中的读写操作会按照ByteBuffer的字节序作用到ByteBuffer中的数据上

        */

       vertexBuffer = vbb.asFloatBuffer();

      

       ByteBuffer ibb = ByteBuffer.allocateDirect(numberOfVertices *2);

       ibb.order(ByteOrder.nativeOrder());

       indexBuffer = ibb.asShortBuffer();

       

       /**

        * coords分别定义了三个顶点的座,

        * 对应为: X, Y, Z

        * 这里需要注意的是:

        * 相对于屏幕中, 原点既是在屏幕中的中点(X/2, Y/2)

        * 原点: 0, 0, 0

        * 其中, Z轴需要以设置场景的深度为准.

        * 各个座标取值[0, 1]的浮点值.

        */

       float[] coords = {-0.5f,-0.5f, 0f,

                       0.5f, -0.5f, 0f,

                       0f, 0.5f,0.1f};

      

       vertexBuffer.put(coords);// 写入顶点座标到vertexBuffer, 以便下面显示场景.

       indexBuffer.put(indicesArray);

       vertexBuffer.position(0);//设置当前的读取起始位置.

       indexBuffer.position(0);

    }

   

    public void setColor(float red, float green, float blue){

       this.red = red;

       this.green = green;

       this.blue = blue;

    }

   

    public void setAngle(float an){

       this.angle = an;

    }

   

    @Override

    public void onDrawFrame(GL10 gl) {

               // TODO Auto-generated method stub

       /**

        * RGB + A

        * 绝大多数人都认为Alpha分量代表材料的透明度。这就是说,alpha值为0.0时所代表的材料是完全透明的。alpha值为1.0时所代表的材料则是完全不透明的。

        * 红,绿,蓝和AFA值是在颜色缓冲区被清除之后使用的,并且缺省值全是0.即(0000),其实就是设置颜色

        */

       gl.glClearColor(red, green, blue, 0.0f);

      

       gl.glClear(GL10.GL_COLOR_BUFFER_BIT);//表示把整个窗口清除为当前的清除颜色,glClear()的唯一参数表示需要被清除的缓冲区。

      

       /**

        * 定义旋转轴

        * glRotatef(速度, X, Y,Z);

        */

       gl.glRotatef(angle, 0f, 0f, 1f);

       gl.glColor4f(0.5f, 0f, 0f,0.5f);

      

      

       gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);

       gl.glDrawElements(GL10.GL_TRIANGLES, numberOfVertices, GL10.GL_UNSIGNED_SHORT, indexBuffer);

    }

 

    @Override

    public void onSurfaceChanged(GL10 gl, int w, int h) {

       // TODO Auto-generatedmethod stub

       gl.glViewport(0, 0, w, h);

    }

 

    @Override

    public void onSurfaceCreated(GL10 gl, EGLConfig cf) {

       // TODO Auto-generatedmethod stub

       gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

       initTriangle();

    }

 

 

添加画圆圈: CRenderer.java

package org.gl;

 

import java.nio.Buffer;

import java.nio.ByteBuffer;

import java.nio.ByteOrder;

import java.nio.FloatBuffer;  

import javax.microedition.khronos.egl.EGLConfig;  

import javax.microedition.khronos.opengles.GL10;   

importandroid.opengl.GLSurfaceView.Renderer;  

 

public class CRenderer implements Renderer {  

    float rotateAngle;  

    float rotateY;  

    float r = 0.5f;  

      

    //顶点数组

    private float[] vertices = new float[720];    

    

    //度到弧度的转换    

    public float DegToRad(float deg)    

    {  

        //360 = 2PI  

        float Pi = 3.14159265358979323846f;  

        float Du = 360;  

        float v = deg * (2*Pi) / Du;  

        return v;  

    }    

    public void setAnX(float angle){  

        rotateAngle -= angle;  

    }  

    public void setAnY(float ay){  

        rotateY += ay;  

    }  

    public void onDrawFrame(GL10 gl) {  

        // TODO Auto-generated method stub  

        // 进入这个函数第一件要做的事就是清除屏幕和深度缓存    

        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);    

        //画圆形    

        drawCircle(gl);  

    }  

    public void drawCircle(GL10 gl)  

    {     

        //重置投影矩阵    

        gl.glLoadIdentity();    

        // 移动操作,移入屏幕(Z)5个像素, x, y , z    

        gl.glTranslatef(0.0f, 0.0f,-1.5f);    

        //旋转, angle, x, y , z    

        gl.glRotatef(rotateAngle, 1.0f,0f, 0f);  

          

        gl.glRotatef(rotateY, 0f, 1f, 0f);  

    

        // 设置当前色为红色, R, G, B, Alpha    

        gl.glColor4f(1.0f, 0.1f, 0.1f,1.0f);    

            

        //设置圆形顶点数据,这个是在创建时生成    

        //FloatBuffer verBuffer = FloatBuffer.wrap(vertices); //Android 1.5以上版本运行出错:Must use a native order direct Buffer

        Buffer verBuffer=bufferUtil(vertices);

    

        //设置顶点类型为浮点坐标(GL_FLOAT),不设置或者设置错误类型将导致图形不能显示或者显示错误    

        gl.glVertexPointer(2, GL10.GL_FLOAT, 0, verBuffer);    

 

        //打开顶点数组    

        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);    

                

        //OGL发送实际画图指令  

        /** 

         * GL_TRIANGLE_FAN 

         * GL_LINES 

         * GL_LINES_LOOP 

         */ 

        gl.glDrawArrays(GL10.GL_LINES, 0,360);    

     

        //关闭顶点数组功能    

        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);    

    

        //画图结束    

        gl.glFinish();    

            

        //更改旋转角度    

        //rotateAngle += 0.5;    

    }    

      

      

    public voidonSurfaceChanged(GL10 gl, int width, int height) {  

        // TODO Auto-generated method stub  

         float ratio = (float) width / height;    

            //设置OpenGL场景的大小    

            gl.glViewport(0, 0, width,height);    

            //设置投影矩阵,既告诉OPENGL 如何把三维矩阵换为二维显示到界面上.    

            gl.glMatrixMode(GL10.GL_PROJECTION);    

            //重置投影矩阵,初始化.    

            gl.glLoadIdentity();    

            // 设置视口的大小  

            /** 

             * glFrustumf(float left, floatright, float bottom, float top, float zNear, float zFar) 

             * 设置了显示视口的大小,也就是说,一个可视范围

             * 把三维的东西用二维显示出来, 需要知道可以平面有多大能看多近和多远

             * 前面四个参数指定视口平面的大小, 后两个参数分别是可以看到的最近和最远

             */ 

            //gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);  

            gl.glFrustumf(-ratio, ratio, 1f, -1f,1f, 25);    

            // 选择模型观察矩阵    

            gl.glMatrixMode(GL10.GL_MODELVIEW);        

            // 重置模型观察矩阵    

            gl.glLoadIdentity();         

    }  

 

    public void onSurfaceCreated(GL10 gl, EGLConfig config){  

        // TODO Auto-generated method stub  

        // 启用阴影平滑   

        /** glShadeModel函数用于控制opengl中绘制指定两点间其他点颜色的过渡模式。 

          * 参数一般为GL_SMOOTH(默认),GL_FLATOpenGL默认是将制定的两点颜色进行插值,绘制之间的其他点。 

          * 如果两点的颜色相同,使用两个参数效果相同。 

          * 如果两点颜色不同,GL_SMOOTH会出现过渡效果,GL_FLAT 则只是以指定的某一点的单一色绘制其他所有点。 

          */ 

        gl.glShadeModel(GL10.GL_SMOOTH);    

        // 黑色背景    

        gl.glClearColor(0, 0, 0, 0);    

        // 设置深度缓存    

        gl.glClearDepthf(1.0f);  

          

        // 启用深度测试  

        /** 

         * 在三维空间里一个物体A,在另一个物体B后面,为了不让档住的部分不显示

         * 需要告诉OpenGL把被档住的部分隐藏, glEnable(GL10.GL_DEPTH_TEST)就是实现这个功能

         */ 

        gl.glEnable(GL10.GL_DEPTH_TEST);    

          

        /** 

         * 所作深度测试的类型 

         * 这里我们比较常用的深度测试函数有 GL_LESS GL_LEQUAL  

         * 两者的区别在于当深度相同时是显示新的象素还是老的象素。 

         */ 

        gl.glDepthFunc(GL10.GL_LEQUAL);                                 

            

        // 告诉系统对透视进行修正  

        /** 

         * OpenGL中,许多细节的实现算法有所不同。 

         * 这样,可以调用函数glHint()对图像质量和绘制速度之间的权衡作一些控制,但并非所有的实现都采用它。 

         * 其函数形式为:void glHint(GLenum target,GLenum hint); 

         * 控制OpenGL行为的某些方面。 

         * 参数target说明控制什么行为 

         * 参数hint可以是:GL_FASTEST(即给出最有效的选择)、GL_NICEST(即给出最高质量的选择)、GL_DONT_CARE(即没有选择)。 

         */ 

        gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);    

            

            

        //初始化圆形数据    

        for (int i = 0; i < 720;i += 2) {    

            // x value  

            if(i%4 ==0)  

                vertices[i]   =(float) (Math.cos(DegToRad(i)) * r);  

            // y value  

            if(i%4 ==0)  

                vertices[i+1] = -(float) (Math.sin(DegToRad(i)) * r);  

        }  

    }

   

    /* 

     * OpenGL 是一个非常底层的画图接口,它所使用的缓冲区存储结构是和我们的 java 程序中不相同的。 

     * Java 是大端字节序(BigEdian),而 OpenGL 所需要的数据是小端字节序(LittleEdian) 

     * 所以,我们在将 Java 的缓冲区转化为 OpenGL 可用的缓冲区时需要作一些工作。建立buff的方法如下 

     * */ 

    public Buffer bufferUtil(float []arr){  

         FloatBuffer mBuffer ;  

           

         //先初始化buffer,数组的长度*4,因为一个float4个字节  

        ByteBuffer qbb = ByteBuffer.allocateDirect(arr.length * 4);  

        //数组排列用nativeOrder  

         qbb.order(ByteOrder.nativeOrder());  

          

         mBuffer = qbb.asFloatBuffer();  

         mBuffer.put(arr);  

         mBuffer.position(0);  

           

         return mBuffer;  

    }  

 

 

要使圆圈运动起来: CView.java

package org.gl;

 

import android.content.Context;  

import android.opengl.GLSurfaceView;  

import android.util.AttributeSet;  

import android.view.MotionEvent;  

 

public class CView extends GLSurfaceView {  

    CRenderer renderer;  

    float oX = 0f;  

    float oY = 0f;  

    public CView(Context context,AttributeSet attrs) {  

        super(context, attrs);  

        // TODO Auto-generated constructor stub  

    }  

    public CView(Context context) {  

        super(context, null);  

        // TODO Auto-generated constructor stub  

          

        renderer = newCRenderer();  

        setRenderer(renderer);  

    }  

    @Override 

    public boolean onTouchEvent(MotionEvent event) {  

        //android.util.Log.d("AnsonLog", "TouchEvent:::::::::");  

        // TODO Auto-generated method stub  

        switch(event.getAction()){  

        case MotionEvent.ACTION_DOWN:  

            oX = event.getRawX();  

            oY = event.getRawY();  

            break;  

        case MotionEvent.ACTION_MOVE:  

            float cX = event.getRawX();  

            float cY = event.getRawY();  

            float disX = cX - oX;  

            float disY = cY - oY;  

            oX = cX;  

            oY = cY;  

              

           renderer.setAnX(disY/4f);  

            renderer.setAnY(disX/4f);         

            break;  

        case MotionEvent.ACTION_UP:  

            oX = 0f;  

            oY = 0f;  

            break;  

        }  

          

        return true;  

          

    }  

      

 

效果图一:

 

效果图二:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值