Android OpenGL ES滤镜开发设计

栏目: 编程工具 · 发布时间: 7年前

内容简介:按照正常的Android OpenGL开发,一般只需引入两个“主角”:这里定义一个滤镜需要实现的接口。

一、引入

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

二、定义

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

三、代码设计

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

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

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

3. FilterRenderer

讲完 IFilterIFilterGroup ,接下来就要讲下上面两个在 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 制作滤镜;

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

以上所述就是小编给大家介绍的《Android OpenGL ES滤镜开发设计》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

让云落地

让云落地

【美】Michael J. Kavis(迈克尔 J.凯维斯) 著 / 陈志伟、辛敏 / 电子工业出版社 / 2016-3 / 65.00元

云计算落地已成事实。从前几年的概念普及,到如今越来越多的企业将业务迁移至云上,云计算正在改变整个社会的信息资源使用观念和方式。云计算还在不断成长,技术细节也在不断变化之中。对于使用者而言,能够基于自身的业务、技术和组织需求等各方面情况,选择正确的云服务模式,是成功使用云计算最关键的技术决策之一。 《让云落地:云计算服务模式(SaaS、PaaS和IaaS)设计决策》共有 16 章,作者有意避开......一起来看看 《让云落地》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具