XML文件<?xml version="1.0" encoding="utf-8"?> 
< com.example.myapplication.EGLSurfaceViewxmlns: 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}  ) 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) 
原图 原图,绘制某个目标区域