OpenGL ES之GLSurfaceView使用详解 您所在的位置:网站首页 opengl底层 OpenGL ES之GLSurfaceView使用详解

OpenGL ES之GLSurfaceView使用详解

#OpenGL ES之GLSurfaceView使用详解| 来源: 网络整理| 查看: 265

一.GLSurfaceView概述

GLSurfaceView从Android 1.5(API level 3)开始加入,继承自SurfaceView,实现了SurfaceHolder.Callback2接口,拥有SurfaceView的全部特性,也有view所有的功能和属性,特别是处理事件的能力,它主要是在SurfaceView的基础上它加入了EGL的管理,并自带了一个GLThread绘制线程(EGLContext创建GL环境所在线程即为GL线程),绘制的工作直接通过OpenGL在绘制线程进行,不会阻塞主线程,绘制的结果输出到SurfaceView所提供的Surface上,这使得GLSurfaceView也拥有了OpenGlES所提供的图形处理能力,通过它定义的Render接口,使更改具体的Render的行为非常灵活性,只需要将实现了渲染函数的Renderer的实现类设置给GLSurfaceView即可。

 GLSurfaceView的特性:

1.管理一个surface,这个surface就是一块特殊的内存,能直接排版到android的视图view上。

2.管理一个EGL display,它能让opengl把内容渲染到上述的surface上。

3.用户自定义渲染器(render)。

4.让渲染器在独立的线程里运作,和UI线程分离。

5.支持按需渲染(on-demand)和连续渲染(continuous)。

6.可以封装、跟踪并且排查渲染器的问题。

 

二.GLSurfaceView的基本使用

1.创建GLSurfaceView

GLSurfaceView一般有两种创建方式:(1)一种是在android布局文件中配置;(2)直接在代码中new出来;

以下是第一种方式:xml文件中配置:

在上面的代码中,因为GLSurfaceView本身就是一个View控件,所以是可以直接在xml中添加该控件,然后就可以直接在Activity或者fragment中通过id找到该控件并操作它;

以下是通过new的方法直接创建GLSurfaceView的实例:

package com.yh.opengltext01; import android.app.Activity; import android.app.ActivityManager; import android.content.pm.ConfigurationInfo; import android.opengl.GLSurfaceView; import android.os.Build; import android.os.Bundle; import android.widget.Toast; public class MainActivity extends Activity { private GLSurfaceView mGLSurfaceView; private boolean mRendererSet = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mGLSurfaceView = new GLSurfaceView(this); final ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE); final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo(); final boolean supportsEs2 = configurationInfo.reqGlEsVersion >= 0x20000 ||(Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) &&(Build.FINGERPRINT.startsWith("generic")) || Build.FINGERPRINT.startsWith("unknow") || Build.MODEL.contains("google_sdk") || Build.MODEL.contains("Emulator") || Build.MODEL.contains("Android SDK built for x86"); if (supportsEs2){ mGLSurfaceView.setEGLContextClientVersion(2); mGLSurfaceView.setRenderer(new SimpleRenderer(this)); mRendererSet = true; }else { Toast.makeText(this , "This device does not support OpenGL ES 2.0." , Toast.LENGTH_SHORT).show(); return; } setContentView(mGLSurfaceView); } @Override protected void onPause() { if (mRendererSet){ mGLSurfaceView.onPause(); } super.onPause(); } @Override protected void onResume() { super.onResume(); if (mRendererSet){ mGLSurfaceView.onResume(); } } } Activity的onCreate方法中首先我们就创建GLSurfaceView的实例: mGLSurfaceView = new GLSurfaceView(this); 第二步我们判断了当前设备是否支持OpenGL ES2,不支持我们直接retrun,并做相应的提示,后面“||”是为了判断设备是不是模拟器的情况: final boolean supportsEs2 = configurationInfo.reqGlEsVersion >= 0x20000 ||(Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) &&(Build.FINGERPRINT.startsWith("generic")) || Build.FINGERPRINT.startsWith("unknow") || Build.MODEL.contains("google_sdk") || Build.MODEL.contains("Emulator") || Build.MODEL.contains("Android SDK built for x86"); 第三步如果支持,我们为我们GLSurfaceView配置一些简单的属性,并为它设置渲染器(Render),渲染器我们之后会解释: mGLSurfaceView.setEGLContextClientVersion(2); //设置渲染器 mGLSurfaceView.setRenderer(new SimpleRenderer(this)); 第四步,把我们GLSurfaceView的生命周期和Activity的生命周期绑定: @Override protected void onPause() { if (mRendererSet){ mGLSurfaceView.onPause(); } super.onPause(); } @Override protected void onResume() { if (mRendererSet){ mGLSurfaceView.onResume(); }   super.onResume(); }

 

以上第二步到最后一步在使用id获取GLSurfaceView也是需要这样做的; 

这样一个简单初始化GLSurfaceView的初始化就做好了;

三.GLSurfaceView的事件处理

为了处理事件,一般都是继承GLSurfaceView类并重载它的事件方法,但是由于GLSurfaceView是多线程的,渲染器在独立的渲染线程里,你应该使用Java的跨线程机制跟渲染器通讯,GLSurfaceView提供的queueEvent(Runnable)方法就是一种相对简单的操作,queueEvent()方法被安全地用于在UI线程和渲染线程之间进行交流通信:

该方法的原型:

/** * Queue a runnable to be run on the GL rendering thread. This can be used * to communicate with the Renderer on the rendering thread. * Must not be called before a renderer has been set. * @param r the runnable to be run on the GL rendering thread. */ public void queueEvent(Runnable r) { mGLThread.queueEvent(r); }

 简单的使用:

package com.yh.opengltext01; import android.content.Context; import android.opengl.GLSurfaceView; import android.util.AttributeSet; import android.view.KeyEvent; import android.view.MotionEvent; public class MyGLSurfaceView extends GLSurfaceView { public MyGLSurfaceView(Context context) { super(context); } public MyGLSurfaceView(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { queueEvent(new Runnable() { // 这个方法会在渲染线程里被调用 public void run() { //todo 写自己的逻辑 } }); return true; } return super.onKeyDown(keyCode, event); } @Override public boolean onTouchEvent(MotionEvent event) { queueEvent(new Runnable() { public void run() { //todo 做自己的逻辑 } }); return super.onTouchEvent(event); } }

如果在UI线程里调用渲染器的方法,因为UI事件和渲染绘制是在不同的线程里,会收到“call to OpenGL ES API with no current context”的警告,典型的案例就是在键盘或触摸事件方法里直接调用opengl es的API。

以上就是OpenGLSurfaceView的简单使用;



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有