12.OpenGL ES

OpenGL ES

android中 GLSurfaceView 繼承 SurfaceView

GLSurfaceView 中有 GLThread

setEGLContextClientVersion(2);//使用openGLES 2.0上下文
setRenderer(...);//設(shè)置渲染回調(diào)接口 該方法中實(shí)例化GLThread
 /**
 * 刷新方式:
 *     RENDERMODE_WHEN_DIRTY 手動(dòng)刷新,調(diào)用requestRender();
 *     RENDERMODE_CONTINUOUSLY 自動(dòng)刷新,大概16ms自動(dòng)回調(diào)一次onDraw方法
 */
//注意必須在setRenderer 后面。
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);

openGL 渲染管線 頂點(diǎn)->圖元裝配->光柵化(像素化)

            著色器(頂點(diǎn)著色器和片元著色器)

Android Studio 集成GLSLSupport插件 編輯OpenGL著色器語言(GLSL)時(shí)關(guān)鍵字高亮智能提示

openGL著色語言

attribute 屬性變量(只在頂點(diǎn)著色器使用)
uniforms 一致變量(片元著色器使用)
varying 易編變量(頂點(diǎn)著色器輸出數(shù)據(jù)到片元著色器)
gl_Position 坐標(biāo)(x,y,z,w)
samplerExternalOES  圖片采樣器
samplerExternalOES 相當(dāng)于rgba 使用texture2D(...)
precision / mediump / float  精度定義

openGL的世界坐標(biāo)和紋理坐標(biāo)

static final float COORD[] = {
            -1.0f, -1.0f,
            1.0f, -1.0f,
            -1.0f, 1.0f,
            1.0f, 1.0f,
    };

    static final float TEXTURE_COORD[] = {
            0.0f, 1.0f,
            1.0f, 1.0f,
            0.0f, 0.0f,
            1.0f, 0.0f,
    };
圖片.png
  1. onSurfaceCreated

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        //創(chuàng)建OpenGL 紋理 ,把攝像頭的數(shù)據(jù)與這個(gè)紋理關(guān)聯(lián)
        textures = new int[1];  //當(dāng)做能在opengl用的一個(gè)圖片的ID
        mCameraTexure.attachToGLContext(textures[0]);
        // 當(dāng)攝像頭數(shù)據(jù)有更新回調(diào) onFrameAvailable
        mCameraTexure.setOnFrameAvailableListener(this);//監(jiān)聽更新時(shí)手動(dòng)調(diào)用requestRender()
        screenFilter = new ScreenFilter(cameraView.getContext());
    }
    

    創(chuàng)建和初始化著色器供, 這些過程一般分為7個(gè)步驟:

創(chuàng)建頂點(diǎn)著色器對象(glcreateShader);

 向頂點(diǎn)著色器對象中填充著色器程序的源代碼(glshaderSource);

 編譯頂點(diǎn)著色器(glcompileShander);

創(chuàng)建片元著色器對象(glcreateShader);

 向片元著色器對象中填充著色器程序的源代碼(glshaderSource);

 編譯片元著色器(glcompileShander);

創(chuàng)建程序?qū)ο螅╣lcreateProgram);

 為程序?qū)ο蠓峙渲鳎╣lattachShader);

 連接程序?qū)ο螅╣llinkProgram);

 使用程序?qū)ο螅╣luseProgram)
