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 ES API,了解 OpenGL 开发的基本
  2. c语言如何求三角形的面积
  3. 手把手教你在C语言中如何打印倒三角形
  4. 图解两数之和的变形题之「有效三角形的个数」
  5. 从“顶点小说”下载完整小说——python爬虫
  6. Python能不能方便的画三角形?
  7. python输出斐波那契数列三角形
  8. java三角形的画法

随机推荐

  1. 智能电视使用什么操作系统?
  2. android进程创建分析
  3. delphi xe 之路(28)Android(安卓)SDK API
  4. 命令行下Android应用开发
  5. android studio使用说明
  6. Android(安卓)WebView与JS交互全面详解
  7. Android与服务器端数据交互(1)
  8. 帮你分析android与java的关系
  9. Android应用层源码阅读笔记--Application
  10. 在Android中建立Android(安卓)project没