Android OpenGLES滤镜开发之贴纸效果
前言
上一篇中寫到了如何實現放大眼睛的效果,這一篇實現貼紙效果,就像那個faceu相機,b612相機,還有抖音都會有的這種貼紙效果。
思路
1、貼紙肯定也是需要定位到人臉的
2、找到貼紙需要放置的位置
3、將貼紙紋理和人本身紋理進行融合
實現
人臉定位啥的,我就不說了,不清楚的可以去前面的文章看看,主要來看看貼紙是如何貼上去的
1. 創建貼紙的紋理
//OpenGL 紋理mTextureId = new int[1];//OpenGLUtils是個OpenGL的工具類,具體的前面也有寫OpenGLUtils.glGenTextures(mTextureId);GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,mTextureId[0]);//將bitmap與紋理的id綁定起來GLUtils.texImage2D(GLES20.GL_TEXTURE_2D,0,mBitmap,0);//解綁GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,0);2. 畫貼紙
在畫貼紙之前,是已經將之前攝像頭那些紋理已經畫上去過了,然后再來畫貼紙。
//開啟混合模式:將多張圖片進行混合(貼圖)GLES20.glEnable(GLES20.GL_BLEND);//設置貼圖模式//1.src 源圖因子 要畫的是源(耳朵)//2.dst 已經畫好的目標,也就是我們要往哪兒畫,也就是其他filter的圖像//GLES20.GL_ONE 原本是什么樣子,就畫成什么樣子//GLES20.GL_ONE_MINUS_SRC_ALPHA,表示用1.0減去源顏色alpha的值來作為因子 GLES20.glBlendFunc(GLES20.GL_ONE,GLES20.GL_ONE_MINUS_SRC_ALPHA);因為在OpenGL中如果不開啟混合模式,就會把之前的紋理覆蓋掉,這里就不會顯示上一個紋理了。
什么是混合?混合就是把某一個像素點的位置原來的顏色與將要畫上去的顏色,以某種方式混合在一起,從而達到某種特殊的效果。我們這里就需要將貼紙的紋理和人臉的紋理進行一個混合。
glBlendFunc的參數設置有多種模式,第一個參數表示的是源圖因子,也就是我們要畫上去的貼紙,第二個參數是目標因子,也就是我們要把貼紙畫到哪兒去。這兩個參數有多種值:
GL_ZERO:表示使用0.0作為因子,實際上相當于不使用這種顏色參與混合運算。
GL_ONE: 表示使用1.0作為因子,實際上相當于完全的使用了這種顏色參與混合運算。
GL_SRC_ALPHA:表示使用源顏色的alpha值來作為因子。
GL_DST_ALPHA:表示使用目標顏色的alpha值來作為因子。
GL_ONE_MINUS_SRC_ALPHA:表示用1.0減去源顏色的alpha值來作為因子。
GL_ONE_MINUS_DST_ALPHA:表示用1.0減去目標顏色的alpha值來作為因子。
這個源圖因子使用的是完全使用,也就是貼紙是完全展示出來的,目標因子是用1.0 - 貼紙的alpha值來作為因子的。
下面就是計算出貼紙所要顯示的位置,然后將坐標信息傳遞給著色器
//畫耳朵,是需要往人臉上畫,不是全屏畫float x = mFace.landmarks[0];float y =mFace.landmarks[1];//轉換為要畫到屏幕上的寬、高x = x / mFace.imgWidth * mOutputWidth;y = y/ mFace.imgHeight * mOutputHeight;//貼紙需要顯示的位置//1.需要顯示到屏幕上的x坐標,2.y坐標//3.需要顯示的貼紙的寬 4.高,這兩個參數需要不斷的調試,然后獲得比較合適的GLES20.glViewport((int)x, (int)y-mBitmap.getHeight()/2,(int) ((float)mFace.width /mFace.imgWidth * mOutputWidth),mBitmap.getHeight());LES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER,mFrameBuffers[0]);GLES20.glUseProgram(mGLProgramId);//傳遞坐標mGLVertexBuffer.position(0);GLES20.glVertexAttribPointer(vPosition, 2, GLES20.GL_FLOAT, false, 0, mGLVertexBuffer);GLES20.glEnableVertexAttribArray(vPosition);mGLTextureBuffer.position(0);GLES20.glVertexAttribPointer(vCoord, 2, GLES20.GL_FLOAT, false, 0, mGLTextureBuffer);GLES20.glEnableVertexAttribArray(vCoord);//激活紋理,傳遞紋理給著色器GLES20.glActiveTexture(GLES20.GL_TEXTURE0);GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,mTextureId[0]);GLES20.glUniform1i(vTexture,0);//畫畫GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP,0,4);// 解綁紋理GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,0);//解綁FRAMEBUFFERGLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER,0);//最后使用完畢以后需要關閉這個融合GLES20.glDisable(GLES20.GL_BLEND);很多都在代碼里進行了注釋,應該都可以看得懂,下面就看一下效果圖吧~~
效果圖
就差不多是這樣的效果,是因為我手機問題所有才模糊不清楚的,前置攝像頭完成沒有問題的。
總結
以上是生活随笔為你收集整理的Android OpenGLES滤镜开发之贴纸效果的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【uniapp】使用扫码插件,解决uni
- 下一篇: 梅科尔工作室-梁嘉莹-鸿蒙笔记1