android opengl滤镜,Android OpenGL ES滤镜开发设计

一、引入

按照正常的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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值