XML文件
<?xml version="1.0" encoding="utf-8"?>
< com.example.myapplication.MyGLSurfaceViewxmlns: android = " http://schemas.android .com/apk/res/android " android : layout_width= " match_parent" android : layout_height= " match_parent" />
自定义GLSurfaceView
代码
kotlin">class MyGLSurfaceView ( context: Context, attrs: AttributeSet) : GLSurfaceView ( context, attrs) { private var mRenderer = MyGLRenderer ( context) init { setEGLContextClientVersion ( 3 ) setRenderer ( mRenderer) renderMode = RENDERMODE_WHEN_DIRTY}
}
自定义GLSurfaceView.Renderer
代码
kotlin">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 { initVertexBuffer ( ) initShader ( ) loadTexture ( mContext, R. drawable. bitmap_shader) } } override fun onSurfaceChanged ( gl: GL10? , width: Int, height: Int) { GLES30. glViewport ( 0 , 0 , width, height) mDrawData? . computeMVPMatrix ( width. toFloat ( ) , height. toFloat ( ) ) } override fun onDrawFrame ( gl: GL10? ) { GLES30. glClear ( GLES30. GL_COLOR_BUFFER_BIT) mDrawData? . drawSomething ( ) }
}
GLSurfaceView.Renderer
需要的绘制数据
kotlin">class DrawData { private var mProgram : Int = - 1 private var NO_OFFSET = 0 private val VERTEX_POS_DATA_SIZE = 3 private val TEXTURE_POS_DATA_SIZE = 2 private var mTextureID = IntArray ( 1 ) private var mVertexVBO = 0 private var mTexCoordVBO = 0 private val mMVPMatrix = FloatArray ( 16 ) private val mProjectionMatrix = FloatArray ( 16 ) private val mViewMatrix = FloatArray ( 16 ) private var mViewPortRatio = 1f 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 ( ) 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 ( ) fun initVertexBuffer ( ) { vertexBuffer. put ( vertex) vertexBuffer. position ( NO_OFFSET) textureBuffer. put ( textureCoords) textureBuffer. position ( NO_OFFSET) val vbo = IntArray ( 2 ) GLES30. glGenBuffers ( vbo. size, vbo, NO_OFFSET) GLES30. glBindBuffer ( GLES30. GL_ARRAY_BUFFER, vbo[ 0 ] ) GLES30. glBufferData ( GLES30. GL_ARRAY_BUFFER, vertex. size * 4 , vertexBuffer, GLES30. GL_STATIC_DRAW) GLES30. glBindBuffer ( GLES30. GL_ARRAY_BUFFER, vbo[ 1 ] ) GLES30. glBufferData ( GLES30. GL_ARRAY_BUFFER, textureCoords. size * 4 , textureBuffer, GLES30. GL_STATIC_DRAW) mVertexVBO = vbo[ 0 ] mTexCoordVBO = vbo[ 1 ] } fun initShader ( ) { val vertexShaderCode = "" "#version 300 esin vec4 aPosition; uniform mat4 uMVPMatrix; in vec2 aTexCoord; out vec2 vTexCoord; void main ( ) { gl_Position = uMVPMatrix * aPosition; vTexCoord = aTexCoord; } "" ". trimIndent ( ) val fragmentShaderCode = "" "#version 300 esprecision mediump float; out vec4 fragColor; in vec2 vTexCoord; uniform sampler2D uTexture; void main ( ) { fragColor = texture ( uTexture, 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) } fun loadTexture ( context: Context, resourceId: Int) { GLES30. glGenTextures ( mTextureID. size, mTextureID, NO_OFFSET) GLES30. glBindTexture ( GLES30. GL_TEXTURE_2D, mTextureID[ 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, NO_OFFSET, bitmap, NO_OFFSET) bitmap. recycle ( ) GLES30. glBindTexture ( GLES30. GL_TEXTURE_2D, NO_OFFSET) } fun computeMVPMatrix ( width: Float, height: Float) { takeIf { width > height } ? . let { mViewPortRatio = width / heightMatrix. orthoM ( mProjectionMatrix, NO_OFFSET, - mViewPortRatio, mViewPortRatio, - 1f , 1f , 0f , 1f ) } ?: run { mViewPortRatio = height / 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 , ) val matrixHandler = GLES30. glGetUniformLocation ( mProgram, "uMVPMatrix" ) GLES30. glUniformMatrix4fv ( matrixHandler, 1 , false , mMVPMatrix, NO_OFFSET) } fun drawSomething ( ) { GLES30. glActiveTexture ( GLES30. GL_TEXTURE0) GLES30. glBindTexture ( GLES30. GL_TEXTURE_2D, mTextureID[ 0 ] ) val textureSampleHandle = GLES30. glGetUniformLocation ( mProgram, "uTexture" ) GLES30. glUniform1i ( textureSampleHandle, NO_OFFSET) val matrixHandle = GLES30. glGetUniformLocation ( mProgram, "uMVPMatrix" ) GLES30. glUniformMatrix4fv ( matrixHandle, 1 , false , mMVPMatrix, NO_OFFSET) val positionHandle = GLES30. glGetAttribLocation ( mProgram, "aPosition" ) GLES30. glEnableVertexAttribArray ( positionHandle) GLES30. glBindBuffer ( GLES30. GL_ARRAY_BUFFER, mVertexVBO) GLES30. glVertexAttribPointer ( positionHandle, VERTEX_POS_DATA_SIZE, GLES30. GL_FLOAT, false , 0 , NO_OFFSET) val textureHandle = GLES30. glGetAttribLocation ( mProgram, "aTexCoord" ) GLES30. glEnableVertexAttribArray ( textureHandle) GLES30. glBindBuffer ( GLES30. GL_ARRAY_BUFFER, mTexCoordVBO) GLES30. glVertexAttribPointer ( textureHandle, TEXTURE_POS_DATA_SIZE, GLES30. GL_FLOAT, false , 0 , NO_OFFSET) GLES30. glDrawArrays ( GLES30. GL_TRIANGLE_STRIP, NO_OFFSET, vertex. size / VERTEX_POS_DATA_SIZE) GLES30. glDisableVertexAttribArray ( positionHandle) GLES30. glDisableVertexAttribArray ( textureHandle) }
} object LoadShaderUtil{ fun loadShader ( type: Int, source: String) : Int { val shader = GLES30. glCreateShader ( type) GLES30. glShaderSource ( shader, source) GLES30. glCompileShader ( shader) return shader}
}
效果图