GLSurfaceView的渲染模式。

OpenGl ES关于渲染方式有以下两种:RENDERMODE_CONTINUOUSLY和RENDERMODE_WHEN_DIRTY。

默认渲染方式为RENDERMODE_CONTINUOUSLY,当设置为RENDERMODE_CONTINUOUSLY时渲染器会不停地渲染场景,当设置为RENDERMODE_WHEN_DIRTY时只有在创建和调用requestRender()时才会刷新。

一般设置为RENDERMODE_WHEN_DIRTY方式,这样不会让CPU一直处于高速运转状态,提高手机电池使用时间和软件整体性能。

接着简单写一个OpenGL ES程序。

1.在Manifest中添加声明
  为了使用OpenGL ES 2.0 API,需要添加如下声明:

<uses-feature android:glEsVersion="0x00020000" android:required="true" />

  OpenGL ES 2.0 requires Android 2.2 (API Level 8) or higher,所以需要确认系统版本。

2.创建Activity
  在Activity的布局中,需要加入GLSurfaceView来放置绘制的图形。

  一个最简单的版本如下:

public class OpenGLES20 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 MyGLSurfaceView(this);
        setContentView(mGLView);
    }
}

3.创建GLSurfaceView
  GLSurfaceView是一个特殊的组件,你可以在其中绘制OpenGL ES图形。

  你需要扩展这个类,在它的构造方法中设置渲染器:

class MyGLSurfaceView extends GLSurfaceView {

public MyGLSurfaceView(Context context){
        super(context);

// Set the Renderer for drawing on the GLSurfaceView
        setRenderer(new MyRenderer());
    }
}

 如果使用OpenGL ES 2.0,还需要加一句声明:

// Create an OpenGL ES 2.0 context
setEGLContextClientVersion(2);

  还有一个可选的设置是,把渲染模式改为 GLSurfaceView.RENDERMODE_WHEN_DIRTY ,这样仅在你的数据有变化时重新进行渲染。

// Render the view only when there is a change in the drawing data
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);

  除非你调用requestRender(),这个设置会阻止帧被重画,有些情况下这样效率更高。

4.建立一个Renderer类
  Renderer类(渲染器类),即 GLSurfaceView.Renderer的实现类,它控制了与它相关联的 GLSurfaceView 上绘制什么。

  其中有三个主要的回调方法:

onSurfaceCreated() - Called once to set up the view's OpenGL ES environment.
onDrawFrame() - Called for each redraw of the view.
onSurfaceChanged() - Called if the geometry of the view changes, for example when the device's screen orientation changes.

  

  一个简单的实现例子:

public class MyGL20Renderer implements GLSurfaceView.Renderer {

public void onSurfaceCreated(GL10 unused, EGLConfig config) {
        // Set the background frame color
        GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
    }

public void onDrawFrame(GL10 unused) {
        // Redraw background color
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
    }

public void onSurfaceChanged(GL10 unused, int width, int height) {
        GLES20.glViewport(0, 0, width, height);
    }
}

程序例子
  一个简单的程序例子,并没有绘制什么,只是设置了背景色,为了展示方便,GLSurfaceView类和渲染器类都作为Acitivity的内部类写出。

  首先在Manifest中加上声明:

Manifest

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.helloopengles"
    android:versionCode="1"
    android:versionName="1.0" >

<uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="15" />
    <!-- Tell the system this app requires OpenGL ES 2.0. -->
    <uses-feature
        android:glEsVersion="0x00020000"
        android:required="true" />

<application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".HelloOpenGLESActivity"
            android:label="@string/title_activity_hello_open_gles" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Activity

package com.example.helloopengles;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.app.Activity;
import android.content.Context;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.util.Log;

public class HelloOpenGLESActivity 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 MyGLSurfaceView(this);
        setContentView(mGLView);

}

class MyGLSurfaceView extends GLSurfaceView
    {

public MyGLSurfaceView(Context context)
        {
            super(context);

try
            {
                // Create an OpenGL ES 2.0 context
                setEGLContextClientVersion(2);

// Set the Renderer for drawing on the GLSurfaceView
                setRenderer(new MyRenderer());

// Render the view only when there is a change in the drawing
                // data
                setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);

// 注意上面语句的顺序,反了可能会出错

}
            catch (Exception e)
            {
                e.printStackTrace();

}

}
    }

