12.OpenGL ES

OpenGL ES

android中 GLSurfaceView 继承 SurfaceView

GLSurfaceView 中有 GLThread

setEGLContextClientVersion(2);//使用openGLES 2.0上下文
setRenderer(...);//设置渲染回调接口 该方法中实例化GLThread
 /**
 * 刷新方式:
 *     RENDERMODE_WHEN_DIRTY 手动刷新,調用requestRender();
 *     RENDERMODE_CONTINUOUSLY 自動刷新,大概16ms自動回調一次onDraw方法
 */
//注意必须在setRenderer 后面。
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);

openGL 渲染管线 顶点->图元装配->光栅化(像素化)

            着色器(顶点着色器和片元着色器)

Android Studio 集成GLSLSupport插件 编辑OpenGL着色器语言(GLSL)时关键字高亮智能提示

openGL着色语言

attribute 属性变量(只在顶点着色器使用)
uniforms 一致变量(片元着色器使用)
varying 易编变量(顶点着色器输出数据到片元着色器)
gl_Position 坐标(x,y,z,w)
samplerExternalOES  图片采样器
samplerExternalOES 相当于rgba 使用texture2D(...)
precision / mediump / float  精度定义

openGL的世界坐标和纹理坐标

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) {
        //创建OpenGL 纹理 ,把摄像头的数据与这个纹理关联
        textures = new int[1];  //当做能在opengl用的一个图片的ID
        mCameraTexure.attachToGLContext(textures[0]);
        // 当摄像头数据有更新回调 onFrameAvailable
        mCameraTexure.setOnFrameAvailableListener(this);//监听更新时手动调用requestRender()
        screenFilter = new ScreenFilter(cameraView.getContext());
    }
    

    创建和初始化着色器供, 这些过程一般分为7个步骤:

创建顶点着色器对象(glcreateShader);

 向顶点着色器对象中填充着色器程序的源代码(glshaderSource);

 编译顶点着色器(glcompileShander);

创建片元着色器对象(glcreateShader);

 向片元着色器对象中填充着色器程序的源代码(glshaderSource);

 编译片元着色器(glcompileShander);

创建程序对象(glcreateProgram);

 为程序对象分配着色器(glattachShader);

 连接程序对象(gllinkProgram);

 使用程序对象(gluseProgram)
//着色器程序准备
public static int loadProgram(String vSource, String fSource) {
    /**
     * 顶点着色器
     */
    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));
    }


    /**
     * 创建着色器程序
     */
    int program = GLES20.glCreateProgram();
    //绑定顶点和片元
    GLES20.glAttachShader(program, vShader);
    GLES20.glAttachShader(program, fShader);
    //链接着色器程序
    GLES20.glLinkProgram(program);


    //获得状态
    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设置宽高

  2. onDrawFrame

    @Override
    public void onDrawFrame(GL10 gl) {
        //todo 更新纹理
        mCameraTexure.updateTexImage();//拿到最新的图像数据
        mCameraTexure.getTransformMatrix(mtx);
        screenFilter.setTransformMatrix(mtx);
        screenFilter.onDraw(textures[0]);
    }
    
    public int onDraw(int texture, FilterChain filterChain) {
            FilterContext filterContext = filterChain.filterContext;
            //设置绘制区域
            GLES20.glViewport(0, 0, filterContext.width, filterContext.height);
    
    
            GLES20.glUseProgram(program);
    
            vertexBuffer.position(0);
            // 4、归一化 normalized  [-1,1] . 把[2,2]转换为[-1,1]
            GLES20.glVertexAttribPointer(vPosition, 2, GLES20.GL_FLOAT, false, 0, vertexBuffer);
            //CPU传数据到GPU,默认情况下着色器无法读取到这个数据。 需要我们启用一下才可以读取
            GLES20.glEnableVertexAttribArray(vPosition);
    
    
            textureBuffer.position(0);
            // 4、归一化 normalized  [-1,1] . 把[2,2]转换为[-1,1]
            GLES20.glVertexAttribPointer(vCoord, 2, GLES20.GL_FLOAT, false, 0, textureBuffer);
            //CPU传数据到GPU,默认情况下着色器无法读取到这个数据。 需要我们启用一下才可以读取
            GLES20.glEnableVertexAttribArray(vCoord);
    
    
            //相当于激活一个用来显示图片的画框
            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();
            //創建FBO
            /**
             * 1、创建FBO + FBO中的纹理
             */
            frameBuffer = new int[1];
            frameTextures = new int[1];
            GLES20.glGenFramebuffers(1, frameBuffer, 0);
            OpenGLUtils.glGenTextures(frameTextures);
    
            /**
             * 2、fbo与纹理关联
             */
            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);
            //纹理关联 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子线程 同样需要搭建一个EGL环境在子线程

1.创建Display获取显示窗口

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

2.配置属性选项

EGL.eglChooseConfig(...)

3.创建EGL上下文

EGL14.eglCreateWindowSurface(...)

5.绘制

//先绑定当前线程的显示屏diplay
EGL14.eglMakeCurrent(EGLDisplay, EGLSurface, EGLSurface, EGLContext);
//EGLSurface是双缓冲模式
EGLExt.eglPresentationTimeANDROID(EGLDisplay,EGLSurface,时间戳);
EGL14.eglSwapBuffers(EGLDisplay,EGLSurface);

实现功能一 、调整快慢帧

//只需要调整bufferInfo参数中的时间戳
Muxer.writeSampleData(track,encodeData,bufferInfo);
//改变时间的速率
bufferInfo.presentationTimeUs = bufferInfo.presentationTimeUs/speed;

实现功能二、识别脸部 使用Seetaface FaceLandmarker

图像局部缩放 
图片.png

实现功能三、图像遮罩物

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中转换世界坐标系

GLUtils.textImage2D(...)将Bitmap图片绑定openGL中

实现功能四、美颜

1.模糊效果(水平方向和垂直方向)设计11*11算子

2.高反差保留 边缘化  高反差=原图-模糊图

3.保留边缘细节不被模糊掉

4.磨皮调整

实现功能五、闪烁 以中心点(0.5,0.5)向四周扩散

实现功能六、分配 以屏幕0.25~0.75绘制(大于0.5则减去0.25,否则加上0.25)

你可能感兴趣的:(12.OpenGL ES)