目录
  1. 1. OpenGL是什么?OpenGL ES又是什么?
    1. 1.1. 简介
    2. 1.2. 应用场景
    3. 1.3. Android对OpenGL ES 的支持
    4. 1.4. 版本的选择
    5. 1.5. 导入
  2. 2. 基本框架
    1. 2.1. GLSrufaceView
    2. 2.2. GLSurfaceView.Renderer
  3. 3. 编写流程
    1. 3.1. 编写Activity
    2. 3.2. 编写Renderer
OpenGL ES 2.0笔记1——简介

OpenGL是什么?OpenGL ES又是什么?

简介

OpenGL是一个跨平台的软件接口语言,用于调用硬件的2D、3D图形处理器。

然而受限于现在的移动设备性能,如果将OpenGL直接用在他们上面将会特别卡,于是就出现了OpenGL ES。 OpenGL ES是OpenGL的分支,他专门作用于嵌入式设备,去掉了OpenGL很多不必要的功能。

应用场景

  • 游戏
  • 视频播放器
  • 视频编辑应用
  • 图片编辑应用

等对图像处理的及时性要求较高的应用场景。

Android对OpenGL ES 的支持

OpenGL ES 版本 基于OpenGL的版本 Android引入的版本 兼容性 功能、特色
1.0&1.1 1.3&1.5 Android 1.0 - 固定的图像管道,开发难度相比2.0低
2.0 2.0 Android 2.2 不兼容1.x 可编程的渲染管道,性能效率更高,开发难度更高
3.0 3.x Android 4.3 兼容2.0 性能更高,支持ETC2格式的透明纹理压缩
3.1 4.x Android 5.0 兼容2.0/3.0 新增计算着色器、单独的着色器对象等新特性

版本的选择

由于此篇博客是学习阶段写的,而我在网上找到的大部分博客都是2.0,所以就以2.0为主。

其实我觉得应该是3.0,2.0确实太老了,现在Android4.3的手机都较少见了,而3.1又太新了。

导入

首先你得在AndroidManifest.xml中加入
<uses-feature android:glEsVersion="0x00020000" android:required="true" />

其中不同版本对应值:

OpenGL ES 版本 glEsVersion 版本
2.0 0x00020000
3.0 0x00030000
3.1 0x00030001

基本框架

Android框架里面提供了两个类来给你使用OpenGL ES API创建和操作图形:GLSrufaceViewGLSurfaceView.Renderer

GLSrufaceView

这是一个视图类,你可以通过OpenGL ES API来绘制和操作图形对象,他在功能上很类似与SurfaceView。你可以通过创建一个SurfaceView的实例并添加你的渲染器来使用这个类。

他的常用方法有:

  • setEGLContextClientVersion:设置OpenGL ES版本,2.0则设置2
  • onPause:暂停渲染,最好是在ActivityFragmentonPause()方法内调用,减少不必要的性能开销,避免不必要的崩溃
  • onResume:恢复渲染,用法类比onPause()
  • setRenderer:设置渲染器
  • setRenderMode:设置渲染模式
  • requestRender: 请求渲染,由于是请求异步线程进行渲染,所以不是同步方法,调用后不会立刻就进行渲染。渲染会回调到Renderer接口的onDrawFrame()方法。
  • queueEvent:插入一个Runnable任务到后台渲染线程上执行。相应的,渲染线程中可以通过ActivityrunOnUIThread的方法来传递事件给主线程去执行

其中,GLSurfaceView的渲染模式有:

  • RENDERMODE_CONTINUOUSLY:不停地渲染
  • RENDERMODE_WHEN_DIRTY:只有调用了requestRender()之后才会触发渲染回调onDrawFrame方法

GLSurfaceView.Renderer

此接口定义了在GLSurfaceView中绘制图形所需的方法。必须将此接口的实现作为单独的类提供,并使用GLSurfaceView.setRenderer()将其添加到GLSurfaceView的实现类中。

他的主要方法有三个:

  • onSurfaceCreated(GL10 gl, EGLConfig config):GLSurfaceView内的Surface被创建时会被调用到
  • onSurfaceChanged(GL10 gl, int width, int height):Surface尺寸改变时调用到
  • onDrawFrame(GL10 gl):渲染绘制每一帧时调用到