public class MyRenderer implements GLSurfaceView.Renderer
    {

public void onSurfaceCreated(GL10 unused, EGLConfig config)
        {
            // Set the background frame color
            GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
        }

public void onDrawFrame(GL10 unused)
        {
            // Redraw background color
            GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
        }

public void onSurfaceChanged(GL10 unused, int width, int height)
        {
            GLES20.glViewport(0, 0, width, height);
        }
    }

}

GLSurfaceView的绘制过程要点

1,GLSurfaceview的渲染模式RenderMode

在onAttachedToWindow后就启动了一个无线循环的子线程,该子线程完成了整个绘制流程,并系统默认是负责不断刷新重绘,刷新的帧率是16FPS。从这里也可以看出来,GLSurfaceView系统默认是60ms就重绘一次,这样的耗性能的重绘操作一定是要用在那种有持续动画的效果才有意义。

当然,你也可以通过设置setRenderMode去设置主动刷新:

/**
 * Set the rendering mode. When renderMode is
 * RENDERMODE_CONTINUOUSLY, the renderer is called
 * repeatedly to re-render the scene. When renderMode
 * is RENDERMODE_WHEN_DIRTY, the renderer only rendered when the surface
 * is created, or when {@link #requestRender} is called. Defaults to RENDERMODE_CONTINUOUSLY.
 *
* Using RENDERMODE_WHEN_DIRTY can improve battery life and overall system performance * by allowing the GPU and CPU to idle when the view does not need to be updated. *

* This method can only be called after {@link #setRenderer(Renderer)} * * @param renderMode one of the RENDERMODE_X constants * @see #RENDERMODE_CONTINUOUSLY * @see #RENDERMODE_WHEN_DIRTY */ public void setRenderMode(int renderMode) { mGLThread.setRenderMode(renderMode); }

注解中提到:系统默认mode==RENDERMODE_CONTINUOUSLY,这样系统会自动重绘;mode==RENDERMODE_WHEN_DIRTY时,只有surfaceCreate的时候会绘制一次,然后就需要通过requestRender()方法主动请求重绘。同时也提到,如果你的界面不需要频繁的刷新最好是设置成RENDERMODE_WHEN_DIRTY,这样可以降低CPU和GPU的活动,可以省电。

2,事件处理

为了处理事件,一般都是继承GLSurfaceView类并重载它的事件方法。但是由于GLSurfaceView是多线程操作,所以需要一些特殊的处理。由于渲染器在独立的渲染线程里,你应该使用Java的跨线程机制跟渲染器通讯。queueEvent(Runnable)方法就是一种相对简单的操作。

class MyGLSurfaceView extends GLSurfaceView { 
    private MyRenderer mMyRenderer; 
   
        public void start() { 
            mMyRenderer = ...; 
            setRenderer(mMyRenderer); 
        } 
   
   
        public boolean onKeyDown(int keyCode, KeyEvent event) { 
   
            if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { 
                queueEvent(new Runnable() { 
                    // 这个方法会在渲染线程里被调用 
                         public void run() { 
                             mMyRenderer.handleDpadCenter(); 
                         }}); 
                     return true; 
                 } 
   
                 return super.onKeyDown(keyCode, event); 
            } 
      } 
}

调用queueEvent就是给队列中添加runnable

public void queueEvent(Runnable r) {
 
    synchronized(sGLThreadManager) {
        mEventQueue.add(r);
        sGLThreadManager.notifyAll();
    }
 
}

在guardenRun()中有如下代码:

if (! mEventQueue.isEmpty()) {
                    event = mEventQueue.remove(0);
                    break;
                }
                 
                ...
                 
                if (event != null) {
                    event.run();
                    event = null;
                    continue;
                }

