Android OpenGL ES滤镜开发设计

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

内容简介:按照正常的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滤镜开发设计》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

区块链与人工智能:数字经济新时代

区块链与人工智能:数字经济新时代

高航、俞学劢、王毛路 / 电子工业出版社 / 2018-7-23 / 80

《区块链与人工智能》是畅销书《区块链与新经济:数字货币2.0时代》全新修订升级版。本书是市场上为数不多的系统阐述区块链、人工智能技术与产业的入门级系统教程。从比特币到各类数字货币(代币),从基础原理到应用探讨,全景式呈现区块链与人工智能的发展脉络,既有历史的厚重感也有科技的未来感。本书的另一个亮点是系统整理了区块链创业地图,是一本关于区块链创业、应用、媒体的学习指南,以太坊创始人Vitalik专门......一起来看看 《区块链与人工智能:数字经济新时代》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码