内容简介:按照正常的Android OpenGL开发,一般只需引入两个“主角”:这里定义一个滤镜需要实现的接口。
一、引入
按照正常的Android OpenGL开发,一般只需引入两个“主角”: GLSurfaceView
和 Renderer
。在拍摄这种各种挂件和特效纵横的场景下, Renderer
会变得臃肿和不堪重负,而且 不够灵活
地去替换各种挂机和特效。正如 Activity
引入 Fragment
,同理,这里我们的 Renderer
引入 Filter
。
二、定义
Filter
定义为一个小型的 Renderer
,一个 Renderer
可以有多个 Filter
,可以增删 Filter
, Filter
间可以互相叠加特效。
三、代码设计
1. IFilter
这里定义一个滤镜需要实现的接口。
public interface IFilter { void create(); // Renderer#onSurfaceCreated时调用 void changeSize(int width, int height);// Renderer#onSurfaceChanged时调用 void draw();// Renderer#onDrawFrame时调用 }
在这个接口的基础上,按照OpenGL常用的代码实现过程,抽出一个抽象类来。
public abstract class AbsFilter implements IFilter{ @Override public final void create(){ onCreateProgram(); onCreate(mProgram); } @Override public final void changeSize(int width, int height){ onSizeChange(width, height); } @Override public final void draw() { onClear(); onUseProgram(); onSetExpandData(); onBindTexture(); onDraw(); } protected void onCreateProgram() { // loadShader && createProgram 减少代码阅读压力,此处简写 } protected void onUseProgram() { GLES20.glUseProgram(mProgram); } protected abstract void onCreate(int program); protected abstract String getVertexShaderCode(); // 子类实现,返回vertex shader 代码段内容。 protected abstract String getFragmentShaderCode(); // 子类实现,返回fragment shader 代码段内容。 protected abstract void onSizeChange(int width, int height); protected abstract void onClear(); // 颜色清屏 protected abstract void onSetExpandData(); // 传给shader一些其他的参数 protected abstract void onBindTexture(); // 绑定texture protected abstract void onDraw(); // 绘制 }
2. IFilterGroup
除了 Filter
,还需要一个 FilterGroup
来管理这些个 Filter
。
public interface IFilterGroup { void addFilter(IFilter filter); void removeFilter(IFilter filter); boolean containsFilter(IFilter filter); void clear(); }
这时,其实有人会这么说,干嘛要用 FilterGroup
,直接用 List
来不就可以了吗?
我们先看下这个 IFilterGroup
的实现,以此来解答这个疑问。
public class FilterGroup implements IFilterGroup, IFilter{ private int mWidth; private int mHeight; private Queue<IFilter> mFilterQueue = new ConcurrentLinkedQueue<IFilter>(); // glThread和MainThread都会操作这个,所以用ConcurrentLinkedQueue private List<IFilter> mFilters = new CopyOnWriteArrayList<IFilter>(); // 有遍历和多线程操作,防止抛异常 @Override public void create() { for (IFilter filter : mFilters) { filter.create(); } } @Override public void changeSize(int width, int height) { this.mWidth = width; this.mHeight = height; updateFilter(); for (IFilter filter : mFilters) { filter.changeSize(width, height); } } @Override public void draw() { updateFilter(); for (IFilter filter : mFilters) { filter.draw(); } } @Override public void addFilter(IFilter filter) { this.mFilterQueue.add(filter); } @Override public void removeFilter(IFilter filter) { // 减少阅读压力,简单代码,此处省略 } @Override public boolean containsFilter(IFilter filter) { // 减少阅读压力,简单代码,此处省略 } @Override public void clear() { // 减少阅读压力,简单代码,此处省略 } private void updateFilter() { IFilter f; while ((f=mFilterQueue.poll())!=null){ f.create(); f.changeSize(mWidth,mHeight); mFilters.add(f); } } }
因为, Filter
有着与 Renderer
相似的方法,由于 Filter
可支持动态添加的缘故,可能会出现 Renderer
的 onSurfaceCreated
和 onSurfaceChanged
都执行过了, Filter
无法执行 create
和 changeSize
,之后执行 draw
。
故需要有一个如同 FilterGroup
,有一个 updateFilter
方法,将添加的 Filter
先存放在一个队列中,等要执行 Renderer
的 onDrawFrame
方法时,将所有从队列取出执行前面未执行到的 create
和 changeSize
方法,后才加入到正常的 Filter
的 List
中,一起去执行 draw
方法。
而执行 updateFilter
方法的时机是 Renderer
的 onSurfaceChanged
和 onDrawFrame
时。
3. FilterRenderer
讲完 IFilter
和 IFilterGroup
,接下来就要讲下上面两个在 Renderer
里的使用了。
public class FilterRenderer implements GLSurfaceView.Renderer, IFilterGroup{ private FilterGroup mDefaultFilterGroup = new FilterGroup(); @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { mDefaultFilterGroup.create(); } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { mDefaultFilterGroup.changeSize(width, height); } @Override public void onDrawFrame(GL10 gl) { mDefaultFilterGroup.draw(); } @Override public void addFilter(IFilter filter) { mDefaultFilterGroup.addFilter(filter); } @Override public void removeFilter(IFilter filter) { mDefaultFilterGroup.removeFilter(filter); } @Override public boolean containsFilter(IFilter filter) { return mDefaultFilterGroup.containsFilter(filter); } @Override public List<IFilter> getFilterList() { return mDefaultFilterGroup.getFilterList(); } @Override public void clear() { mDefaultFilterGroup.clear(); } }
四、使用
1,. 继承 AbsFilter
或实现 IFilter
制作滤镜;
-
实现
FilterRenderer
,用FilterRenderer#addFilter
添加自己写的滤镜(步骤3后面add也可以); -
GLSurfaceView#setRenderer
。
以上所述就是小编给大家介绍的《Android OpenGL ES滤镜开发设计》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 作为后端开发如何设计数据库系列文章(二)设计大数据量表结构(Java开发)
- 微页面设计开发指南
- Kubernetes 设计与开发原则
- MongoDB提升性能的18原则(开发设计阶段)
- 从Git设计原理到业务系统设计与开发
- 设计和架构:业务开发指导原则
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。