Android平臺Camera實時濾鏡實現方法探討(五)--GLSurfaceView實現Camera預覽
阿新 • • 發佈:2019-02-13
前面有一篇探討了如何在片段著色器中將YUV資料轉換為RGB資料並顯示,但採用samplerExternalOES將SurfaceTexture作為OpenGL外部紋理,需要使用GL_TEXTURE_EXTERNAL_OES作為紋理模板,通過SetPreviewTexture將Camera資料影象輸出到SurfaceTexture,呼叫updateTexImage()時將對應紋理更新為最新的一幀,然後通知OpenGL繪製對應紋理。
1.建立紋理ID
2.根據紋理id建立SurfaceTextureint[] texture = new int[1]; GLES20.glGenTextures(1, texture, 0); GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, texture[0]); GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_LINEAR); GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE); GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE); return texture[0];
3.更改ShadermSurfaceTexture = new SurfaceTexture(textureId); mSurfaceTexture.setOnFrameAvailableListener(listener); private OnFrameAvailableListener listener = new OnFrameAvailableListener() { @Override public void onFrameAvailable(SurfaceTexture surfaceTexture) { // TODO Auto-generated method stub mGlSurfaceView.requestRender(); } };
頂點著色器與之前相比多了個textureTransform,用於接收SurfaceTexture變換矩陣,如果不需要也可以不蓋被vertext shader。
片段著色器需要增加#extension GL_OES_EGL_image_external : require,因為第一步的紋理都繫結到GL_TEXTURE_EXTERNAL_OES
對應取樣方式由Samlpe2D更改成samplerExternalOES。
public static final String NO_FILTER_VERTEX_SHADER = "" + "attribute vec4 position;\n" + " attribute vec4 inputTextureCoordinate;\n" + " \n" + "uniform mat4 textureTransform;\n" + "varying vec2 textureCoordinate;\n" + " \n" + " void main()\n" + "{\n" + "textureCoordinate = (textureTransform * inputTextureCoordinate).xy;\n" + "gl_Position = position;\n" + "}"; public static final String NO_FILTER_FRAGMENT_SHADER = "" + "#extension GL_OES_EGL_image_external : require\n"+ "precision mediump float;" + "varying vec2 textureCoordinate;\n" + "uniform samplerExternalOES inputImageTexture;\n" + " \n" + "void main() {" + " gl_FragColor = texture2D( inputImageTexture, textureCoordinate );\n" + "}";
4.繪製
與之前採用glTexImage2D繫結2D影象紋理不同,這裡通過GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureid);繫結外部紋理即可。
如果使用了SurfaceTexture變換矩陣,可採用glUniformMatrix4fv傳遞給Shader
採用片段著色器方案的時間消耗主要在資料轉移中,本方法的格式相關工作交給EGLImage處理,用到了Lock ANativeWindow。具體優劣尚未探討,如有經驗人士希望指點迷津。