框架源码:https://github.com/smzhldr/AGLFramework
一、前言
安卓中,OpenGL ES的开发有基本着固定的代码形式,为实现不同的功能,只需将shader编写好,按步就班的在代码中调用就可以了,但是OpenGL ES提供的API比较抽象,写起来不容易记忆,而且重复代码有可能较多。为了使用的更方便,我们简单的封装成一个库的形式,这在第一篇《五分钟开发一款美颜相机》 中已经简单使用过该框架,确实简单易用,以后所提到的功能实现,我们基本上都基于该框架实现。
二、框架目录一览
AGLView-----------------继承自GLSurfaceView,显示OpenGL ES代码输出结果。
AGLRenderer-------------继承自GLSurfaceView.Renderer,渲染逻辑控制器。
ISource-----------------AGLRenderer输入源,包括视屏,图片等数据流。
IFilter-----------------数据处理器,可有不同的实现,比如美颜功能,y由不同的处理Filter完 成,只需在AGLRenderer中调用不同的Filter就可完成不同的图像处理效果。
OpenGlUtils-------------OPenGl ES代码编译使用工具类
有了上面这几个类,基本上这个框架就可以使用的,实现不同的功能只需要调用用不同的Filter就行,其他部分完全相同不用重写,这在开发效率上和代码层次上有很大帮助。
三、框架原理浅析
该框架继承GLSurfaceView,逻辑部分都在AGLRenderer中,而实现部分都在Filter层,逻辑如下:
@Override
public void onDrawFrame(GL10 gl) {
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
runAll(runOnDraw);
if (rendererSource != null) {
//生成每一帧的数据源
IFilter.Frame frame = source.createFrame();
//为元数据添加美颜,贴纸等特效
if (filter != null && !disable) {
frame = filter.draw(frame);
}
//将美化后的数据输出到屏幕
if (outputFilter != null) {
outputFilter.draw(frame);
}
}
runAll(runOnDrawEnd);
}
可以看出框架的原理很简单也很清晰,我们使用框架的重点就是编写好自己的filter就可以实现我们想要的特效了。
三、Filter的使用
花时间造这个框架(其实也不算啥框架)的目的是为了更方便,更直接的编写OpenGL的代码,而不是把时间花在OpenGL的使用环境搭建上,就像是画画的核心是画内容而不是调颜料,虽然调颜料也很重要。。。
filter的使用我们只需实现Ifilter接口就行,请看栗子:
public class MyFilter implements IFilter {
/*
* draw方法是每一帧都会调用的方法
* 在draw中运行我们的OpenGL代码以达到特效处理功能
*/
public Frame draw(Frame frame) {
...
return frame;
}
//释放OpenGL相关资源
public void destroy() {
...
}
}
从上面的栗子可以看出,filter的内容几乎都在draw方法中,
draw方法中需要做的工作有:
1.使用OpenglUtils编译链接shader
2.初始化shader变量
3.填充数据并绘制
//有了filter之后,一个set就可以使用
AGLView.setFilter(IFilter filter)
对于每一个filter,其中大部分代码都是相同的,尤其是初始化和绘制的顶点坐标和纹理坐标,所以我们封装一个输出绘制原图的AGLFilter,一般的功能继承这个filter就可以:
public class MyFilter extends AGLFilter {
@Override
public void onInit() {
//编译shader,初始化shader变量
programId = OpenGlUtils.loadProgram(vertexShaderCode, fragmentShaderCode);
...
}
@Override
protected void onDrawArraysPre(Frame frame) {
//父类中完成了渲染texture的工作
//如果在渲染中需要额外的工作,需要重写此方法,否则不需要
}
}
可以看出封装后我们只需要认真的编写好shader,并完成初始化,赋值就可以看到我们想要的特效了。
对于功能复杂的filter,可以直接去实现IFilter接口,虽然代码会多一些,但扩展起来更灵活。
四、后记
以后关于OpenGL ES的代码我们都将使用AGLFrameWork框架处理,也就是只需要编写不同的Filter就可以了。 还不理解可以参考文章开头框架源码或者留言交流。