前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android OpenGL ES滤镜开发设计

Android OpenGL ES滤镜开发设计

原创
作者头像
Clayman Twinkle
发布2018-07-25 18:35:29
9790
发布2018-07-25 18:35:29
举报
文章被收录于专栏:Android原创

一、引入

按照正常的Android OpenGL开发,一般只需引入两个“主角”:GLSurfaceViewRenderer。在拍摄这种各种挂件和特效纵横的场景下,Renderer会变得臃肿和不堪重负,而且不够灵活地去替换各种挂机和特效。正如Activity引入Fragment,同理,这里我们的Renderer引入Filter

二、定义

Filter定义为一个小型的Renderer,一个Renderer可以有多个Filter,可以增删FilterFilter间可以互相叠加特效。

三、代码设计

1. IFilter

这里定义一个滤镜需要实现的接口。

代码语言:txt
复制
public interface IFilter {
    void create(); // Renderer#onSurfaceCreated时调用
    void changeSize(int width, int height);// Renderer#onSurfaceChanged时调用
    void draw();// Renderer#onDrawFrame时调用
}

在这个接口的基础上,按照OpenGL常用的代码实现过程,抽出一个抽象类来。

代码语言:txt
复制
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

代码语言:txt
复制
public interface IFilterGroup {
    void addFilter(IFilter filter);
    void removeFilter(IFilter filter);
    boolean containsFilter(IFilter filter);
    void clear();
}

这时,其实有人会这么说,干嘛要用FilterGroup,直接用List来不就可以了吗?

我们先看下这个IFilterGroup的实现,以此来解答这个疑问。

代码语言:txt
复制
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可支持动态添加的缘故,可能会出现RendereronSurfaceCreatedonSurfaceChanged都执行过了,Filter无法执行createchangeSize,之后执行draw

故需要有一个如同FilterGroup,有一个updateFilter方法,将添加的Filter先存放在一个队列中,等要执行RendereronDrawFrame方法时,将所有从队列取出执行前面未执行到的createchangeSize方法,后才加入到正常的FilterList中,一起去执行draw方法。

而执行updateFilter方法的时机是RendereronSurfaceChangedonDrawFrame时。

3. FilterRenderer

讲完IFilterIFilterGroup,接下来就要讲下上面两个在Renderer里的使用了。

代码语言:txt
复制
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制作滤镜;

  1. 实现FilterRenderer,用FilterRenderer#addFilter添加自己写的滤镜(步骤3后面add也可以);
  2. GLSurfaceView#setRenderer

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、引入
  • 二、定义
  • 三、代码设计
    • 1. IFilter
      • 2. IFilterGroup
        • 3. FilterRenderer
        • 四、使用
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档