//著色器程序準(zhǔn)備
public static int loadProgram(String vSource, String fSource) {
    /**
     * 頂點(diǎn)著色器
     */
    int vShader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
    //加載著色器代碼
    GLES20.glShaderSource(vShader, vSource);
    //編譯(配置)
    GLES20.glCompileShader(vShader);

    //查看配置 是否成功
    int[] status = new int[1];
    GLES20.glGetShaderiv(vShader, GLES20.GL_COMPILE_STATUS, status, 0);
    if (status[0] != GLES20.GL_TRUE) {
        //失敗
        throw new IllegalStateException("load vertex shader:" + GLES20.glGetShaderInfoLog
                (vShader));
    }

    /**
     *  片元著色器
     *  流程和上面一樣
     */
    int fShader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
    //加載著色器代碼
    GLES20.glShaderSource(fShader, fSource);
    //編譯(配置)
    GLES20.glCompileShader(fShader);

    //查看配置 是否成功
    GLES20.glGetShaderiv(fShader, GLES20.GL_COMPILE_STATUS, status, 0);
    if (status[0] != GLES20.GL_TRUE) {
        //失敗
        throw new IllegalStateException("load fragment shader:" + GLES20.glGetShaderInfoLog
                (vShader));
    }


    /**
     * 創(chuàng)建著色器程序
     */
    int program = GLES20.glCreateProgram();
    //綁定頂點(diǎn)和片元
    GLES20.glAttachShader(program, vShader);
    GLES20.glAttachShader(program, fShader);
    //鏈接著色器程序
    GLES20.glLinkProgram(program);


    //獲得狀態(tài)
    GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, status, 0);
    if (status[0] != GLES20.GL_TRUE) {
        throw new IllegalStateException("link program:" + GLES20.glGetProgramInfoLog(program));
    }
    GLES20.glDeleteShader(vShader);
    GLES20.glDeleteShader(fShader);
    return program;
}
  1. onSurfaceChanged設(shè)置寬高

  2. onDrawFrame

    @Override
    public void onDrawFrame(GL10 gl) {
        //todo 更新紋理
        mCameraTexure.updateTexImage();//拿到最新的圖像數(shù)據(jù)
        mCameraTexure.getTransformMatrix(mtx);
        screenFilter.setTransformMatrix(mtx);
        screenFilter.onDraw(textures[0]);
    }
    
    public int onDraw(int texture, FilterChain filterChain) {
            FilterContext filterContext = filterChain.filterContext;
            //設(shè)置繪制區(qū)域
            GLES20.glViewport(0, 0, filterContext.width, filterContext.height);
    
    
            GLES20.glUseProgram(program);
    
            vertexBuffer.position(0);
            // 4、歸一化 normalized  [-1,1] . 把[2,2]轉(zhuǎn)換為[-1,1]
            GLES20.glVertexAttribPointer(vPosition, 2, GLES20.GL_FLOAT, false, 0, vertexBuffer);
            //CPU傳數(shù)據(jù)到GPU,默認(rèn)情況下著色器無法讀取到這個(gè)數(shù)據(jù)。 需要我們啟用一下才可以讀取
            GLES20.glEnableVertexAttribArray(vPosition);
    
    
            textureBuffer.position(0);
            // 4、歸一化 normalized  [-1,1] . 把[2,2]轉(zhuǎn)換為[-1,1]
            GLES20.glVertexAttribPointer(vCoord, 2, GLES20.GL_FLOAT, false, 0, textureBuffer);
            //CPU傳數(shù)據(jù)到GPU,默認(rèn)情況下著色器無法讀取到這個(gè)數(shù)據(jù)。 需要我們啟用一下才可以讀取
            GLES20.glEnableVertexAttribArray(vCoord);
    
    
            //相當(dāng)于激活一個(gè)用來顯示圖片的畫框
            GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture);
            // 0: 圖層ID  GL_TEXTURE0
            // GL_TEXTURE1 , 1
            GLES20.glUniform1i(vTexture, 0);
    
            beforeDraw();
            //通知畫畫,
            GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
    
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
    
            return texture;
    }
    

    openGL ES離屏渲染 FBO(Frame Buffer Object)幀緩存對象

    public void createFrame(int width, int height) {
            releaseFrame();
            //創(chuàng)建FBO
            /**
             * 1、創(chuàng)建FBO + FBO中的紋理
             */
            frameBuffer = new int[1];
            frameTextures = new int[1];
            GLES20.glGenFramebuffers(1, frameBuffer, 0);
            OpenGLUtils.glGenTextures(frameTextures);
    
            /**
             * 2、fbo與紋理關(guān)聯(lián)
             */
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, frameTextures[0]);
            GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE,
                    null);
            //紋理關(guān)聯(lián) fbo
            GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frameBuffer[0]);  //綁定FBO
            GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D,
                    frameTextures[0],
                    0);
    
            /**
             * 3、解除綁定
             */
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
            GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
    
        }
    

EGL庫 管理窗口 將Surface和EGLSurface綁定

圖片.png

openGL是在GLThread子線程 同樣需要搭建一個(gè)EGL環(huán)境在子線程

1.創(chuàng)建Display獲取顯示窗口

EGLDisplay mEglDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
EGL14.eglinitialize(...);//初始化

2.配置屬性選項(xiàng)

EGL.eglChooseConfig(...)

3.創(chuàng)建EGL上下文

EGL14.eglCreateWindowSurface(...)

5.繪制

//先綁定當(dāng)前線程的顯示屏diplay
EGL14.eglMakeCurrent(EGLDisplay, EGLSurface, EGLSurface, EGLContext);
//EGLSurface是雙緩沖模式
EGLExt.eglPresentationTimeANDROID(EGLDisplay,EGLSurface,時(shí)間戳);
EGL14.eglSwapBuffers(EGLDisplay,EGLSurface);

實(shí)現(xiàn)功能一 、調(diào)整快慢幀

//只需要調(diào)整bufferInfo參數(shù)中的時(shí)間戳
Muxer.writeSampleData(track,encodeData,bufferInfo);
//改變時(shí)間的速率
bufferInfo.presentationTimeUs = bufferInfo.presentationTimeUs/speed;

實(shí)現(xiàn)功能二、識別臉部 使用Seetaface FaceLandmarker

圖像局部縮放 
圖片.png

實(shí)現(xiàn)功能三、圖像遮罩物

openGL圖像混合
GLES20.gleEnable(GLES20.GL_BLEND);
GLES20.GLBlendFunc(GLES20.GLONE,GLES20.GL_ONE_MINUS_SRC_ALPHA);
//GL_ONE采用源顏色的alpha值作為因子
//GL_ONE_MINUS_SRC_ALPHA表示用1.0減去源顏色的aplha作為因子
利用GLES20.glViewPort(x,y,width,heigh)或openGL中轉(zhuǎn)換世界坐標(biāo)系

GLUtils.textImage2D(...)將Bitmap圖片綁定openGL中

實(shí)現(xiàn)功能四、美顏

1.模糊效果(水平方向和垂直方向)設(shè)計(jì)11*11算子

2.高反差保留 邊緣化  高反差=原圖-模糊圖

3.保留邊緣細(xì)節(jié)不被模糊掉

4.磨皮調(diào)整

實(shí)現(xiàn)功能五、閃爍 以中心點(diǎn)(0.5,0.5)向四周擴(kuò)散

實(shí)現(xiàn)功能六、分配 以屏幕0.25~0.75繪制(大于0.5則減去0.25,否則加上0.25)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容