XML
文件
<?xml version="1.0" encoding="utf-8"?>
< com.example.myapplication.EGLSurfaceView xmlns: android= " http://schemas.android.com/apk/res/android" android: layout_width= " match_parent" android: layout_height= " match_parent" />
Activity
代码
class MainActivity8 : AppCompatActivity ( ) { override fun onCreate ( savedInstanceState: Bundle? ) { super . onCreate ( savedInstanceState) setContentView ( R. layout. activity_main8) }
}
SurfaceView
代码
class EGLSurfaceView ( context: Context, attrs: AttributeSet? = null ) : SurfaceView ( context, attrs) { private val renderer = EGLRenderer ( context) init { holder. addCallback ( renderer. surfaceCallback) } fun setRenderStrategy ( strategy: RenderStrategy) { renderer. setRenderStrategy ( strategy) }
}
渲染器代码
class EGLRenderer ( context: Context) { private val strategy: RenderStrategy = MyRenderStrategy ( context) private val engine: EGLRenderEngine = EGLRenderEngine ( strategy) fun setRenderStrategy ( strategy: RenderStrategy) { } val surfaceCallback = object : SurfaceHolder. Callback { override fun surfaceCreated ( holder: SurfaceHolder) { engine. onSurfaceCreated ( holder. surface) } override fun surfaceChanged ( holder: SurfaceHolder, format: Int, width: Int, height: Int) { engine. onSurfaceChanged ( width, height) } override fun surfaceDestroyed ( holder: SurfaceHolder) { engine. onSurfaceDestroyed ( ) } }
}
渲染引擎代码
class EGLRenderEngine ( private val strategy: RenderStrategy) { private var mEGLEnvironment: EGLEnvironment? = null private var mRenderThread: RenderThread? = null fun onSurfaceCreated ( surface: Surface) { mRenderThread = RenderThread ( surface, strategy) . apply { start ( ) } } fun onSurfaceChanged ( width: Int, height: Int) { mRenderThread? . updateSize ( width, height) } fun onSurfaceDestroyed ( ) { mRenderThread? . shutdown ( ) mRenderThread = null } private inner class RenderThread ( private val surface: Surface, private val strategy: RenderStrategy) : Thread ( ) { @Volatile private var running = true @Volatile private var sizeChanged = false private var width = 0 private var height = 0 fun updateSize ( width: Int, height: Int) { this . width = widththis . height = heightsizeChanged = true } fun shutdown ( ) { running = false interrupt ( ) strategy. onSurfaceDestroyed ( ) mEGLEnvironment? . release ( ) } override fun run ( ) { try { mEGLEnvironment = EGLEnvironmentBuilder ( ) . build ( surface) strategy. onSurfaceCreated ( ) while ( running) { if ( sizeChanged) { strategy. onSurfaceChanged ( width, height) sizeChanged = false } strategy. onDrawFrame ( ) mEGLEnvironment? . swapBuffers ( ) } } catch ( e: Exception) { Log. e ( "RenderEngine" , "Render thread error: ${ e. message} " ) } } }
}
自定义渲染策略代码
interface RenderStrategy { fun onSurfaceCreated ( ) fun onSurfaceChanged ( width: Int, height: Int) fun onDrawFrame ( ) fun onSurfaceDestroyed ( )
}
class MyRenderStrategy ( private val context: Context) : RenderStrategy { var mDrawData: EGLDrawData? = null override fun onSurfaceCreated ( ) { GLES30. glClearColor ( 0.0f , 0.5f , 0.5f , 1.0f ) mDrawData = EGLDrawData ( ) . apply { initTexture0 ( context, R. drawable. picture) initShaderProgram ( ) initOutlineShaderProgram ( ) initVertexBuffer ( ) } } override fun onSurfaceChanged ( width: Int, height: Int) { GLES30. glViewport ( 0 , 0 , width, height) mDrawData? . setSurfaceSize ( width, height) } override fun onDrawFrame ( ) { mDrawData? . drawCurrentOutput ( ) } override fun onSurfaceDestroyed ( ) { mDrawData? . release ( ) }
}
搭建EGL
环境代码
class EGLEnvironmentBuilder ( private val factory: EGLComponentFactory = DefaultEGLFactory ( ) ) { private lateinit var mEGL: EGL10private lateinit var mEGLDisplay: EGLDisplayprivate lateinit var mEGLConfig: EGLConfigprivate lateinit var mEGLContext: EGLContextprivate lateinit var mEGLSurface: EGLSurfacefun build ( surface: Surface) : EGLEnvironment { mEGL = factory. createEGL ( ) mEGLDisplay = factory. createEGLDisplay ( mEGL) mEGLConfig = factory. createEGLConfig ( mEGL, mEGLDisplay) mEGLContext = factory. createEGLContext ( mEGL, mEGLDisplay, mEGLConfig) mEGLSurface = factory. createEGLSurface ( mEGL, mEGLDisplay, mEGLConfig, surface) if ( ! mEGL. eglMakeCurrent ( mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext) ) { throw RuntimeException ( "eglMakeCurrent failed" ) } return EGLEnvironment ( mEGL, mEGLDisplay, mEGLContext, mEGLSurface) }
}
class EGLEnvironment ( val egl: EGL10, val display: EGLDisplay, val context: EGLContext, val surface: EGLSurface
) { fun swapBuffers ( ) { if ( ! egl. eglSwapBuffers ( display, surface) ) { throw RuntimeException ( "eglSwapBuffers failed" ) } } fun release ( ) { egl. eglMakeCurrent ( display, EGL10. EGL_NO_SURFACE, EGL10. EGL_NO_SURFACE, EGL10. EGL_NO_CONTEXT) egl. eglDestroySurface ( display, surface) egl. eglDestroyContext ( display, context) egl. eglTerminate ( display) }
}
interface EGLComponentFactory { fun createEGL ( ) : EGL10fun createEGLDisplay ( egl: EGL10) : EGLDisplayfun createEGLConfig ( egl: EGL10, display: EGLDisplay) : EGLConfigfun createEGLContext ( egl: EGL10, display: EGLDisplay, config: EGLConfig) : EGLContextfun createEGLSurface ( egl: EGL10, display: EGLDisplay, config: EGLConfig, surface: Surface) : EGLSurface
}
class DefaultEGLFactory : EGLComponentFactory { override fun createEGL ( ) : EGL10 = EGLContext. getEGL ( ) as EGL10override fun createEGLDisplay ( egl: EGL10) : EGLDisplay { val eglDisplay = egl. eglGetDisplay ( EGL10. EGL_DEFAULT_DISPLAY) if ( eglDisplay == EGL10. EGL_NO_DISPLAY) { throw RuntimeException ( "eglGetDisplay failed" ) } val version = IntArray ( 2 ) if ( ! egl. eglInitialize ( eglDisplay, version) ) { throw RuntimeException ( "eglInitialize failed" ) } return eglDisplay} override fun createEGLConfig ( egl: EGL10, display: EGLDisplay) : EGLConfig { val attributes = intArrayOf ( EGL_RED_SIZE, 8 , EGL_GREEN_SIZE, 8 , EGL_BLUE_SIZE, 8 , EGL_ALPHA_SIZE, 8 , EGL_DEPTH_SIZE, 8 , EGL_STENCIL_SIZE, 4 , EGL_NONE) val numConfigs = IntArray ( 1 ) egl. eglChooseConfig ( display, attributes, null , 0 , numConfigs) if ( numConfigs[ 0 ] <= 0 ) { throw RuntimeException ( "No matching EGL configs" ) } val configs = arrayOfNulls< EGLConfig> ( numConfigs[ 0 ] ) egl. eglChooseConfig ( display, attributes, configs, numConfigs[ 0 ] , numConfigs) return configs[ 0 ] ?: throw RuntimeException ( "No suitable EGL config found" ) } override fun createEGLContext ( egl: EGL10, display: EGLDisplay, config: EGLConfig) : EGLContext { val contextAttrs = intArrayOf ( EGL_CONTEXT_CLIENT_VERSION, 3 , EGL_NONE) val eglContext = egl. eglCreateContext ( display, config, EGL10. EGL_NO_CONTEXT, contextAttrs) if ( eglContext == EGL10. EGL_NO_CONTEXT) { throw RuntimeException ( "eglCreateContext failed" ) } return eglContext} override fun createEGLSurface ( egl: EGL10, display: EGLDisplay, config: EGLConfig, surface: Surface) : EGLSurface { val eglSurface = egl. eglCreateWindowSurface ( display, config, surface, null ) if ( eglSurface == EGL10. EGL_NO_SURFACE) { throw RuntimeException ( "eglCreateWindowSurface failed" ) } return eglSurface}
}
渲染数据代码
data class CubeInfo ( var x: Float, var y: Float, var angle: Float, var rotationSpeed: Float, var scale : Float
)
private val cubes = arrayOf ( CubeInfo ( x = - 1.0f , y = 1.0f , angle = 0f , rotationSpeed = 0.3f , scale = 0.3f ) , CubeInfo ( x = 1.0f , y = 1.0f , angle = 45f , rotationSpeed = 0.5f , scale = 0.4f ) , CubeInfo ( x = 0f , y = 0f , angle = 90f , rotationSpeed = 0.7f , scale = 0.2f ) , CubeInfo ( x = - 1.0f , y = - 1.0f , angle = 135f , rotationSpeed = 0.4f , scale = 0.5f ) , CubeInfo ( x = 1.0f , y = - 1.0f , angle = 180f , rotationSpeed = 0.2f , scale = 0.7f )
) class EGLDrawData { private var mProgram: Int = - 1 private var mOutlineProgram : Int = - 1 private var NO_OFFSET = 0 private val VERTEX_POS_DATA_SIZE = 3 private val TEXTURE_POS_DATA_SIZE = 2 private val STRIDE = ( VERTEX_POS_DATA_SIZE + TEXTURE_POS_DATA_SIZE) * 4 private var mVAO = IntArray ( 1 ) private var mVBO = IntArray ( 1 ) private var mTextureID = IntArray ( 1 ) private var mMVPMatrix = FloatArray ( 16 ) private val mProjectionMatrix = FloatArray ( 16 ) private val mViewMatrix = FloatArray ( 16 ) private val mModelMatrix = FloatArray ( 16 ) private var mViewPortRatio = 1f private var mSurfaceWidth = 0 private var mSurfaceHeight = 0 val vertexData = floatArrayOf ( - 0.5f , - 0.5f , - 0.5f , 0.0f , 0.0f , 0.5f , - 0.5f , - 0.5f , 1.0f , 0.0f , 0.5f , 0.5f , - 0.5f , 1.0f , 1.0f , 0.5f , 0.5f , - 0.5f , 1.0f , 1.0f , - 0.5f , 0.5f , - 0.5f , 0.0f , 1.0f , - 0.5f , - 0.5f , - 0.5f , 0.0f , 0.0f , - 0.5f , - 0.5f , 0.5f , 0.0f , 0.0f , 0.5f , - 0.5f , 0.5f , 1.0f , 0.0f , 0.5f , 0.5f , 0.5f , 1.0f , 1.0f , 0.5f , 0.5f , 0.5f , 1.0f , 1.0f , - 0.5f , 0.5f , 0.5f , 0.0f , 1.0f , - 0.5f , - 0.5f , 0.5f , 0.0f , 0.0f , - 0.5f , 0.5f , 0.5f , 1.0f , 0.0f , - 0.5f , 0.5f , - 0.5f , 1.0f , 1.0f , - 0.5f , - 0.5f , - 0.5f , 0.0f , 1.0f , - 0.5f , - 0.5f , - 0.5f , 0.0f , 1.0f , - 0.5f , - 0.5f , 0.5f , 0.0f , 0.0f , - 0.5f , 0.5f , 0.5f , 1.0f , 0.0f , 0.5f , 0.5f , 0.5f , 1.0f , 0.0f , 0.5f , 0.5f , - 0.5f , 1.0f , 1.0f , 0.5f , - 0.5f , - 0.5f , 0.0f , 1.0f , 0.5f , - 0.5f , - 0.5f , 0.0f , 1.0f , 0.5f , - 0.5f , 0.5f , 0.0f , 0.0f , 0.5f , 0.5f , 0.5f , 1.0f , 0.0f , - 0.5f , - 0.5f , - 0.5f , 0.0f , 1.0f , 0.5f , - 0.5f , - 0.5f , 1.0f , 1.0f , 0.5f , - 0.5f , 0.5f , 1.0f , 0.0f , 0.5f , - 0.5f , 0.5f , 1.0f , 0.0f , - 0.5f , - 0.5f , 0.5f , 0.0f , 0.0f , - 0.5f , - 0.5f , - 0.5f , 0.0f , 1.0f , - 0.5f , 0.5f , - 0.5f , 0.0f , 1.0f , 0.5f , 0.5f , - 0.5f , 1.0f , 1.0f , 0.5f , 0.5f , 0.5f , 1.0f , 0.0f , 0.5f , 0.5f , 0.5f , 1.0f , 0.0f , - 0.5f , 0.5f , 0.5f , 0.0f , 0.0f , - 0.5f , 0.5f , - 0.5f , 0.0f , 1.0f ) val vertexDataBuffer = ByteBuffer. allocateDirect ( vertexData. size * 4 ) . order ( ByteOrder. nativeOrder ( ) ) . asFloatBuffer ( ) . put ( vertexData) . position ( NO_OFFSET) fun initShaderProgram ( ) { 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. glDeleteShader ( vertexShader) GLES30. glDeleteShader ( fragmentShader) } fun initOutlineShaderProgram ( ) { val vertexShaderCode = """#version 300 esuniform mat4 uMVPMatrix; in vec4 aPosition; void main() {gl_Position = uMVPMatrix * aPosition; }""" . trimIndent ( ) val fragmentShaderCode = """#version 300 esprecision mediump float;out vec4 fragColor;void main() {fragColor = vec4(1.0, 1.0, 1.0, 1.0);}""" . trimIndent ( ) val vertexShader = LoadShaderUtil. loadShader ( GLES30. GL_VERTEX_SHADER, vertexShaderCode) val fragmentShader = LoadShaderUtil. loadShader ( GLES30. GL_FRAGMENT_SHADER, fragmentShaderCode) mOutlineProgram = GLES30. glCreateProgram ( ) GLES30. glAttachShader ( mOutlineProgram, vertexShader) GLES30. glAttachShader ( mOutlineProgram, fragmentShader) GLES30. glLinkProgram ( mOutlineProgram) 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, vertexData. size * 4 , vertexDataBuffer, GLES30. GL_STATIC_DRAW) val positionHandle = GLES30. glGetAttribLocation ( mProgram, "aPosition" ) GLES30. glEnableVertexAttribArray ( positionHandle) GLES30. glVertexAttribPointer ( positionHandle, VERTEX_POS_DATA_SIZE, GLES30. GL_FLOAT, false , STRIDE, NO_OFFSET ) val textureHandle = GLES30. glGetAttribLocation ( mProgram, "aTexCoord" ) GLES30. glEnableVertexAttribArray ( textureHandle) GLES30. glVertexAttribPointer ( textureHandle, TEXTURE_POS_DATA_SIZE, GLES30. GL_FLOAT, false , STRIDE, VERTEX_POS_DATA_SIZE * 4 ) GLES30. glBindVertexArray ( 0 ) GLES30. glBindBuffer ( GLES30. GL_ARRAY_BUFFER, 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. glDrawArrays ( GLES30. GL_TRIANGLES, NO_OFFSET, vertexData. size / ( VERTEX_POS_DATA_SIZE + TEXTURE_POS_DATA_SIZE) ) GLES30. glBindVertexArray ( 0 ) } fun setSurfaceSize ( width: Int, height: Int) { mSurfaceWidth = widthmSurfaceHeight = height} fun resetMatrix ( ) { Matrix. setIdentityM ( mModelMatrix, NO_OFFSET) Matrix. setIdentityM ( mViewMatrix, NO_OFFSET) Matrix. setIdentityM ( mProjectionMatrix, NO_OFFSET) Matrix. setIdentityM ( mMVPMatrix, NO_OFFSET) } fun computeMVPMatrix ( width: Int, height: Int, cube: CubeInfo) { mSurfaceWidth = widthmSurfaceHeight = heightcube. angle += cube. rotationSpeedcube. angle %= 360 Matrix. scaleM ( mModelMatrix, NO_OFFSET, cube. scale, cube. scale, cube. scale) Matrix. translateM ( mModelMatrix, NO_OFFSET, cube. x, cube. y, 0f ) Matrix. rotateM ( mModelMatrix, NO_OFFSET, cube. angle, 0.5f , 0.5f , 0f ) val isLandscape = width > heightmViewPortRatio = if ( isLandscape) width. toFloat ( ) / height else height. toFloat ( ) / widthval radius = sqrt ( 1f + mViewPortRatio * mViewPortRatio) val near = 0.1f val far = near + 2 * radiusval distance = near / ( near + radius) Matrix. setLookAtM ( mViewMatrix, NO_OFFSET, 0f , 0f , near + radius, 0f , 0f , 0f , 0f , 1f , 0f ) Matrix. frustumM ( mProjectionMatrix, NO_OFFSET, if ( isLandscape) ( - mViewPortRatio * distance) else ( - 1f * distance) , if ( isLandscape) ( mViewPortRatio * distance) else ( 1f * distance) , if ( isLandscape) ( - 1f * distance) else ( - mViewPortRatio * distance) , if ( isLandscape) ( 1f * distance) else ( mViewPortRatio * distance) , near, far ) Matrix. multiplyMM ( mMVPMatrix, NO_OFFSET, mViewMatrix, NO_OFFSET, mModelMatrix, NO_OFFSET) Matrix. multiplyMM ( mMVPMatrix, NO_OFFSET, mProjectionMatrix, NO_OFFSET, mMVPMatrix, NO_OFFSET) Matrix. scaleM ( mMVPMatrix, NO_OFFSET, 1f , - 1f , 1f , ) } 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 ) 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" ) if ( textureSampleHandle != - 1 ) { GLES30. glUniform1i ( textureSampleHandle, 0 ) } } fun disableTexture0 ( ) { GLES30. glActiveTexture ( GLES30. GL_TEXTURE0) GLES30. glBindTexture ( GLES30. GL_TEXTURE_2D, 0 ) } fun initTexture0 ( context: Context, resourceId: Int) { mTextureID[ 0 ] = loadTexture ( context, resourceId) } fun drawCurrentOutput ( ) { val state = saveGLState ( ) try { GLES30. glClearColor ( 0.0f , 0.5f , 0.5f , 1.0f ) GLES30. glClear ( GLES30. GL_COLOR_BUFFER_BIT or GLES30. GL_DEPTH_BUFFER_BIT or GLES30. GL_STENCIL_BUFFER_BIT) GLES30. glEnable ( GLES30. GL_DEPTH_TEST) GLES30. glEnable ( GLES30. GL_STENCIL_TEST) GLES30. glColorMask ( false , false , false , false ) GLES30. glDepthMask ( false ) GLES30. glStencilFunc ( GLES30. GL_ALWAYS, 1 , 0xFF ) GLES30. glStencilOp ( GLES30. GL_KEEP, GLES30. GL_KEEP, GLES30. GL_REPLACE) drawStencilRect ( ) GLES30. glColorMask ( true , true , true , true ) GLES30. glDepthMask ( true ) GLES30. glStencilFunc ( GLES30. GL_EQUAL, 1 , 0xFF ) GLES30. glStencilOp ( GLES30. GL_KEEP, GLES30. GL_KEEP, GLES30. GL_KEEP) GLES30. glUseProgram ( mProgram) enableTexture0 ( mProgram, mTextureID[ 0 ] ) for ( cube in cubes) { resetMatrix ( ) computeMVPMatrix ( mSurfaceWidth, mSurfaceHeight, cube) drawSomething ( mProgram, mMVPMatrix) } disableTexture0 ( ) GLES30. glDisable ( GLES30. GL_STENCIL_TEST) GLES30. glDisable ( GLES30. GL_DEPTH_TEST) } finally { restoreGLState ( state) } } fun drawStencilRect ( ) { GLES30. glUseProgram ( mOutlineProgram) val vertices = floatArrayOf ( - 0.5f , - 0.5f , 0.0f , 0.5f , - 0.5f , 0.0f , 0.5f , 0.5f , 0.0f , - 0.5f , 0.5f , 0.0f ) val indices = shortArrayOf ( 0 , 1 , 2 , 0 , 2 , 3 ) val vertexBuffer = ByteBuffer. allocateDirect ( vertices. size * 4 ) . order ( ByteOrder. nativeOrder ( ) ) . asFloatBuffer ( ) . put ( vertices) . position ( 0 ) val indexBuffer = ByteBuffer. allocateDirect ( indices. size * 2 ) . order ( ByteOrder. nativeOrder ( ) ) . asShortBuffer ( ) . put ( indices) . position ( 0 ) val identityMatrix = FloatArray ( 16 ) Matrix. setIdentityM ( identityMatrix, 0 ) val positionHandle = GLES30. glGetAttribLocation ( mOutlineProgram, "aPosition" ) val matrixHandle = GLES30. glGetUniformLocation ( mOutlineProgram, "uMVPMatrix" ) if ( positionHandle == - 1 || matrixHandle == - 1 ) { Log. e ( "yang" , "着色器变量未找到: aPosition=$positionHandle , uMVPMatrix =$matrixHandle " ) return } GLES30. glEnableVertexAttribArray ( positionHandle) GLES30. glVertexAttribPointer ( positionHandle, 3 , GLES30. GL_FLOAT, false , 0 , vertexBuffer) GLES30. glUniformMatrix4fv ( matrixHandle, 1 , false , identityMatrix, 0 ) GLES30. glDrawElements ( GLES30. GL_TRIANGLES, indices. size, GLES30. GL_UNSIGNED_SHORT, indexBuffer) GLES30. glDisableVertexAttribArray ( positionHandle) } private fun drawRect ( program: Int, left: Float, bottom: Float, right: Float, top: Float) { val rectVertices = floatArrayOf ( left, bottom, 0.0f , right, bottom, 0.0f , right, top, 0.0f , left, top, 0.0f ) val indices = shortArrayOf ( 0 , 1 , 2 , 0 , 2 , 3 ) val vertexBuffer = ByteBuffer. allocateDirect ( rectVertices. size * 4 ) . order ( ByteOrder. nativeOrder ( ) ) . asFloatBuffer ( ) . put ( rectVertices) . position ( 0 ) val indexBuffer = ByteBuffer. allocateDirect ( indices. size * 2 ) . order ( ByteOrder. nativeOrder ( ) ) . asShortBuffer ( ) . put ( indices) . position ( 0 ) val identityMatrix = FloatArray ( 16 ) Matrix. setIdentityM ( identityMatrix, 0 ) val positionHandle = GLES30. glGetAttribLocation ( program, "aPosition" ) val matrixHandle = GLES30. glGetUniformLocation ( program, "uMVPMatrix" ) GLES30. glEnableVertexAttribArray ( positionHandle) GLES30. glVertexAttribPointer ( positionHandle, 3 , GLES30. GL_FLOAT, false , 0 , vertexBuffer) GLES30. glUniformMatrix4fv ( matrixHandle, 1 , false , identityMatrix, 0 ) GLES30. glDrawElements ( GLES30. GL_TRIANGLES, indices. size, GLES30. GL_UNSIGNED_SHORT, indexBuffer) GLES30. glDisableVertexAttribArray ( positionHandle) } private fun saveGLState ( ) : GLState { val viewport = IntArray ( 4 ) val program = IntArray ( 1 ) val framebuffer = IntArray ( 1 ) GLES30. glGetIntegerv ( GLES30. GL_VIEWPORT, viewport, 0 ) GLES30. glGetIntegerv ( GLES30. GL_CURRENT_PROGRAM, program, 0 ) GLES30. glGetIntegerv ( GLES30. GL_FRAMEBUFFER_BINDING, framebuffer, 0 ) return GLState ( viewport, program[ 0 ] , framebuffer[ 0 ] ) } private fun restoreGLState ( state: GLState) { GLES30. glViewport ( state. viewport[ 0 ] , state. viewport[ 1 ] , state. viewport[ 2 ] , state. viewport[ 3 ] ) GLES30. glUseProgram ( state. program) GLES30. glBindFramebuffer ( GLES30. GL_FRAMEBUFFER, state. framebuffer) } fun release ( ) { if ( mVAO[ 0 ] != 0 ) { GLES30. glDeleteVertexArrays ( 1 , mVAO, 0 ) mVAO[ 0 ] = 0 } if ( mVBO[ 0 ] != 0 ) { GLES30. glDeleteBuffers ( 1 , mVBO, 0 ) mVBO[ 0 ] = 0 } if ( mTextureID[ 0 ] != 0 ) { GLES30. glDeleteTextures ( 1 , mTextureID, 0 ) mTextureID[ 0 ] = 0 } if ( mProgram != - 1 ) { GLES30. glDeleteProgram ( mProgram) mProgram = - 1 } if ( mOutlineProgram != - 1 ) { GLES30. glDeleteProgram ( mOutlineProgram) mOutlineProgram = - 1 } vertexDataBuffer. clear ( ) } data class GLState ( val viewport: IntArray, val program: Int, val framebuffer: Int) object LoadShaderUtil { fun loadShader ( type: Int, source: String) : Int { val shader = GLES30. glCreateShader ( type) GLES30. glShaderSource ( shader, source) GLES30. glCompileShader ( shader) return shader} }
}
模版测试通用流程
GLES30. glClearColor ( 0.0f , 0.5f , 0.5f , 1.0f )
GLES30. glClear ( GLES30. GL_COLOR_BUFFER_BIT or GLES30. GL_DEPTH_BUFFER_BIT or GLES30. GL_STENCIL_BUFFER_BIT)
GLES30. glEnable ( GLES30. GL_DEPTH_TEST)
GLES30. glEnable ( GLES30. GL_STENCIL_TEST)
GLES30. glColorMask ( false , false , false , false )
GLES30. glDepthMask ( false )
GLES30. glStencilFunc ( GLES30. GL_ALWAYS, 1 , 0xFF )
GLES30. glStencilOp ( GLES30. GL_KEEP, GLES30. GL_KEEP, GLES30. GL_REPLACE)
drawStencilRect ( )
GLES30. glColorMask ( true , true , true , true )
GLES30. glDepthMask ( true )
GLES30. glStencilFunc ( GLES30. GL_EQUAL, 1 , 0xFF )
GLES30. glStencilOp ( GLES30. GL_KEEP, GLES30. GL_KEEP, GLES30. GL_KEEP)
GLES30. drawXX ( )
GLES30. glDisable ( GLES30. GL_STENCIL_TEST)
GLES30. glDisable ( GLES30. GL_DEPTH_TEST)
效果图
原图 原图,绘制某个目标区域