一、引入
按照正常的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 mFilterQueue = new ConcurrentLinkedQueue(); // glThread和MainThread都会操作这个,所以用ConcurrentLinkedQueue
private List mFilters = new CopyOnWriteArrayList(); // 有遍历和多线程操作,防止抛异常
@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 getFilterList() {
return mDefaultFilterGroup.getFilterList();
}
@Override
public void clear() {
mDefaultFilterGroup.clear();
}
}
四、使用
1,. 继承 AbsFilter
或实现 IFilter
制作滤镜;
实现 FilterRenderer
,用 FilterRenderer#addFilter
添加自己写的滤镜(步骤3后面add也可以);
GLSurfaceView#setRenderer
。