Android通过openGL实现视频贴纸功能

GLSL代码

1.vertex代码,文件vertex_filter_stricker.glsl

attribute vec2 inputTextureCoordinate; //纹理坐标attribute vec4 position;// 顶点坐标varying   vec2 textureCoordinate;//纹理坐标点变换后输出void main() {    gl_Position = position;    textureCoordinate = inputTextureCoordinate;}

2.fragment代码,文件fragment_filter_stricker.glsl

//设置精度precision highp float;varying highp vec2 textureCoordinate;uniform sampler2D videoTexture;uniform sampler2D uImageTexture;uniform vec4 imageRect;void main(){    lowp vec4 c1 = texture2D(videoTexture, textureCoordinate);    lowp vec2 vCamTextureCoord2 = vec2(textureCoordinate.x, 1.0-textureCoordinate.y);    if (vCamTextureCoord2.x>imageRect.r && vCamTextureCoord2.x<imageRect.b && vCamTextureCoord2.y>imageRect.g && vCamTextureCoord2.y<imageRect.a)    {        vec2 imagexy = vec2((vCamTextureCoord2.x-imageRect.r)/(imageRect.b-imageRect.r), (vCamTextureCoord2.y-imageRect.g)/(imageRect.a-imageRect.g));        lowp vec4 c2 = texture2D(uImageTexture, imagexy);        lowp vec4 outputColor = c2+c1*c1.a*(1.0-c2.a);        outputColor.a = 1.0;        gl_FragColor = outputColor;    } else {        gl_FragColor = c1;    }}

Java代码

package com.dong.opencamera.core.filter.impl;import android.content.Context;import android.graphics.Bitmap;import android.graphics.RectF;import android.opengl.GLES20;import com.dong.opencamera.core.filter.IVideoFilter;import com.dong.opencamera.utils.GLHelper;import java.nio.FloatBuffer;import java.nio.ShortBuffer;/** * @author : liaojidong * @date : 2020-01-13 15:00 * @desc : */public class StickerFilter implements IVideoFilter {    // number of coordinates per vertex in this array    private static final int COORDS_PER_VERTEX = 3;    private static final short[] ORDERS = {            0, 1, 2, // 左下角三角形            2, 3, 0  // 右上角三角形    };    private Context mContext;    private volatile boolean isInit = false;    private Bitmap mStickerBitmap;    private int mProgram;    private int glImageTextureLoc;    private int glImageRectLoc;    private int videoTextureLoc;    private int uPosLocation;    private int aTexLocation;    protected int imageTexture;    private RectF imageRectF = new RectF();    private int width;    private int height;    public StickerFilter(Context context,                         Bitmap stickerBitmap) {        this.mStickerBitmap = stickerBitmap;        this.mContext = context;    }    @Override    public void onFilterChanged(int surfaceWidth, int surfaceHeight) {        this.width = surfaceWidth;        this.height = surfaceHeight;    }    private void init() {        if (isInit) return;        mProgram = GLHelper.createProgram(mContext,                "vertex_filter_stricker.glsl",                "fragment_filter_stricker.glsl");        // 将程序添加到OpenGL ES环境        GLES20.glUseProgram(mProgram);        // 获取顶点着色器的位置的句柄        uPosLocation = GLES20.glGetAttribLocation(mProgram, "position");        aTexLocation = GLES20.glGetAttribLocation(mProgram, "inputTextureCoordinate");        videoTextureLoc = GLES20.glGetUniformLocation(mProgram, "videoTexture");        glImageRectLoc = GLES20.glGetUniformLocation(mProgram, "imageRect");        glImageTextureLoc = GLES20.glGetUniformLocation(mProgram, "uImageTexture");        imageTexture = GLHelper.loadTexture(mContext, mStickerBitmap);        isInit = true;    }    public void setStickerLoc(int x, int y) {        imageRectF.left = (float) ((x * 1.0) / (width * 1.0));        imageRectF.right = (float) (imageRectF.left + ((mStickerBitmap.getWidth() * 1.0) / (width * 1.0)));        imageRectF.top = (float) ((y * 1.0) / (height * 1.0));        imageRectF.bottom = (float) (imageRectF.top + ((mStickerBitmap.getHeight() * 1.0) / (height * 1.0)));    }    @Override    public void onDraw(int inputTexture,                       int targetFrameBuffer,                       FloatBuffer vertexPosBuffer,                       FloatBuffer texturePosBuffer,                       ShortBuffer order) {        init();        setStickerLoc(100, 100);        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, targetFrameBuffer);        GLES20.glUseProgram(mProgram);        // Set the active texture unit to texture unit 0.        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);        // Bind the texture to this unit 0.        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, inputTexture);        // Tell the texture uniform sampler to use this texture in the shader by        // telling it to read from texture unit 0.        GLES20.glUniform1i(videoTextureLoc, 0);        // Set the active texture unit to texture unit 1.        GLES20.glActiveTexture(GLES20.GL_TEXTURE1);        // Bind the texture to this unit 1.        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, imageTexture);        // Tell the texture uniform sampler to use this texture in the shader by        // telling it to read from texture unit 1.        GLES20.glUniform1i(glImageTextureLoc, 1);        // 将数据传递到着色器中        GLES20.glVertexAttribPointer(uPosLocation, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, 0, vertexPosBuffer);        GLES20.glVertexAttribPointer(aTexLocation, 2, GLES20.GL_FLOAT, false, 0, texturePosBuffer);        GLES20.glUniform4f(glImageRectLoc, imageRectF.left, imageRectF.top, imageRectF.right, imageRectF.bottom);        // 启用顶点位置的句柄        GLES20.glEnableVertexAttribArray(uPosLocation);        GLES20.glEnableVertexAttribArray(aTexLocation);        GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);        GLES20.glDrawElements(GLES20.GL_TRIANGLES, ORDERS.length, GLES20.GL_UNSIGNED_SHORT, order);        GLES20.glFinish();        GLES20.glDisableVertexAttribArray(uPosLocation);        GLES20.glDisableVertexAttribArray(aTexLocation);        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);        GLES20.glUseProgram(0);        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);    }}

效果如下图所示:

总结

贴纸的原理本质就是在绘制的时候判断当前位置是应该绘制视频还是应该绘制贴纸。

更多相关文章

  1. Android(安卓)中OpenGL的使用
  2. Android(安卓)API开发之OpenGL开发之Android(安卓)OpenGL之使用G
  3. Android(安卓)音视频开发(五) : OpenGL ES API,了解 OpenGL 开发
  4. [置顶] 一步一步学android OpenGL ES2.0编程(2)
  5. Android(安卓)OpenGL例子学习
  6. OpenGL ES for Android(安卓)绘制线
  7. openGL 简单demo
  8. PHP算法练习八:判断给定的三个数是否能构成直角三角形
  9. 关键路径(C语言)

随机推荐

  1. 创建android phonegap项目
  2. Android(安卓)自定义RecyclerView 实现真
  3. Android(安卓)Inflate方法
  4. API Demos 2.2 研读笔记(10)——Redirectio
  5. 详解Android(安卓)Handler的使用
  6. Android软键盘将标题栏顶上去的解决办法
  7. android Launcher之获取安装的app列表的
  8. Android(安卓)Post请求SQL数据库
  9. Android滑动冲突解决方式(下拉刷新上拉加
  10. Android(安卓)onTouch、OnLongClick、onC