android GLSurfaceView渲染模式相关推荐

  1. 【Android UI】Paint Gradient 渐变渲染 ① ( LinearGradient 线性渐变渲染 | 设置渲染方向 | 设置渲染颜色 | 设置渲染模式 | MIRROR )

    文章目录 一.LinearGradient 线性渐变渲染 1.设置 2 个颜色的渐变 3.设置多个颜色的渐变 二.LinearGradient 线性渐变渲染重要参数分析 1.正常渲染 2.设置多个渐变 ...

  2. Android GLSurfaceView.Renderer 类 onDrawFrame 方法的刷新机制

    这玩意只要不是设置渲染模式是when dirty,就会一直调用这个函数,我之前一直以为是采集到数据才会调用 http://blog.waterlin.org/articles/the-principl ...

  3. Android GLSurfaceView详解

    学习在Android中使用OpenGL ES,就不得不提到一个控件:GLSurfaceView GLSurfaceView从Android 1.5(API level 3)开始加入,继承自Surfac ...

  4. 【音视频安卓开发 (六)】Android GLSurfaceView播放视频

    GLSurfaceView渲染RGB的数据,利用双缓冲空间机制.取出缓冲地址,将要渲染的数据copy到缓冲地址. 获取Surface Java部分: SurfaceView控件设置到界面中显示 Sur ...

  5. 关于Android Framework渲染机制,你需要学习哪些?

    聊到Android的渲染流程部分,部分Android开发脑海中估计又会想起面试官在面试时提出的那些死亡面试题: Android渲染的整体架构是怎样的? Android渲染的生产者包括哪些?Skia与O ...

  6. iOS 7 跳过的一个坑又掉里了 - 图片渲染模式

    iOS 7 跳过的一个坑又掉里了 - 图片渲染模式 太阳火神的美丽人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作 ...

  7. android新架构模式_Android MVIReact架构模式

    android新架构模式 If you are already aware of basic principles of architecture patterns and MVVM and MVI ...

  8. Android UI 渲染机制的演进,你需要了解什么?

    前言 如今UI 渲染可能是诸多性能问题中最容易被察觉到的,Android 开发既要面对各式各样的手机屏幕尺寸和分辨率,还要与"凶残"的产品和 UI 设计师过招. 在正确实现复杂.炫 ...

  9. Android GLSurfaceView用法解析

    OpenGL和OpenGLES简介 这里先简单介绍下OpenGL和OpenGLES.OpenGL(Open Graphics Library)意为开放图形库,是一个跨平台的图形API,用于指定3D图形 ...

最新文章

  1. 第一个Servlet和Jsp
  2. shell脚本的测试与判断的基础实施
  3. react 封装表格组件_React--封装的表单组件
  4. 大连理工18秋计算机应用基础,大连理工大学网络教育本科计算机应用基础入学考试模拟题...
  5. layui 数据表格 日期格式化
  6. quercus mysql_让PHP运行在Glassfish中:quercus配置
  7. Android 系统(41)---善用工具
  8. Java Sokect编程之HTTP请求
  9. 029、JVM实战总结:大厂面试题:最新的G1垃圾回收器的工作原理,你能聊聊吗
  10. 在任务分解结果中,最底层的要素必须是实现项目目标的充分必要条件
  11. android下拉刷新完全解析,教你如何一分钟实现下拉刷新功能,高仿京东下拉刷新,轻松上手!...
  12. XenApp6.5启用3D功能
  13. 员工请假审批系统 php,php073企业考勤请假系统
  14. EHCache的使用教程
  15. 编程高手与IT民工的区别在哪?
  16. 实战 | 用 Python 选股票,据说可以多挣个20%
  17. 阴阳师服务器维护稍后,《阴阳师》11月7日更新维护到几点 暂时无法进入服务器进行游戏...
  18. 英语单词记忆 词源法-思维导图(20)词源st/sist/stat/stin/stem-217
  19. ADS1220 24位高精度ADC芯片驱动
  20. 《HTML5与CSS3基础教程》第四章学习笔记 文本

热门文章

  1. python openpyxl读取excel_Python使用openpyxl读写excel文件
  2. class.forname找不到类_15个“专科专业”就业找工作容易,关注热度也挺高,报考比较靠谱...
  3. 21.5. 流量控制
  4. defensive-bash-programming
  5. 你不可不知的家庭装修禁忌
  6. viewpage的使用
  7. Solr配置与简单Demo[转]
  8. 味道不错的NBearLite查询语法
  9. 修复Long类型太长转为JSON格式的时候出错的问题
  10. Maven项目上总有一个小红叉问题