美文网首页AndroidHot音视频/图像处理
android-opengl-canvas里代替GLSurfac

android-opengl-canvas里代替GLSurfac

作者: chillingvan | 来源:发表于2016-11-15 09:50 被阅读2167次

本文主要说明GLTextureView,一个代替GLSurfaceView的自定义View。将会说明包括GLTextureView的优点,大致实现方式,以及使用。

一如既往地放项目地址:
android-openGL-canvas

本文相关的代码:
BaseGLTextureView

优点

其实Android官方在Android 4.0以后推出TextureView,本意就是想代替GLSurfaceView。可是TextureView在里面并没有像GLSurfaceView那样封装好一个绘制线程以及OpenGL的初始化。所以GLTextureView将会实现这些部分。
GLTextureView的优点其实也包括TextureView的优点,在官方文档里也有说明: TextureView 不会创建一个分离的window,而是像一个普通的view那样显示, 这样就不会像GLSurfaceView那样,要么在所有View上方,要么被其它View遮住(看 setZOrderOnTop(boolean) 的说明)。而且像myView.setAlpha(0.5f)这种方法调用后也会有效果了。

实现方式

实现需要使用GLThread,这是由GLSurfaceView.GLThread改造过来的类,关于这个类的说明请看
如何封装 opengl 流程 -- 以为android-opengl-canvas例

利用GLThread,实现过程就变得很简单了,以下是关键代码:

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        ...
        glThreadBuilder.setRenderMode(getRenderMode())
                .setSurface(surface)
                .setRenderer(renderer);
        ...
    }

        ...
        mGLThread = glThreadBuilder.createGLThread();
        mGLThread.start();
        ...
        mGLThread.surfaceCreated();
        mGLThread.onWindowResize(w, h);
        ...

    public void requestRender() {
        if (mGLThread != null) {
            mGLThread.requestRender();
        }
    }

可以看到,主要就是先实现TextureView.SurfaceTextureListener,然后在onSurfaceTextureAvailable时创建GLThread,传入自己的SurfaceTexture用于承载绘制的内容,就基本可以了。
以上代码里的setRenderer,就实现了像GLSurfaceView那样使用Renderer就可以实现绘制了。

剩下的就是流程控制的代码了。

    public void onPause() {
        if (mGLThread != null) {
            mGLThread.onPause();
        }
    }

    public void onResume() {
        if (mGLThread != null) {
            mGLThread.onResume();
        }
    }

    protected void surfaceDestroyed() {
        // Surface will be destroyed when we return
        mGLThread.surfaceDestroyed();
    }

    public void requestRender() {
        if (mGLThread != null) {
            mGLThread.requestRender();
        }
    }

实现就是这么简单。

使用

那么看看使用:

    public class GLTextureView extends BaseGLTextureView implements GLSurfaceView.Renderer
    ...
        setRenderer(this);
    ...
    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        mCanvas = new CanvasGL();
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        mCanvas.setSize(width, height);

    }

    @Override
    public void onDrawFrame(GL10 gl) {
        mGL = gl;
        mCanvas.clearBuffer(backgroundColor);
        onGLDraw(mCanvas);
    }

    protected abstract void onGLDraw(ICanvasGL canvas);

这里使用了封装好的canvasgl。
只要继承以上代码所在的类就可以啦。

    @Override
    protected void onGLDraw(ICanvasGL canvas) {
        canvas.drawBitmap(bitmap, 0, 0);
    }

效果图

效果图

上图左边就是GLTextureView的效果,右图是GPUImage的效果,知道这个库的应该知道它的内部实现就是用GLSurfaceView的吧。那么,就可以看看TextureView和GLSurfaceView的表现有什么区别了。

详细的请进入github地址进行查阅。

相关文章

网友评论

  • 徐世斌:大神,能不能实现一下gpuimage里面的GPUImageLookupFilter这个滤镜,根据你的demo自己试了一下,滤镜效果不对:disappointed_relieved:
  • sea5241:您好,看最新的GitHub工程,GLTextureView里的Render已经不回调GL10这个参数了,那如果我想用这个,从哪获取
  • 大脑好饿:如果要先在内存中绘制图像,绘制完成后再更新到屏幕上,应该怎么做?
    chillingvan: @只是个昵称 应该是后者,直接绘制到界面上比较高效率的,因为直接绘制是依赖GPU,而创建bitmap是依赖CPU比较多。
    如果是直接绘制到界面,那就应该不用offScreenCanvas了吧?
    大脑好饿:@chillingvan 是这样的场景,假设有一千个带透明度的小图片需要随机坐标和旋转角度绘制到界面上,我是先创建一个bitmap,先将所有的小图片绘制到这一个bitmap上去,然后再将这个bitmap绘制到canvas上;还是直接使用canvas.drawBitmap,一个一个的去绘制?哪种方式效率比较高?
    另外我看demo中OffScreenCanvas的使用是嵌套进行了第二次绘制,我只绘制一次然后获取图片是全黑色的?
    如果方便的话希望加QQ或者微信请求帮助。
    chillingvan:@只是个昵称 在内存中绘制图像的意思是在一个Bitmap上绘制吗?如果是,那么用canvas.drawBitmap(bitmap, 0, 0)方法或其它drawBitmap的方法就可以了。

本文标题:android-opengl-canvas里代替GLSurfac

本文链接:https://www.haomeiwen.com/subject/kamkpttx.html