Android OpenGL入门

我的CSDN博客同步发布:Android OpenGL入门

转载请注明出处:【huachao1001的简书:http://www.jianshu.com/users/0a7e42698e4b/latest_articles】

如今VR这么火,感觉有必要先把OpenGL学好,为以后转VR奠定一些基础。一年前,接触过AndroidOpenGL,当时是实现了在Android上显示标准的3D文件(STL格式)。现在打算整理一下OpenGL相关知识,后续会有相关的系列文章。本文为后面文章铺垫,让大家对OpenGL代码编写有个总体上的认识。

1 检测设备是否支持OpenGL

Android中,有个专门用于显示OpenGL3D图像ViewGLSurfaceViewGLSurfaceView会处理OpenGL初始化过程中比较基本的操作,如配置显示设备,以及在后台线程中渲染。说的太正式了哈,其实不用太在乎它,就把它当当成是一个SurfaceView就好,因为其实它的用法跟SurfaceView很像(然而,它就是继承自SurfaceView~)。

接下来开始创建GLSurfaceView。在使用OpenGL时,我们首先得判断当前设备是否支持OpenGL(其实大部分手机都是支持的啦~),由于各种设备都可能支持Android系统,其实还是有必要判断一下。因为我们现在基本上用到的是OpenGL ES 2.0,我们要验证的是检查系统是否实际支持2.0版本。

final ActivityManager activityManager=(ActivityManager)getSystemService(ACTIVITY_SERVICE);
final ConfigurationInfo configurationInfo=activityManager.getDeviceConfigurationInfo();
boolean supportsEs2=configurationInfo.reqGlEsVersion>=0x2000;

由于这段代码不能很好的在模拟器上工作(GPU模拟部分有缺陷),得要稍微修改一下,使之能在模拟器上正常工作


boolean supportsEs2 = configurationInfo.reqGlEsVersion >= 0x2000;

boolean isEmulator = Build.VERSION.SDK_INT > Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1
                && (Build.FINGERPRINT.startsWith("generic")
                || Build.FINGERPRINT.startsWith("unknown")
                || Build.MODEL.contains("google_sdk")
                || Build.MODEL.contains("Emulator")
                || Build.MODEL.contains("Android SDK built for x86"));

supportsEs2 = supportsEs2 || isEmulator;

我们看看怎么使用GLSurfaceView吧~

private boolean supportsEs2;
private  GLSurfaceView glSurfaceView; 
@Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        checkSupported();

        if (supportsEs2) {
            glSurfaceView = new GLSurfaceView(this); 
            glSurfaceView.setRenderer(new GLRenderer()); 
            setContentView(glSurfaceView);
        } else {
            setContentView(R.layout.activity_main);
            Toast.makeText(this, "当前设备不支持OpenGL ES 2.0!", Toast.LENGTH_SHORT).show();
        }
    }

  
private void checkSupported() {
        ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
        ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
        supportsEs2 = configurationInfo.reqGlEsVersion >= 0x2000;

        boolean isEmulator = Build.VERSION.SDK_INT > Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1
                && (Build.FINGERPRINT.startsWith("generic")
                || Build.FINGERPRINT.startsWith("unknown")
                || Build.MODEL.contains("google_sdk")
                || Build.MODEL.contains("Emulator")
                || Build.MODEL.contains("Android SDK built for x86"));

        supportsEs2 = supportsEs2 || isEmulator;
}

什么?这么简单,难道这样就能显示3D模型?可是并没有看到3D模型图形在哪里啊!别着急,看看第9行代码,有个setRenderer()函数,里面需要传入一个Renderer对象,那么什么是Renderer呢?前面提到GLSurfaceView是用于显示3D模型的视图,如果说GLSurfaceView是画布,那么,光有一块白纸是没用的,得要在白纸上画图,通过什么画图呢?就是接下来要说的RendererRenderer是一个接口,它主要包含3个抽象函数:onSurfaceCreatedonDrawFrameonSurfaceChanged;从名字就可以看出,分别是在SurfaceView创建时调用、在绘制图形时调用以及在视图大小发生改变时调用。看看我们的GLRenderer对象是怎么定义的:

/**
 * Package com.hc.opengl
 * Created by HuaChao on 2016/7/27.
 */
public class GLRenderer implements GLSurfaceView.Renderer {

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {

    }

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

    }

    @Override
    public void onDrawFrame(GL10 gl) {

    }
}

这里啥也没干,所以你的屏幕上面啥都没有~但是大致框架已经搭建好了。另外,还需要注意一点,就是防止我们在切换程序时,OpenGL还在绘制图形导致程序崩溃,因此我们还需要根据Activity的生命周期针对GLSurfaceView做一些处理:

 @Override
    protected void onPause() {
        super.onPause();
        if (glSurfaceView != null) {
            glSurfaceView.onPause();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (glSurfaceView != null) {
            glSurfaceView.onResume();
        }
    }

ok,到目前为止,这个框架算是搭建好了,接下来,让我们把战场转移到Renderer对象上去吧!

2 Renderer显示背景颜色

在绘制3D模型时,我们首先要对画板的背景颜色绘制好,颜色可以随便选。glClearColor函数是设置清屏的颜色,参数分别对应RGBA,我们设置为红色就是glClearColor(1f, 0f, 0f, 0f);,为啥红色是1呢?而不是我们平时所熟知的255,请注意:在使用OpenGL时,很多地方采用的参数变化范围都是从0到1,比如在贴纹理的时候选择图片区域也是[0,1]。也就是说,rgba的取值都是从0~1。然后是设置视角窗口大小glViewport,其实就是决定绘制的矩形区域的大小,当然并不是这么简单,后面我会详细讲,目前就可以把它理解为绘制的区域,在GLSurfaceView窗口大小发生变化时我们动态改变视角窗口。最后就是真正的绘制图形啦,我们先啥也不干,就针对画板“刷一次油漆”,把画板背景颜色设置为红色,glClear(GL10.GL_COLOR_BUFFER_BIT)的意思是,使用glClearColor函数所设置的颜色进行清屏。

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        gl.glClearColor(1f, 0f, 0f, 0f);
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        gl.glViewport(0, 0, width, height);
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
    }

运行一下吧,是不是看到满满的红色~。如果你的模拟器没有显示效果:请检查“Use Host GPU”选项已经勾选。如果已经勾选,那就在 glSurfaceView.setRenderer(new GLRenderer());代码之前添加代码:glSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);

设置清屏颜色

目前我们把基本框架写好了,但是还没有绘制模型图像,其实,我们在显示模型时,主要的工作就是集中在Renderer,重写里面的3个重要函数,基本上就可以把一个模型显示出来。下一篇文章中,我们一起学习如何显示简单的图形。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容