贴图
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
代码
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
代码
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 { initShader ( ) initVertexBuffer ( ) initTexture0 ( 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? . enableTexture ( ) mDrawData? . drawSomething ( ) mDrawData? . disableTexture ( ) }
}
GLSurfaceView.Renderer
需要的绘制数据
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 mVBO = IntArray ( 2 ) private val mMVPMatrix = FloatArray ( 16 ) private val mProjectionMatrix = FloatArray ( 16 ) private val mViewMatrix = FloatArray ( 16 ) private var mViewPortRatio = 1f var mTextureID = IntArray ( 2 ) 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 ( 0 ) 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) 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;uniform sampler2D uTexture_1;in vec2 vTexCoord;out vec4 fragColor;void main() {fragColor = texture(uTexture_0, vTexCoord) + texture(uTexture_1, 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. 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) 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) GLES30. glBindBuffer ( GLES30. GL_ARRAY_BUFFER, 0 ) } 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 , ) } fun drawSomething ( ) { val matrixHandle = GLES30. glGetUniformLocation ( mProgram, "uMVPMatrix" ) GLES30. glUniformMatrix4fv ( matrixHandle, 1 , false , mMVPMatrix, NO_OFFSET) GLES30. glBindBuffer ( GLES30. GL_ARRAY_BUFFER, mVBO[ 0 ] ) 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, mVBO[ 1 ] ) val textureHandle = GLES30. glGetAttribLocation ( mProgram, "aTexCoord" ) GLES30. glEnableVertexAttribArray ( textureHandle) 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) GLES30. glBindBuffer ( GLES30. GL_ARRAY_BUFFER, 0 ) } fun enableTexture ( ) { GLES30. glActiveTexture ( GLES30. GL_TEXTURE0) GLES30. glBindTexture ( GLES30. GL_TEXTURE_2D, mTextureID[ 0 ] ) val textureSampleHandle = GLES30. glGetUniformLocation ( mProgram, "uTexture_0" ) GLES30. glUniform1i ( textureSampleHandle, 0 ) GLES30. glActiveTexture ( GLES30. GL_TEXTURE1) GLES30. glBindTexture ( GLES30. GL_TEXTURE_2D, mTextureID[ 1 ] ) val textureSampleHandle1 = GLES30. glGetUniformLocation ( mProgram, "uTexture_1" ) GLES30. glUniform1i ( textureSampleHandle1, 1 ) } fun disableTexture ( ) { GLES30. glBindTexture ( GLES30. GL_TEXTURE_2D, 0 ) } fun initTexture0 ( context: Context, resourceId: Int) { mTextureID[ 0 ] = loadTexture ( context, resourceId) } 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 ) return textureId[ 0 ] } object LoadShaderUtil { fun loadShader ( type: Int, source: String) : Int { val shader = GLES30. glCreateShader ( type) GLES30. glShaderSource ( shader, source) GLES30. glCompileShader ( shader) return shader} }
}
效果图