Android OpenGL

本文介绍了Android系统中OpenGL ES的基本概念与应用,详细讲解了如何通过实现Renderer接口完成简单的3D图形绘制。

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

OpenGL  ES 简介

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

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

Android OpenGL ES 简介

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

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 领域。

一步一步实现自己的 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, -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);
    }



OpenGL 参考代码--使用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);
    }


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

}













评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值