贴图
XML文件
<?xml version="1.0" encoding="utf-8"?>
< com.example.myapplication.MyGLSurfaceView
xmlns: 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 {
initVertexBuffer ( )
initShader ( )
mTextureID[ 0 ] = 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? . enableTexture ( )
mDrawData? . drawSomething ( )
}
}
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 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
var mTextureID = IntArray ( 1 )
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 es
uniform mat4 uMVPMatrix;
in vec4 aPosition;
in vec2 aTexCoord;
out vec2 vTexCoord;
void main ( ) {
gl_Position = uMVPMatrix * aPosition;
vTexCoord = aTexCoord;
} "" ". trimIndent ( )
val fragmentShaderCode = "" "#version 300 es
precision mediump float;
uniform sampler2D uTexture;
in vec2 vTexCoord;
out vec4 fragColor;
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)
GLES30. glDeleteShader ( vertexShader)
GLES30. glDeleteShader ( fragmentShader)
}
fun computeMVPMatrix ( width: Float, height: Float) {
takeIf { width > height } ? . let {
mViewPortRatio = width / height
Matrix. orthoM (
mProjectionMatrix,
NO_OFFSET,
- mViewPortRatio,
mViewPortRatio,
- 1f ,
1f ,
0f ,
1f
)
} ?: run {
mViewPortRatio = height / width
Matrix. 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)
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)
}
fun enableTexture ( ) {
GLES30. glActiveTexture ( GLES30. GL_TEXTURE0)
GLES30. glBindTexture ( GLES30. GL_TEXTURE_2D, mTextureID[ 0 ] )
val textureSampleHandle = GLES30. glGetUniformLocation ( mProgram, "uTexture" )
GLES30. glUniform1i ( textureSampleHandle, 0 )
}
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
}
}
}
效果图