按照正常的Android OpenGL开发,一般只需引入两个“主角”:GLSurfaceView
和Renderer
。在拍摄这种各种挂件和特效纵横的场景下,Renderer
会变得臃肿和不堪重负,而且不够灵活地去替换各种挂机和特效。正如Activity
引入Fragment
,同理,这里我们的Renderer
引入Filter
。
Filter
定义为一个小型的Renderer
,一个Renderer
可以有多个Filter
,可以增删Filter
,Filter
间可以互相叠加特效。
这里定义一个滤镜需要实现的接口。
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(); // 绘制
}
除了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
可支持动态添加的缘故,可能会出现Renderer
的onSurfaceCreated
和onSurfaceChanged
都执行过了,Filter
无法执行create
和changeSize
,之后执行draw
。
故需要有一个如同FilterGroup
,有一个updateFilter
方法,将添加的Filter
先存放在一个队列中,等要执行Renderer
的onDrawFrame
方法时,将所有从队列取出执行前面未执行到的create
和changeSize
方法,后才加入到正常的Filter
的List
中,一起去执行draw
方法。
而执行updateFilter
方法的时机是Renderer
的onSurfaceChanged
和onDrawFrame
时。
讲完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<IFilter> getFilterList() {
return mDefaultFilterGroup.getFilterList();
}
@Override
public void clear() {
mDefaultFilterGroup.clear();
}
}
1,. 继承AbsFilter
或实现IFilter
制作滤镜;
FilterRenderer
,用FilterRenderer#addFilter
添加自己写的滤镜(步骤3后面add也可以);GLSurfaceView#setRenderer
。原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。