一般情况下,首次创建GLSurfaceView时,会顺序调用onSurfaceCreated() -> onSurfaceChanged() -> onDrawFrame()。然后每绘制一帧,都会不停地回调onDrawFrame()方法。

编写流程

首先我们来写一个基本框架。

创建一个Android项目,然后Activity选择EmptyActivity。

注意:本项目某些类或者方法通过AndroidStudio导入的时候会让你选择是从哪个包里面导入,一致选择android.opengl.GLES20

编写Activity

打开我们项目的MainActivity,你就能看到熟悉的onCreate方法,接下来我们要对这个Activity进行一些更改。

首先,我们要创建一个GLSurfaceView的对象,并添加一个新的成员变量:

1
2
private GLSurfaceView glSurfaceView;
private boolean rendererSet = false;

接下来将setContentView()移除,并对glSurfaceView进行初始化:

1
2
3
4
5
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
glSurfaceView = new GLSurfaceView(this);
}

由于我们是在写OpenGL ES2.0的代码,所以我们需要检测当前运行APP的系统支不支持OpenGL ES2.0。我们将下面几行代码添加到onCreate()里面去:

1
2
3
final ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
final ConfigurationInfo configurationInfo = activityManager.deviceConfigurationInfo();
final boolean supportsEs2 = configurationInfo.reqGlEsVersion >= 0x20000;

但是这段代码在模拟器上不能工作,因为GPU模拟部分有缺陷。为了使代码在模拟器上运行,我们要按如下代码修改检查条件:

1
2
3
4
5
6
7
final boolean supportsEs2 = configurationInfo.reqGlEsVersion >= 0x20000
|| (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 build for x86")))

接下来就是配置渲染表面:

1
2
3
4
5
6
7
8
9
10
11
12
13
if (supportsEs2) {
// 配置这个surface视图
glSurfaceView.setEGLContextClientVersion(2);

// 配置Renderer
glSurfaceView.setRenderer(FirstOpenGLProjectRenderer());
rendererSet = true;
} else {
Toast.makeText(this, "This device does not support OpenGL ES 2.0", Toast.LENGTH_SHORT).show();
return;
}

setContentView(glSurfaceView);

最后我们还得处理下Activity的生命周期,也就是将GLSurfaceView的生命周期跟Activity的生命周期绑定起来:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Override
void onPause() {
super.onPause();

if (rendererSet)
glSurfaceView.onPause();
}

@Override
void onResume() {
super.onResume();

if (rendererSet)
glSurfaceView.onResume();
}

编写Renderer

创建一个新的文件,命名为FirstOpenGLProjectRenderer,让让这个类继承自GLSurfaceView.Renderer。

接着就实现三个必备方法:

  • onSurfaceCreate():创建时被调用
1
2
3
4
@Override
public void onSurfaceCreated(GL10 glUnsed, EGLConfig config) {
glClearColor(1.0f, 0.0f, 0.0f, 0.0f); //设置一个清空屏幕用的颜色
}
  • onSurfaceChanged():创建后每当Surface尺寸改变时,都调用此方法
1
2
3
4
@Override
public void onSurfaceChanged(GL10 glUnsed, int width, int height) {
glViewport(0, 0, width, height); //设置视窗尺寸
}
  • onDrawFrame():绘制每一帧时调用
1
2
3
4
@Override
public void onDrawFrame(GL10 glUnsed) {
glClear(GL_COLOR_BUFFER_BIT); //清空屏幕
}

然后就可以运行程序了,你就可以看到整个屏幕都成了红色,这是为啥呢?
因为我们在onSurfaceCreated方法里面设置了glClearColor(1.0f,0.0f,0.0f,0.0f)。这个方法的参数对应的是RGBA,然后我们又在onDrawFrame方法中设置了清屏,所以这样你就会看到的是红色了。

文章作者: littlecorgi
文章链接: https://a1203991686.github.io/posts/a92b4a54.html
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 littlecorgiの小站
打赏
  • 微信
  • 支付寶

评论