XML文件
<?xml version="1.0" encoding="utf-8"?>
< RelativeLayout xmlns: android= " http://schemas.android.com/apk/res/android" android: layout_width= " match_parent" android: layout_height= " match_parent" > < com.example.myapplication.MyGLSurfaceViewandroid: id= " @+id/gl_surface_view" android: layout_width= " match_parent" android: layout_height= " match_parent" /> < ImageViewandroid: id= " @+id/image_view_1" android: layout_width= " 180dp" android: layout_height= " 180dp" android: layout_alignParentStart= " true" android: layout_alignParentTop= " true" android: layout_margin= " 10dp" android: background= " #33000000" /> < ImageViewandroid: id= " @+id/image_view_2" android: layout_width= " 180dp" android: layout_height= " 180dp" android: layout_alignParentEnd= " true" android: layout_alignParentTop= " true" android: layout_margin= " 10dp" android: background= " #33000000" /> < ImageViewandroid: id= " @+id/image_view_3" android: layout_width= " 180dp" android: layout_height= " 180dp" android: layout_alignParentStart= " true" android: layout_alignParentBottom= " true" android: layout_margin= " 10dp" android: background= " #33000000" /> < ImageViewandroid: id= " @+id/image_view_4" android: layout_width= " 180dp" android: layout_height= " 180dp" android: layout_alignParentEnd= " true" android: layout_alignParentBottom= " true" android: layout_margin= " 10dp" android: background= " #33000000" /> < Buttonandroid: id= " @+id/capture_button" android: layout_width= " wrap_content" android: layout_height= " wrap_content" android: layout_alignParentBottom= " true" android: layout_centerHorizontal= " true" android: layout_marginBottom= " 10dp" android: text= " 滤镜渲染" android: padding= " 12dp" /> </ RelativeLayout>
Activity
代码
class MainActivity : AppCompatActivity ( ) { private lateinit var glSurfaceView: MyGLSurfaceViewprivate lateinit var imageView1: ImageViewprivate lateinit var imageView2: ImageViewprivate lateinit var imageView3: ImageViewprivate lateinit var imageView4: ImageViewprivate lateinit var captureButton: Button@SuppressLint ( "MissingInflatedId" ) override fun onCreate ( savedInstanceState: Bundle? ) { super . onCreate ( savedInstanceState) setContentView ( R. layout. activity_main) glSurfaceView = findViewById ( R. id. gl_surface_view) imageView1 = findViewById ( R. id. image_view_1) imageView2 = findViewById ( R. id. image_view_2) imageView3 = findViewById ( R. id. image_view_3) imageView4 = findViewById ( R. id. image_view_4) captureButton = findViewById ( R. id. capture_button) captureButton. setOnTouchListener ( object : View. OnTouchListener { override fun onTouch ( v: View? , event: MotionEvent? ) : Boolean { when ( event? . action) { MotionEvent. ACTION_DOWN -> { glSurfaceView? . getDrawData ( ) ? . getEdgeFilterBitmap ( ) ? . let { imageView1. setImageBitmap ( it) } glSurfaceView? . getDrawData ( ) ? . getPixelFilterBitmap ( ) ? . let { imageView2. setImageBitmap ( it) } glSurfaceView? . getDrawData ( ) ? . getColorFilterBitmap ( ) ? . let { imageView3. setImageBitmap ( it) } glSurfaceView? . getDrawData ( ) ? . getOriginBitmap ( ) ? . let { imageView4. setImageBitmap ( it) } } MotionEvent. ACTION_UP -> { imageView1. setImageBitmap ( null ) imageView2. setImageBitmap ( null ) imageView3. setImageBitmap ( null ) imageView4. setImageBitmap ( null ) } } return true } } ) }
}
自定义GLSurfaceView
代码
class MyGLSurfaceView ( context: Context, attrs: AttributeSet) : GLSurfaceView ( context, attrs) { private var mRenderer = MyGLRenderer ( context) init { setEGLContextClientVersion ( 3 ) setRenderer ( mRenderer) renderMode = RENDERMODE_WHEN_DIRTY} fun getDrawData ( ) : DrawData? { return mRenderer? . getDrawData ( ) }
}
自定义GLSurfaceView.Renderer
代码
class MyGLRenderer ( private val mContext: Context) : GLSurfaceView. Renderer { private var mDrawData: DrawData? = null override fun onSurfaceCreated ( gl: GL10? , config: EGLConfig? ) { GLES30. glClearColor ( 0.0f , 0.5f , 0.5f , 1.0f ) mDrawData = DrawData ( ) . apply { initTexture0 ( mContext, R. drawable. picture) initShader ( ) initVertexBuffer ( ) initFrameBuffer ( ) initEdgeFilterShader ( ) initEdgeFrameBuffer ( ) initPixelFilterShader ( ) initPixelFrameBuffer ( ) initColorFilterShader ( ) initColorFrameBuffer ( ) } } override fun onSurfaceChanged ( gl: GL10? , width: Int, height: Int) { GLES30. glViewport ( 0 , 0 , width, height) mDrawData? . computeMVPMatrix ( width, height) } override fun onDrawFrame ( gl: GL10? ) { GLES30. glClear ( GLES30. GL_COLOR_BUFFER_BIT) mDrawData? . drawOriginFrameBuffer ( ) mDrawData? . drawPixelFilterBitmap ( ) mDrawData? . drawColorFilterBitmap ( ) mDrawData? . drawEdgeFilterBitmap ( ) mDrawData? . drawGLSurfaceView ( ) } fun getDrawData ( ) : DrawData? { return mDrawData}
}
GLSurfaceView.Renderer
需要的绘制数据
class DrawData { private var NO_OFFSET = 0 private val VERTEX_POS_DATA_SIZE = 3 private val TEXTURE_POS_DATA_SIZE = 2 private var mProgram: Int = - 1 private var mEdgeProgram : Int = - 1 private var mPixelProgram : Int = - 1 private var mColorProgram : Int = - 1 private var mFBO = IntArray ( 1 ) private var mEdgeFBO = IntArray ( 1 ) private var mPixelFBO = IntArray ( 1 ) private var mColorFBO = IntArray ( 1 ) private var mVAO = IntArray ( 1 ) private var mVBO = IntArray ( 2 ) private var mIBO = IntArray ( 1 ) private var mTextureID = IntArray ( 1 ) private var mFBOTextureID = IntArray ( 1 ) private var mEdgeFBOTextureID = IntArray ( 1 ) private var mPixelFBOTextureID = IntArray ( 1 ) private var mColorFBOTextureID = IntArray ( 1 ) private var mMVPMatrix = FloatArray ( 16 ) private val mProjectionMatrix = FloatArray ( 16 ) private val mViewMatrix = FloatArray ( 16 ) private var mViewPortRatio = 1f private var mFrameBufferWidth = 0 private var mFrameBufferHeight = 0 private val mFrameBufferMVPMatrix = FloatArray ( 16 ) val vertex = floatArrayOf ( - 1.0f , 1.0f , 0.0f , - 1.0f , - 1.0f , 0.0f , 1.0f , 1.0f , 0.0f , 1.0f , - 1.0f , 0.0f , ) val vertexBuffer = ByteBuffer. allocateDirect ( vertex. size * 4 ) . order ( ByteOrder. nativeOrder ( ) ) . asFloatBuffer ( ) . put ( vertex) . position ( NO_OFFSET) val textureCoords = floatArrayOf ( 0.0f , 1.0f , 0.0f , 0.0f , 1.0f , 1.0f , 1.0f , 0.0f , ) val textureBuffer = ByteBuffer. allocateDirect ( textureCoords. size * 4 ) . order ( ByteOrder. nativeOrder ( ) ) . asFloatBuffer ( ) . put ( textureCoords) . position ( NO_OFFSET) val index = shortArrayOf ( 0 , 1 , 2 , 1 , 3 , 2 , ) val indexBuffer = ByteBuffer. allocateDirect ( index. size * 2 ) . order ( ByteOrder. nativeOrder ( ) ) . asShortBuffer ( ) . put ( index) . position ( NO_OFFSET) private var mOriginBitmap : Bitmap ? = null private var mEdgeFilterBitmap : Bitmap ? = null private var mPixelFilterBitmap : Bitmap ? = null private var mColorFilterBitmap : Bitmap ? = null fun initShader ( ) { val vertexShaderCode = "" "#version 300 esuniform mat4 uMVPMatrix; in vec4 aPosition; in vec2 aTexCoord; out vec2 vTexCoord; void main ( ) { gl_Position = uMVPMatrix * aPosition; vTexCoord = aTexCoord; } """.trimIndent()val fragmentShaderCode = """ #version 300 esprecision mediump float; uniform sampler2D uTexture_0; in vec2 vTexCoord; out vec4 fragColor; void main ( ) { fragColor = texture ( uTexture_0, vTexCoord) ; } "" ". trimIndent ( ) val vertexShader = LoadShaderUtil. loadShader ( GLES30. GL_VERTEX_SHADER, vertexShaderCode) val fragmentShader = LoadShaderUtil. loadShader ( GLES30. GL_FRAGMENT_SHADER, fragmentShaderCode) mProgram = GLES30. glCreateProgram ( ) GLES30. glAttachShader ( mProgram, vertexShader) GLES30. glAttachShader ( mProgram, fragmentShader) GLES30. glLinkProgram ( mProgram) GLES30. glUseProgram ( mProgram) GLES30. glDeleteShader ( vertexShader) GLES30. glDeleteShader ( fragmentShader) } fun initVertexBuffer ( ) { GLES30. glGenVertexArrays ( mVAO. size, mVAO, NO_OFFSET) GLES30. glBindVertexArray ( mVAO[ 0 ] ) GLES30. glGenBuffers ( mVBO. size, mVBO, NO_OFFSET) GLES30. glBindBuffer ( GLES30. GL_ARRAY_BUFFER, mVBO[ 0 ] ) GLES30. glBufferData ( GLES30. GL_ARRAY_BUFFER, vertex. size * 4 , vertexBuffer, GLES30. GL_STATIC_DRAW) val positionHandle = GLES30. glGetAttribLocation ( mProgram, "aPosition" ) GLES30. glEnableVertexAttribArray ( positionHandle) GLES30. glVertexAttribPointer ( positionHandle, VERTEX_POS_DATA_SIZE, GLES30. GL_FLOAT, false , 0 , NO_OFFSET) GLES30. glBindBuffer ( GLES30. GL_ARRAY_BUFFER, 0 ) GLES30. glBindBuffer ( GLES30. GL_ARRAY_BUFFER, mVBO[ 1 ] ) GLES30. glBufferData ( GLES30. GL_ARRAY_BUFFER, textureCoords. size * 4 , textureBuffer, GLES30. GL_STATIC_DRAW) val textureHandle = GLES30. glGetAttribLocation ( mProgram, "aTexCoord" ) GLES30. glEnableVertexAttribArray ( textureHandle) GLES30. glVertexAttribPointer ( textureHandle, TEXTURE_POS_DATA_SIZE, GLES30. GL_FLOAT, false , 0 , NO_OFFSET) GLES30. glBindBuffer ( GLES30. GL_ARRAY_BUFFER, 0 ) GLES30. glGenBuffers ( mIBO. size, mIBO, NO_OFFSET) GLES30. glBindBuffer ( GLES30. GL_ELEMENT_ARRAY_BUFFER, mIBO[ 0 ] ) GLES30. glBufferData ( GLES30. GL_ELEMENT_ARRAY_BUFFER, index. size * 2 , indexBuffer, GLES30. GL_STATIC_DRAW) GLES30. glBindVertexArray ( 0 ) GLES30. glBindBuffer ( GLES30. GL_ELEMENT_ARRAY_BUFFER, 0 ) } fun initFrameBuffer ( ) { GLES30. glGenFramebuffers ( mFBO. size, mFBO, NO_OFFSET) GLES30. glBindFramebuffer ( GLES30. GL_FRAMEBUFFER, mFBO[ 0 ] ) GLES30. glGenTextures ( mFBOTextureID. size, mFBOTextureID, NO_OFFSET) GLES30. glBindTexture ( GLES30. GL_TEXTURE_2D, mFBOTextureID[ 0 ] ) GLES30. glTexParameteri ( GLES30. GL_TEXTURE_2D, GLES30. GL_TEXTURE_MIN_FILTER, GLES30. GL_LINEAR) GLES30. glTexParameteri ( GLES30. GL_TEXTURE_2D, GLES30. GL_TEXTURE_MAG_FILTER, GLES30. GL_LINEAR) GLES30. glTexParameteri ( GLES30. GL_TEXTURE_2D, GLES30. GL_TEXTURE_WRAP_S, GLES30. GL_CLAMP_TO_EDGE) GLES30. glTexParameteri ( GLES30. GL_TEXTURE_2D, GLES30. GL_TEXTURE_WRAP_T, GLES30. GL_CLAMP_TO_EDGE) GLES30. glTexImage2D ( GLES30. GL_TEXTURE_2D, NO_OFFSET, GLES30. GL_RGBA, mFrameBufferWidth, mFrameBufferHeight, NO_OFFSET, GLES30. GL_RGBA, GLES30. GL_UNSIGNED_BYTE, null ) GLES30. glFramebufferTexture2D ( GLES30. GL_FRAMEBUFFER, GLES30. GL_COLOR_ATTACHMENT0, GLES30. GL_TEXTURE_2D, mFBOTextureID[ 0 ] , 0 ) if ( GLES30. glCheckFramebufferStatus ( GLES30. GL_FRAMEBUFFER) != GLES30. GL_FRAMEBUFFER_COMPLETE) { Log. e ( "yang" , "initFrameBuffer: FBO初始化失败" ) } GLES30. glBindTexture ( GLES30. GL_TEXTURE_2D, 0 ) GLES30. glBindFramebuffer ( GLES30. GL_FRAMEBUFFER, 0 ) } fun drawOriginFrameBuffer ( ) { val previousProgram = IntArray ( 1 ) val previousFrameBuffer = IntArray ( 1 ) val viewPort = IntArray ( 4 ) try { GLES30. glGetIntegerv ( GLES30. GL_VIEWPORT, viewPort, NO_OFFSET) GLES30. glGetIntegerv ( GLES30. GL_CURRENT_PROGRAM, previousProgram, 0 ) GLES30. glGetIntegerv ( GLES30. GL_FRAMEBUFFER_BINDING, previousFrameBuffer, 0 ) GLES30. glViewport ( 0 , 0 , mFrameBufferWidth, mFrameBufferHeight) enableTexture0 ( mProgram, mTextureID[ 0 ] ) GLES30. glBindFramebuffer ( GLES30. GL_FRAMEBUFFER, mFBO[ 0 ] ) GLES30. glClear ( GLES30. GL_COLOR_BUFFER_BIT) computeFrameBufferMVPMatrix ( ) drawSomething ( mProgram, mFrameBufferMVPMatrix) mOriginBitmap = savePixelBufferBitmap ( ) GLES30. glBindFramebuffer ( GLES30. GL_FRAMEBUFFER, 0 ) disableTexture0 ( ) } finally { GLES30. glViewport ( viewPort[ 0 ] , viewPort[ 1 ] , viewPort[ 2 ] , viewPort[ 3 ] ) GLES30. glBindFramebuffer ( GLES30. GL_FRAMEBUFFER, previousFrameBuffer[ 0 ] ) GLES30. glUseProgram ( previousProgram[ 0 ] ) } } fun drawGLSurfaceView ( ) { val previousProgram = IntArray ( 1 ) val previousFrameBuffer = IntArray ( 1 ) try { GLES30. glGetIntegerv ( GLES30. GL_CURRENT_PROGRAM, previousProgram, 0 ) GLES30. glGetIntegerv ( GLES30. GL_FRAMEBUFFER_BINDING, previousFrameBuffer, 0 ) enableTexture0 ( mProgram, mEdgeFBOTextureID[ 0 ] ) drawSomething ( mProgram, mMVPMatrix) disableTexture0 ( ) } finally { GLES30. glBindFramebuffer ( GLES30. GL_FRAMEBUFFER, previousFrameBuffer[ 0 ] ) GLES30. glUseProgram ( previousProgram[ 0 ] ) } } fun drawEdgeFilterBitmap ( ) { takeIf { mEdgeFilterBitmap == null } ? . let { val previousProgram = IntArray ( 1 ) val previousFrameBuffer = IntArray ( 1 ) val viewPort = IntArray ( 4 ) try { GLES30. glGetIntegerv ( GLES30. GL_VIEWPORT, viewPort, NO_OFFSET) GLES30. glGetIntegerv ( GLES30. GL_CURRENT_PROGRAM, previousProgram, 0 ) GLES30. glGetIntegerv ( GLES30. GL_FRAMEBUFFER_BINDING, previousFrameBuffer, 0 ) GLES30. glViewport ( 0 , 0 , mFrameBufferWidth, mFrameBufferHeight) GLES30. glUseProgram ( mEdgeProgram) GLES30. glBindFramebuffer ( GLES30. GL_FRAMEBUFFER, mEdgeFBO[ 0 ] ) GLES30. glClear ( GLES30. GL_COLOR_BUFFER_BIT) enableTexture2 ( mEdgeProgram, mColorFBOTextureID[ 0 ] ) val textureSizeHandle = GLES30. glGetUniformLocation ( mEdgeProgram, "uTextureSize" ) GLES30. glUniform2f ( textureSizeHandle, mFrameBufferWidth. toFloat ( ) , mFrameBufferHeight. toFloat ( ) ) drawSomething ( mEdgeProgram, mFrameBufferMVPMatrix) mEdgeFilterBitmap = savePixelBufferBitmap ( ) disableTexture2 ( ) GLES30. glBindFramebuffer ( GLES30. GL_FRAMEBUFFER, 0 ) } finally { GLES30. glViewport ( viewPort[ 0 ] , viewPort[ 1 ] , viewPort[ 2 ] , viewPort[ 3 ] ) GLES30. glBindFramebuffer ( GLES30. GL_FRAMEBUFFER, previousFrameBuffer[ 0 ] ) GLES30. glUseProgram ( previousProgram[ 0 ] ) } } } fun drawPixelFilterBitmap ( ) { takeIf { mPixelFilterBitmap == null } ? . let { val previousProgram = IntArray ( 1 ) val previousFrameBuffer = IntArray ( 1 ) val viewPort = IntArray ( 4 ) try { GLES30. glGetIntegerv ( GLES30. GL_VIEWPORT, viewPort, NO_OFFSET) GLES30. glGetIntegerv ( GLES30. GL_CURRENT_PROGRAM, previousProgram, 0 ) GLES30. glGetIntegerv ( GLES30. GL_FRAMEBUFFER_BINDING, previousFrameBuffer, 0 ) GLES30. glViewport ( 0 , 0 , mFrameBufferWidth, mFrameBufferHeight) GLES30. glUseProgram ( mPixelProgram) GLES30. glBindFramebuffer ( GLES30. GL_FRAMEBUFFER, mPixelFBO[ 0 ] ) GLES30. glClear ( GLES30. GL_COLOR_BUFFER_BIT) enableTexture3 ( mPixelProgram, mFBOTextureID[ 0 ] ) val textureSizeHandle = GLES30. glGetUniformLocation ( mPixelProgram, "uTextureSize" ) GLES30. glUniform2f ( textureSizeHandle, mFrameBufferWidth. toFloat ( ) , mFrameBufferWidth. toFloat ( ) ) val pixelSizeHandle = GLES30. glGetUniformLocation ( mPixelProgram, "uPixelSize" ) GLES30. glUniform1f ( pixelSizeHandle, 15.0f ) drawSomething ( mPixelProgram, mFrameBufferMVPMatrix) mPixelFilterBitmap = savePixelBufferBitmap ( ) disableTexture3 ( ) GLES30. glBindFramebuffer ( GLES30. GL_FRAMEBUFFER, 0 ) } finally { GLES30. glViewport ( viewPort[ 0 ] , viewPort[ 1 ] , viewPort[ 2 ] , viewPort[ 3 ] ) GLES30. glBindFramebuffer ( GLES30. GL_FRAMEBUFFER, previousFrameBuffer[ 0 ] ) GLES30. glUseProgram ( previousProgram[ 0 ] ) } } } fun drawColorFilterBitmap ( ) { takeIf { mColorFilterBitmap == null } ? . let { val previousProgram = IntArray ( 1 ) val previousFrameBuffer = IntArray ( 1 ) val viewPort = IntArray ( 4 ) try { GLES30. glGetIntegerv ( GLES30. GL_VIEWPORT, viewPort, NO_OFFSET) GLES30. glViewport ( 0 , 0 , mFrameBufferWidth, mFrameBufferHeight) GLES30. glGetIntegerv ( GLES30. GL_CURRENT_PROGRAM, previousProgram, 0 ) GLES30. glGetIntegerv ( GLES30. GL_FRAMEBUFFER_BINDING, previousFrameBuffer, 0 ) GLES30. glUseProgram ( mColorProgram) GLES30. glBindFramebuffer ( GLES30. GL_FRAMEBUFFER, mColorFBO[ 0 ] ) GLES30. glClear ( GLES30. GL_COLOR_BUFFER_BIT) enableTexture4 ( mColorProgram, mPixelFBOTextureID[ 0 ] ) val timeHandle = GLES30. glGetUniformLocation ( mColorProgram, "uTime" ) if ( timeHandle != - 1 ) { GLES30. glUniform1f ( timeHandle, ( System. currentTimeMillis ( ) % 10000 ) / 10000.0f ) } val twistIntensityHandle = GLES30. glGetUniformLocation ( mColorProgram, "uTwistIntensity" ) GLES30. glUniform1f ( twistIntensityHandle, 0.15f ) drawSomething ( mColorProgram, mFrameBufferMVPMatrix) mColorFilterBitmap = savePixelBufferBitmap ( ) disableTexture4 ( ) GLES30. glBindFramebuffer ( GLES30. GL_FRAMEBUFFER, 0 ) } finally { GLES30. glViewport ( viewPort[ 0 ] , viewPort[ 1 ] , viewPort[ 2 ] , viewPort[ 3 ] ) GLES30. glBindFramebuffer ( GLES30. GL_FRAMEBUFFER, previousFrameBuffer[ 0 ] ) GLES30. glUseProgram ( previousProgram[ 0 ] ) } } } fun drawSomething ( program: Int, mvpMatrix: FloatArray) { val matrixHandle = GLES30. glGetUniformLocation ( program, "uMVPMatrix" ) GLES30. glUniformMatrix4fv ( matrixHandle, 1 , false , mvpMatrix, NO_OFFSET) GLES30. glBindVertexArray ( mVAO[ 0 ] ) GLES30. glDrawElements ( GLES30. GL_TRIANGLES, index. size, GLES30. GL_UNSIGNED_SHORT, NO_OFFSET) GLES30. glBindVertexArray ( 0 ) } fun initEdgeFilterShader ( ) { val vertexShaderCode = """#version 300 esuniform mat4 uMVPMatrix;in vec4 aPosition;in vec2 aTexCoord;out vec2 vTexCoord;void main() {gl_Position = uMVPMatrix * aPosition;vTexCoord = aTexCoord;}""" . trimIndent ( ) val fragmentShaderCode = "" "#version 300 esprecision mediump float; uniform sampler2D uTexture_2; uniform vec2 uTextureSize; in vec2 vTexCoord; out vec4 fragColor; void main ( ) { float dx = 1.0 / uTextureSize. x; float dy = 1.0 / uTextureSize. y; vec4 center = texture ( uTexture_2, vTexCoord) ; vec4 left = texture ( uTexture_2, vTexCoord - vec2 ( dx, 0.0 ) ) ; vec4 right = texture ( uTexture_2, vTexCoord + vec2 ( dx, 0.0 ) ) ; vec4 top = texture ( uTexture_2, vTexCoord - vec2 ( 0.0 , dy) ) ; vec4 bottom = texture ( uTexture_2, vTexCoord + vec2 ( 0.0 , dy) ) ; vec4 horizontal = abs ( right - left) ; vec4 vertical = abs ( bottom - top) ; float edge = ( horizontal. r + horizontal. g + horizontal. b + vertical. r + vertical. g + vertical. b) / 6.0 ; fragColor = vec4 ( vec3 ( 1.0 - edge * 3.0 ) , 1.0 ) ; } "" ". trimIndent ( ) val vertexShader = LoadShaderUtil. loadShader ( GLES30. GL_VERTEX_SHADER, vertexShaderCode) val fragmentShader = LoadShaderUtil. loadShader ( GLES30. GL_FRAGMENT_SHADER, fragmentShaderCode) mEdgeProgram = GLES30. glCreateProgram ( ) GLES30. glAttachShader ( mEdgeProgram, vertexShader) GLES30. glAttachShader ( mEdgeProgram, fragmentShader) GLES30. glLinkProgram ( mEdgeProgram) GLES30. glDeleteShader ( vertexShader) GLES30. glDeleteShader ( fragmentShader) } fun initPixelFilterShader ( ) { val vertexShaderCode = """#version 300 esuniform mat4 uMVPMatrix;in vec4 aPosition;in vec2 aTexCoord;out vec2 vTexCoord;void main() {gl_Position = uMVPMatrix * aPosition;vTexCoord = aTexCoord;}""" . trimIndent ( ) val fragmentShaderCode = "" "#version 300 esprecision mediump float; uniform sampler2D uTexture_3; uniform vec2 uTextureSize; uniform float uPixelSize; in vec2 vTexCoord; out vec4 fragColor; void main ( ) { float dx = uPixelSize / uTextureSize. x; float dy = uPixelSize / uTextureSize. y; vec2 pixelatedCoord; pixelatedCoord. x = dx * floor ( vTexCoord. x / dx) + dx * 0.5 ; pixelatedCoord. y = dy * floor ( vTexCoord. y / dy) + dy * 0.5 ; vec4 pixelColor = texture ( uTexture_3, pixelatedCoord) ; const float colorLevels = 5.0 ; pixelColor = floor ( pixelColor * colorLevels) / colorLevels; vec2 pixelPos = fract ( vTexCoord / vec2 ( dx, dy) ) ; float borderFactor = step ( 0.95 , max ( pixelPos. x, pixelPos. y) ) ; pixelColor. rgb *= mix ( 1.0 , 0.8 , borderFactor) ; fragColor = pixelColor; } "" ". trimIndent ( ) val vertexShader = LoadShaderUtil. loadShader ( GLES30. GL_VERTEX_SHADER, vertexShaderCode) val fragmentShader = LoadShaderUtil. loadShader ( GLES30. GL_FRAGMENT_SHADER, fragmentShaderCode) mPixelProgram = GLES30. glCreateProgram ( ) GLES30. glAttachShader ( mPixelProgram, vertexShader) GLES30. glAttachShader ( mPixelProgram, fragmentShader) GLES30. glLinkProgram ( mPixelProgram) GLES30. glDeleteShader ( vertexShader) GLES30. glDeleteShader ( fragmentShader) } fun initColorFilterShader ( ) { val vertexShaderCode = """#version 300 esuniform mat4 uMVPMatrix;in vec4 aPosition;in vec2 aTexCoord;out vec2 vTexCoord;void main() {gl_Position = uMVPMatrix * aPosition;vTexCoord = aTexCoord;}""" . trimIndent ( ) val fragmentShaderCode = "" "#version 300 esprecision mediump float; uniform sampler2D uTexture_4; uniform float uTime; uniform float uTwistIntensity; in vec2 vTexCoord; out vec4 fragColor; vec3 rgb2hsv ( vec3 c) { vec4 K = vec4 ( 0.0 , - 1.0 / 3.0 , 2.0 / 3.0 , - 1.0 ) ; vec4 p = mix ( vec4 ( c. bg, K. wz) , vec4 ( c. gb, K. xy) , step ( c. b, c. g) ) ; vec4 q = mix ( vec4 ( p. xyw, c. r) , vec4 ( c. r, p. yzx) , step ( p. x, c. r) ) ; float d = q. x - min ( q. w, q. y) ; float e = 1.0e-10 ; return vec3 ( abs ( q. z + ( q. w - q. y) / ( 6.0 * d + e) ) , d / ( q. x + e) , q. x) ; } vec3 hsv2rgb ( vec3 c) { vec4 K = vec4 ( 1.0 , 2.0 / 3.0 , 1.0 / 3.0 , 3.0 ) ; vec3 p = abs ( fract ( c. xxx + K. xyz) * 6.0 - K. www) ; return c. z * mix ( K. xxx, clamp ( p - K. xxx, 0.0 , 1.0 ) , c. y) ; } void main ( ) { vec2 center = vec2 ( 0.5 , 0.5 ) ; vec2 texCoordFromCenter = vTexCoord - center; float distance = length ( texCoordFromCenter) ; float angle = atan ( texCoordFromCenter. y, texCoordFromCenter. x) ; angle += uTwistIntensity * ( 1.0 - distance) ; vec2 newCoord; newCoord. x = center. x + distance * cos ( angle) ; newCoord. y = center. y + distance * sin ( angle) ; vec4 color = texture ( uTexture_4, newCoord) ; vec3 hsv = rgb2hsv ( color. rgb) ; hsv. y = hsv. y * 1.4 ; hsv. z = hsv. z * 0.9 + 0.1 ; hsv. x = hsv. x + distance * 0.5 ; fragColor = vec4 ( hsv2rgb ( hsv) , color. a) ; } "" ". trimIndent ( ) val vertexShader = LoadShaderUtil. loadShader ( GLES30. GL_VERTEX_SHADER, vertexShaderCode) val fragmentShader = LoadShaderUtil. loadShader ( GLES30. GL_FRAGMENT_SHADER, fragmentShaderCode) mColorProgram = GLES30. glCreateProgram ( ) GLES30. glAttachShader ( mColorProgram, vertexShader) GLES30. glAttachShader ( mColorProgram, fragmentShader) GLES30. glLinkProgram ( mColorProgram) GLES30. glDeleteShader ( vertexShader) GLES30. glDeleteShader ( fragmentShader) } fun initEdgeFrameBuffer ( ) { GLES30. glGenFramebuffers ( mEdgeFBO. size, mEdgeFBO, NO_OFFSET) GLES30. glBindFramebuffer ( GLES30. GL_FRAMEBUFFER, mEdgeFBO[ 0 ] ) GLES30. glGenTextures ( mEdgeFBOTextureID. size, mEdgeFBOTextureID, NO_OFFSET) GLES30. glBindTexture ( GLES30. GL_TEXTURE_2D, mEdgeFBOTextureID[ 0 ] ) GLES30. glTexParameteri ( GLES30. GL_TEXTURE_2D, GLES30. GL_TEXTURE_MIN_FILTER, GLES30. GL_LINEAR) GLES30. glTexParameteri ( GLES30. GL_TEXTURE_2D, GLES30. GL_TEXTURE_MAG_FILTER, GLES30. GL_LINEAR) GLES30. glTexParameteri ( GLES30. GL_TEXTURE_2D, GLES30. GL_TEXTURE_WRAP_S, GLES30. GL_CLAMP_TO_EDGE) GLES30. glTexParameteri ( GLES30. GL_TEXTURE_2D, GLES30. GL_TEXTURE_WRAP_T, GLES30. GL_CLAMP_TO_EDGE) GLES30. glTexImage2D ( GLES30. GL_TEXTURE_2D, NO_OFFSET, GLES30. GL_RGBA, mFrameBufferWidth, mFrameBufferHeight, NO_OFFSET, GLES30. GL_RGBA, GLES30. GL_UNSIGNED_BYTE, null ) GLES30. glFramebufferTexture2D ( GLES30. GL_FRAMEBUFFER, GLES30. GL_COLOR_ATTACHMENT0, GLES30. GL_TEXTURE_2D, mEdgeFBOTextureID[ 0 ] , 0 ) if ( GLES30. glCheckFramebufferStatus ( GLES30. GL_FRAMEBUFFER) != GLES30. GL_FRAMEBUFFER_COMPLETE) { Log. e ( "yang" , "initColdFrameBuffer: FBO初始化失败" ) } GLES30. glBindTexture ( GLES30. GL_TEXTURE_2D, 0 ) GLES30. glBindFramebuffer ( GLES30. GL_FRAMEBUFFER, 0 ) } fun initPixelFrameBuffer ( ) { GLES30. glGenFramebuffers ( mPixelFBO. size, mPixelFBO, NO_OFFSET) GLES30. glBindFramebuffer ( GLES30. GL_FRAMEBUFFER, mPixelFBO[ 0 ] ) GLES30. glGenTextures ( mPixelFBOTextureID. size, mPixelFBOTextureID, NO_OFFSET) GLES30. glBindTexture ( GLES30. GL_TEXTURE_2D, mPixelFBOTextureID[ 0 ] ) GLES30. glTexParameteri ( GLES30. GL_TEXTURE_2D, GLES30. GL_TEXTURE_MIN_FILTER, GLES30. GL_LINEAR) GLES30. glTexParameteri ( GLES30. GL_TEXTURE_2D, GLES30. GL_TEXTURE_MAG_FILTER, GLES30. GL_LINEAR) GLES30. glTexParameteri ( GLES30. GL_TEXTURE_2D, GLES30. GL_TEXTURE_WRAP_S, GLES30. GL_CLAMP_TO_EDGE) GLES30. glTexParameteri ( GLES30. GL_TEXTURE_2D, GLES30. GL_TEXTURE_WRAP_T, GLES30. GL_CLAMP_TO_EDGE) GLES30. glTexImage2D ( GLES30. GL_TEXTURE_2D, NO_OFFSET, GLES30. GL_RGBA, mFrameBufferWidth, mFrameBufferHeight, NO_OFFSET, GLES30. GL_RGBA, GLES30. GL_UNSIGNED_BYTE, null ) GLES30. glFramebufferTexture2D ( GLES30. GL_FRAMEBUFFER, GLES30. GL_COLOR_ATTACHMENT0, GLES30. GL_TEXTURE_2D, mPixelFBOTextureID[ 0 ] , 0 ) if ( GLES30. glCheckFramebufferStatus ( GLES30. GL_FRAMEBUFFER) != GLES30. GL_FRAMEBUFFER_COMPLETE) { Log. e ( "yang" , "initColdFrameBuffer: FBO初始化失败" ) } GLES30. glBindTexture ( GLES30. GL_TEXTURE_2D, 0 ) GLES30. glBindFramebuffer ( GLES30. GL_FRAMEBUFFER, 0 ) } fun initColorFrameBuffer ( ) { GLES30. glGenFramebuffers ( mColorFBO. size, mColorFBO, NO_OFFSET) GLES30. glBindFramebuffer ( GLES30. GL_FRAMEBUFFER, mColorFBO[ 0 ] ) GLES30. glGenTextures ( mColorFBOTextureID. size, mColorFBOTextureID, NO_OFFSET) GLES30. glBindTexture ( GLES30. GL_TEXTURE_2D, mColorFBOTextureID[ 0 ] ) GLES30. glTexParameteri ( GLES30. GL_TEXTURE_2D, GLES30. GL_TEXTURE_MIN_FILTER, GLES30. GL_LINEAR) GLES30. glTexParameteri ( GLES30. GL_TEXTURE_2D, GLES30. GL_TEXTURE_MAG_FILTER, GLES30. GL_LINEAR) GLES30. glTexParameteri ( GLES30. GL_TEXTURE_2D, GLES30. GL_TEXTURE_WRAP_S, GLES30. GL_CLAMP_TO_EDGE) GLES30. glTexParameteri ( GLES30. GL_TEXTURE_2D, GLES30. GL_TEXTURE_WRAP_T, GLES30. GL_CLAMP_TO_EDGE) GLES30. glTexImage2D ( GLES30. GL_TEXTURE_2D, NO_OFFSET, GLES30. GL_RGBA, mFrameBufferWidth, mFrameBufferHeight, NO_OFFSET, GLES30. GL_RGBA, GLES30. GL_UNSIGNED_BYTE, null ) GLES30. glFramebufferTexture2D ( GLES30. GL_FRAMEBUFFER, GLES30. GL_COLOR_ATTACHMENT0, GLES30. GL_TEXTURE_2D, mColorFBOTextureID[ 0 ] , 0 ) if ( GLES30. glCheckFramebufferStatus ( GLES30. GL_FRAMEBUFFER) != GLES30. GL_FRAMEBUFFER_COMPLETE) { Log. e ( "yang" , "initColdFrameBuffer: FBO初始化失败" ) } GLES30. glBindTexture ( GLES30. GL_TEXTURE_2D, 0 ) GLES30. glBindFramebuffer ( GLES30. GL_FRAMEBUFFER, 0 ) } fun savePixelBufferBitmap ( ) : Bitmap? { val pixelBuffer = ByteBuffer. allocateDirect ( mFrameBufferWidth * mFrameBufferHeight * 4 ) . order ( ByteOrder. LITTLE_ENDIAN) GLES30. glReadPixels ( 0 , 0 , mFrameBufferWidth, mFrameBufferHeight, GLES30. GL_RGBA, GLES30. GL_UNSIGNED_BYTE, pixelBuffer) val bitmap = Bitmap. createBitmap ( mFrameBufferWidth, mFrameBufferHeight, Bitmap. Config. ARGB_8888) pixelBuffer. rewind ( ) bitmap. copyPixelsFromBuffer ( pixelBuffer) return bitmap} fun computeMVPMatrix ( width: Int, height: Int) { takeIf { width > height } ? . let { mViewPortRatio = ( width * 1f ) / heightMatrix. orthoM ( mProjectionMatrix, NO_OFFSET, - mViewPortRatio, mViewPortRatio, - 1f , 1f , 0f , 1f ) } ?: run { mViewPortRatio = ( height * 1f ) / widthMatrix. orthoM ( mProjectionMatrix, NO_OFFSET, - 1f , 1f , - mViewPortRatio, mViewPortRatio, 0f , 1f ) } Matrix. setLookAtM ( mViewMatrix, NO_OFFSET, 0f , 0f , 1f , 0f , 0f , 0f , 0f , 1f , 0f ) Matrix. multiplyMM ( mMVPMatrix, NO_OFFSET, mProjectionMatrix, NO_OFFSET, mViewMatrix, NO_OFFSET ) Matrix. scaleM ( mMVPMatrix, NO_OFFSET, 1f , - 1f , 1f , ) } fun computeFrameBufferMVPMatrix ( ) { takeIf { mFrameBufferWidth > mFrameBufferHeight } ? . let { mViewPortRatio = ( mFrameBufferWidth * 1f ) / mFrameBufferHeightMatrix. orthoM ( mProjectionMatrix, NO_OFFSET, - mViewPortRatio, mViewPortRatio, - 1f , 1f , 0f , 1f ) } ?: run { mViewPortRatio = ( mFrameBufferHeight * 1f ) / mFrameBufferWidthMatrix. orthoM ( mProjectionMatrix, NO_OFFSET, - 1f , 1f , - mViewPortRatio, mViewPortRatio, 0f , 1f ) } Matrix. setLookAtM ( mViewMatrix, NO_OFFSET, 0f , 0f , 1f , 0f , 0f , 0f , 0f , 1f , 0f ) Matrix. multiplyMM ( mFrameBufferMVPMatrix, NO_OFFSET, mProjectionMatrix, NO_OFFSET, mViewMatrix, NO_OFFSET )
} fun loadTexture ( context: Context, resourceId: Int) : Int { val textureId = IntArray ( 1 ) GLES30. glGenTextures ( 1 , textureId, 0 ) GLES30. glBindTexture ( GLES30. GL_TEXTURE_2D, textureId[ 0 ] ) GLES30. glTexParameteri ( GLES30. GL_TEXTURE_2D, GLES30. GL_TEXTURE_MIN_FILTER, GLES30. GL_LINEAR) GLES30. glTexParameteri ( GLES30. GL_TEXTURE_2D, GLES30. GL_TEXTURE_MAG_FILTER, GLES30. GL_LINEAR) GLES30. glTexParameteri ( GLES30. GL_TEXTURE_2D, GLES30. GL_TEXTURE_WRAP_S, GLES30. GL_CLAMP_TO_EDGE) GLES30. glTexParameteri ( GLES30. GL_TEXTURE_2D, GLES30. GL_TEXTURE_WRAP_T, GLES30. GL_CLAMP_TO_EDGE) val options = BitmapFactory. Options ( ) . apply { inScaled = false } val bitmap = BitmapFactory. decodeResource ( context. resources, resourceId, options) GLUtils. texImage2D ( GLES30. GL_TEXTURE_2D, 0 , bitmap, 0 ) bitmap. recycle ( ) GLES30. glBindTexture ( GLES30. GL_TEXTURE_2D, 0 ) mFrameBufferWidth = max ( mFrameBufferWidth, bitmap. width) mFrameBufferHeight = max ( mFrameBufferHeight, bitmap. height) Log. e ( "yang" , "loadTexture: 纹理加载成功 bitmap.width: ${ bitmap. width } bitmap.height: ${ bitmap. height } " ) return textureId[ 0 ] } fun enableTexture0 ( program: Int, id: Int) { GLES30. glActiveTexture ( GLES30. GL_TEXTURE0) GLES30. glBindTexture ( GLES30. GL_TEXTURE_2D, id) val textureSampleHandle = GLES30. glGetUniformLocation ( program, "uTexture_0" ) GLES30. glUniform1i ( textureSampleHandle, 0 ) } fun enableTexture2 ( program: Int, id: Int) { GLES30. glActiveTexture ( GLES30. GL_TEXTURE2) GLES30. glBindTexture ( GLES30. GL_TEXTURE_2D, id) val textureSampleHandle2 = GLES30. glGetUniformLocation ( program, "uTexture_2" ) GLES30. glUniform1i ( textureSampleHandle2, 2 ) } fun enableTexture3 ( program: Int, id: Int) { GLES30. glActiveTexture ( GLES30. GL_TEXTURE3) GLES30. glBindTexture ( GLES30. GL_TEXTURE_2D, id) val textureSampleHandle3 = GLES30. glGetUniformLocation ( program, "uTexture_3" ) GLES30. glUniform1i ( textureSampleHandle3, 3 ) } fun enableTexture4 ( program: Int, id: Int) { GLES30. glActiveTexture ( GLES30. GL_TEXTURE4) GLES30. glBindTexture ( GLES30. GL_TEXTURE_2D, id) val textureSampleHandle4 = GLES30. glGetUniformLocation ( program, "uTexture_4" ) GLES30. glUniform1i ( textureSampleHandle4, 4 ) } fun disableTexture0 ( ) { GLES30. glActiveTexture ( GLES30. GL_TEXTURE0) GLES30. glBindTexture ( GLES30. GL_TEXTURE_2D, 0 ) } fun disableTexture2 ( ) { GLES30. glActiveTexture ( GLES30. GL_TEXTURE2) GLES30. glBindTexture ( GLES30. GL_TEXTURE_2D, 2 ) } fun disableTexture3 ( ) { GLES30. glActiveTexture ( GLES30. GL_TEXTURE3) GLES30. glBindTexture ( GLES30. GL_TEXTURE_2D, 3 ) } fun disableTexture4 ( ) { GLES30. glActiveTexture ( GLES30. GL_TEXTURE4) GLES30. glBindTexture ( GLES30. GL_TEXTURE_2D, 4 ) } fun initTexture0 ( context: Context, resourceId: Int) { mTextureID[ 0 ] = loadTexture ( context, resourceId) } fun getEdgeFilterBitmap ( ) : Bitmap? { return mEdgeFilterBitmap} fun getPixelFilterBitmap ( ) : Bitmap? { return mPixelFilterBitmap} fun getColorFilterBitmap ( ) : Bitmap? { return mColorFilterBitmap} fun getOriginBitmap ( ) : Bitmap? { return mOriginBitmap} object LoadShaderUtil { fun loadShader ( type: Int, source: String) : Int { val shader = GLES30. glCreateShader ( type) GLES30. glShaderSource ( shader, source) GLES30. glCompileShader ( shader) return shader} }
}
关键代码
Renderer.onSurfaceCreated
中的初始化
初始化原图纹理 初始化原图着色器程序 初始化顶点坐标和纹理坐标缓冲区 初始化原图帧缓冲 初始化其他三个滤镜的着色器程序和帧缓冲 此时的原图帧缓冲和其他三个滤镜的帧缓冲附着的纹理均为null
,因为还没有开始绘制
override fun onSurfaceCreated ( gl: GL10? , config: EGLConfig? ) { GLES30. glClearColor ( 0.0f , 0.5f , 0.5f , 1.0f ) mDrawData = DrawData ( ) . apply { initTexture0 ( mContext, R. drawable. picture) initShader ( ) initVertexBuffer ( ) initFrameBuffer ( ) initEdgeFilterShader ( ) initEdgeFrameBuffer ( ) initPixelFilterShader ( ) initPixelFrameBuffer ( ) initColorFilterShader ( ) initColorFrameBuffer ( ) }
}
Renderer.onDrawFrame
中的绘制
先给原图帧缓冲绘制 mDrawData?.drawOriginFrameBuffer()
,完成后原图帧缓冲中会有一张原图纹理 先保存当前视口,当前着色器程序,当前作用的帧缓冲 激活纹理编号采样器0
,绑定需要使用原图纹理ID
绑定需要作用的帧缓冲ID
对象,先清除帧缓冲上的颜色 开始绘制原图纹理 解绑作用帧缓冲的ID
对象,解绑使用的原图纹理ID
恢复视口,着色器程序,帧缓冲 再给像素滤镜帧缓冲绘制mDrawData?.drawPixelFilterBitmap()
,绘制时绑定的是原图纹理ID
,绘制完成后像素滤镜帧缓冲会保留原图+像素滤镜
的纹理 再给彩色旋涡滤镜帧缓冲绘制mDrawData?.drawColorFilterBitmap()
,绘制时绑定的是像素滤镜帧缓冲纹理ID
,绘制完成后彩色旋涡滤镜帧缓冲会保留原图+像素滤镜+彩色旋涡滤镜
的纹理 再给边缘滤镜帧缓冲绘制mDrawData?.drawEdgeFilterBitmap()
,绘制时绑定的是彩色旋涡滤镜帧缓冲纹理ID
,绘制完成后边缘滤镜帧缓冲会保留原图+像素滤镜+彩色旋涡滤镜+边缘滤镜
的纹理 再给GLSurfaceView
绘制三个滤镜作用的纹理,直接绑定边缘滤镜帧缓冲ID
override fun onDrawFrame ( gl: GL10? ) { GLES30. glClear ( GLES30. GL_COLOR_BUFFER_BIT) mDrawData? . drawOriginFrameBuffer ( ) mDrawData? . drawPixelFilterBitmap ( ) mDrawData? . drawColorFilterBitmap ( ) mDrawData? . drawEdgeFilterBitmap ( ) mDrawData? . drawGLSurfaceView ( )
}
fun drawOriginFrameBuffer ( ) { val previousProgram = IntArray ( 1 ) val previousFrameBuffer = IntArray ( 1 ) val viewPort = IntArray ( 4 ) try { GLES30. glGetIntegerv ( GLES30. GL_VIEWPORT, viewPort, NO_OFFSET) GLES30. glGetIntegerv ( GLES30. GL_CURRENT_PROGRAM, previousProgram, 0 ) GLES30. glGetIntegerv ( GLES30. GL_FRAMEBUFFER_BINDING, previousFrameBuffer, 0 ) GLES30. glViewport ( 0 , 0 , mFrameBufferWidth, mFrameBufferHeight) enableTexture0 ( mProgram, mTextureID[ 0 ] ) GLES30. glBindFramebuffer ( GLES30. GL_FRAMEBUFFER, mFBO[ 0 ] ) GLES30. glClear ( GLES30. GL_COLOR_BUFFER_BIT) computeFrameBufferMVPMatrix ( ) drawSomething ( mProgram, mFrameBufferMVPMatrix) mOriginBitmap = savePixelBufferBitmap ( ) GLES30. glBindFramebuffer ( GLES30. GL_FRAMEBUFFER, 0 ) disableTexture0 ( ) } finally { GLES30. glViewport ( viewPort[ 0 ] , viewPort[ 1 ] , viewPort[ 2 ] , viewPort[ 3 ] ) GLES30. glBindFramebuffer ( GLES30. GL_FRAMEBUFFER, previousFrameBuffer[ 0 ] ) GLES30. glUseProgram ( previousProgram[ 0 ] ) }
} fun drawEdgeFilterBitmap ( ) { takeIf { mEdgeFilterBitmap == null } ? . let { val previousProgram = IntArray ( 1 ) val previousFrameBuffer = IntArray ( 1 ) val viewPort = IntArray ( 4 ) try { GLES30. glGetIntegerv ( GLES30. GL_VIEWPORT, viewPort, NO_OFFSET) GLES30. glGetIntegerv ( GLES30. GL_CURRENT_PROGRAM, previousProgram, 0 ) GLES30. glGetIntegerv ( GLES30. GL_FRAMEBUFFER_BINDING, previousFrameBuffer, 0 ) GLES30. glViewport ( 0 , 0 , mFrameBufferWidth, mFrameBufferHeight) GLES30. glUseProgram ( mEdgeProgram) GLES30. glBindFramebuffer ( GLES30. GL_FRAMEBUFFER, mEdgeFBO[ 0 ] ) GLES30. glClear ( GLES30. GL_COLOR_BUFFER_BIT) enableTexture2 ( mEdgeProgram, mColorFBOTextureID[ 0 ] ) val textureSizeHandle = GLES30. glGetUniformLocation ( mEdgeProgram, "uTextureSize" ) GLES30. glUniform2f ( textureSizeHandle, mFrameBufferWidth. toFloat ( ) , mFrameBufferHeight. toFloat ( ) ) drawSomething ( mEdgeProgram, mFrameBufferMVPMatrix) mEdgeFilterBitmap = savePixelBufferBitmap ( ) disableTexture2 ( ) GLES30. glBindFramebuffer ( GLES30. GL_FRAMEBUFFER, 0 ) } finally { GLES30. glViewport ( viewPort[ 0 ] , viewPort[ 1 ] , viewPort[ 2 ] , viewPort[ 3 ] ) GLES30. glBindFramebuffer ( GLES30. GL_FRAMEBUFFER, previousFrameBuffer[ 0 ] ) GLES30. glUseProgram ( previousProgram[ 0 ] ) } }
} fun drawPixelFilterBitmap ( ) { takeIf { mPixelFilterBitmap == null } ? . let { val previousProgram = IntArray ( 1 ) val previousFrameBuffer = IntArray ( 1 ) val viewPort = IntArray ( 4 ) try { GLES30. glGetIntegerv ( GLES30. GL_VIEWPORT, viewPort, NO_OFFSET) GLES30. glGetIntegerv ( GLES30. GL_CURRENT_PROGRAM, previousProgram, 0 ) GLES30. glGetIntegerv ( GLES30. GL_FRAMEBUFFER_BINDING, previousFrameBuffer, 0 ) GLES30. glViewport ( 0 , 0 , mFrameBufferWidth, mFrameBufferHeight) GLES30. glUseProgram ( mPixelProgram) GLES30. glBindFramebuffer ( GLES30. GL_FRAMEBUFFER, mPixelFBO[ 0 ] ) GLES30. glClear ( GLES30. GL_COLOR_BUFFER_BIT) enableTexture3 ( mPixelProgram, mFBOTextureID[ 0 ] ) val textureSizeHandle = GLES30. glGetUniformLocation ( mPixelProgram, "uTextureSize" ) GLES30. glUniform2f ( textureSizeHandle, mFrameBufferWidth. toFloat ( ) , mFrameBufferWidth. toFloat ( ) ) val pixelSizeHandle = GLES30. glGetUniformLocation ( mPixelProgram, "uPixelSize" ) GLES30. glUniform1f ( pixelSizeHandle, 15.0f ) drawSomething ( mPixelProgram, mFrameBufferMVPMatrix) mPixelFilterBitmap = savePixelBufferBitmap ( ) disableTexture3 ( ) GLES30. glBindFramebuffer ( GLES30. GL_FRAMEBUFFER, 0 ) } finally { GLES30. glViewport ( viewPort[ 0 ] , viewPort[ 1 ] , viewPort[ 2 ] , viewPort[ 3 ] ) GLES30. glBindFramebuffer ( GLES30. GL_FRAMEBUFFER, previousFrameBuffer[ 0 ] ) GLES30. glUseProgram ( previousProgram[ 0 ] ) } }
} fun drawColorFilterBitmap ( ) { takeIf { mColorFilterBitmap == null } ? . let { val previousProgram = IntArray ( 1 ) val previousFrameBuffer = IntArray ( 1 ) val viewPort = IntArray ( 4 ) try { GLES30. glGetIntegerv ( GLES30. GL_VIEWPORT, viewPort, NO_OFFSET) GLES30. glViewport ( 0 , 0 , mFrameBufferWidth, mFrameBufferHeight) GLES30. glGetIntegerv ( GLES30. GL_CURRENT_PROGRAM, previousProgram, 0 ) GLES30. glGetIntegerv ( GLES30. GL_FRAMEBUFFER_BINDING, previousFrameBuffer, 0 ) GLES30. glUseProgram ( mColorProgram) GLES30. glBindFramebuffer ( GLES30. GL_FRAMEBUFFER, mColorFBO[ 0 ] ) GLES30. glClear ( GLES30. GL_COLOR_BUFFER_BIT) enableTexture4 ( mColorProgram, mPixelFBOTextureID[ 0 ] ) val timeHandle = GLES30. glGetUniformLocation ( mColorProgram, "uTime" ) if ( timeHandle != - 1 ) { GLES30. glUniform1f ( timeHandle, ( System. currentTimeMillis ( ) % 10000 ) / 10000.0f ) } val twistIntensityHandle = GLES30. glGetUniformLocation ( mColorProgram, "uTwistIntensity" ) GLES30. glUniform1f ( twistIntensityHandle, 0.15f ) drawSomething ( mColorProgram, mFrameBufferMVPMatrix) mColorFilterBitmap = savePixelBufferBitmap ( ) disableTexture4 ( ) GLES30. glBindFramebuffer ( GLES30. GL_FRAMEBUFFER, 0 ) } finally { GLES30. glViewport ( viewPort[ 0 ] , viewPort[ 1 ] , viewPort[ 2 ] , viewPort[ 3 ] ) GLES30. glBindFramebuffer ( GLES30. GL_FRAMEBUFFER, previousFrameBuffer[ 0 ] ) GLES30. glUseProgram ( previousProgram[ 0 ] ) } }
} fun drawGLSurfaceView ( ) { val previousProgram = IntArray ( 1 ) val previousFrameBuffer = IntArray ( 1 ) try { GLES30. glGetIntegerv ( GLES30. GL_CURRENT_PROGRAM, previousProgram, 0 ) GLES30. glGetIntegerv ( GLES30. GL_FRAMEBUFFER_BINDING, previousFrameBuffer, 0 ) enableTexture0 ( mProgram, mEdgeFBOTextureID[ 0 ] ) drawSomething ( mProgram, mMVPMatrix) disableTexture0 ( ) } finally { GLES30. glBindFramebuffer ( GLES30. GL_FRAMEBUFFER, previousFrameBuffer[ 0 ] ) GLES30. glUseProgram ( previousProgram[ 0 ] ) } }
效果图