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 ( )
init {
setEGLContextClientVersion ( 3 )
setRenderer ( mRenderer)
renderMode = RENDERMODE_WHEN_DIRTY
}
}
自定义GLSurfaceView.Renderer
代码
class MyGLRenderer : 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 ( )
}
}
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
需要的绘制数据
class DrawData {
private var mProgram : Int = - 1
private var NO_OFFSET = 0
private var VERTEX_POS_DATA_SIZE = 3
private val mMVPMatrix = FloatArray ( 16 )
private val mProjectionMatrix = FloatArray ( 16 )
private val mViewMatrix = FloatArray ( 16 )
private var mViewPortRatio = 1f
val vertex = 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 vertexBuffer = ByteBuffer. allocateDirect ( vertex. size * 4 )
. order ( ByteOrder. nativeOrder ( ) )
. asFloatBuffer ( )
fun initVertexBuffer ( ) {
vertexBuffer. put ( vertex)
vertexBuffer. position ( 0 )
val vbo = IntArray ( 1 )
GLES30. glGenBuffers ( 1 , vbo, 0 )
GLES30. glBindBuffer ( GLES30. GL_ARRAY_BUFFER, vbo[ 0 ] )
GLES30. glBufferData (
GLES30. GL_ARRAY_BUFFER,
vertex. size * 4 ,
vertexBuffer,
GLES30. GL_STATIC_DRAW
)
}
fun initShader ( ) {
val vertexShaderCode = "" "#version 300 es
layout ( location = 0 ) in vec4 aPosition;
uniform mat4 uMVPMatrix;
void main ( ) {
gl_Position = uMVPMatrix * aPosition;
} "" ". trimIndent ( )
val fragmentShaderCode = """#version 300 es
precision mediump float;
uniform vec4 vColor;
out vec4 fragColor;
void main() {
fragColor = vColor;
}""" . 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 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
)
val matrixHandler = GLES30. glGetUniformLocation ( mProgram, "uMVPMatrix" )
GLES30. glUniformMatrix4fv ( matrixHandler, 1 , false , mMVPMatrix, NO_OFFSET)
}
fun drawSomething ( ) {
GLES30. glLineWidth ( 50.0f )
val positionHandle = GLES30. glGetAttribLocation ( mProgram, "aPosition" )
GLES30. glEnableVertexAttribArray ( positionHandle)
GLES30. glVertexAttribPointer ( positionHandle, VERTEX_POS_DATA_SIZE, GLES30. GL_FLOAT, false , 0 , 0 )
val colorHandle = GLES30. glGetUniformLocation ( mProgram, "vColor" )
GLES30. glUniform4f ( colorHandle, 1.0f , 0.5f , 0.5f , 1.0f )
GLES30. glDrawArrays ( GLES30. GL_POINTS, NO_OFFSET, vertex. size / VERTEX_POS_DATA_SIZE)
GLES30. glDisableVertexAttribArray ( positionHandle)
}
}
object LoadShaderUtil{
fun loadShader ( type: Int, source: String) : Int {
val shader = GLES30. glCreateShader ( type)
GLES30. glShaderSource ( shader, source)
GLES30. glCompileShader ( shader)
return shader
}
}
绘制点、线、三角形、正方形、圆
绘制点GLES30.GL_POINTS
val vertex = 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 ,
)
GLES30. glDrawArrays ( GLES30. GL_POINTS, NO_OFFSET, vertex. size / VERTEX_POS_DATA_SIZE)
效果图
绘制线
两个点绘制一条线间隔绘制GLES30.GL_LINES
绘制顺序:将传入的坐标作为单独线条绘制,ABCDEFG
六个顶点,绘制AB、CD、EF
三条线
val vertex = 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 ,
)
GLES30. glLineWidth ( 30f )
GLES30. glDrawArrays ( GLES30. GL_LINES, NO_OFFSET, vertex. size / VERTEX_POS_DATA_SIZE)
效果图
两个点绘制一条线连续绘制GLES30.GL_LINE_STRIP
绘制顺序:将传入的顶点作为折线绘制,ABCD
四个顶点,绘制AB、BC、CD
三条线
val vertex = 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 ,
)
GLES30. glLineWidth ( 30f )
GLES30. glDrawArrays ( GLES30. GL_LINE_STRIP, NO_OFFSET, vertex. size / VERTEX_POS_DATA_SIZE)
效果图
两个点绘制一条线循环绘制GLES30.GL_LINE_LOOP
绘制顺序:将传入的顶点作为闭合折线绘制,ABCD
四个顶点,绘制AB、BC、CD、DA
四条线
val vertex = 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 ,
)
GLES30. glLineWidth ( 30f )
GLES30. glDrawArrays ( GLES30. GL_LINE_LOOP, NO_OFFSET, vertex. size / VERTEX_POS_DATA_SIZE)
效果图
绘制三角形
三个点绘制一条线间隔绘制GLES30.GL_TRIANGLES
绘制顺序:将传入的顶点作为单独的三角形绘制,ABCDEF
绘制ABC,DEF
两个三角形
val vertex = 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 ,
)
GLES30. glDrawArrays ( GLES30. GL_TRIANGLES, NO_OFFSET, vertex. size / VERTEX_POS_DATA_SIZE)
效果图
绘制正方形
三个点绘制一条线连续绘制GLES30.GL_TRIANGLE_STRIP
绘制顺序:将传入的顶点作为三角条带绘制,ABCDEF
绘制ABC,BCD,CDE,DEF
四个三角形
val vertex = 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 ,
)
GLES30. glDrawArrays ( GLES30. GL_TRIANGLE_STRIP, NO_OFFSET, vertex. size / VERTEX_POS_DATA_SIZE)
效果图
绘制圆
三个点绘制一条线连续绘制GLES30.GL_TRIANGLE_FAN
绘制顺序:将传入的顶点作为扇面绘制,ABCDEF
绘制ABC、ACD、ADE、AEF
四个三角形
val vertex = run {
val radius = 0.5f
val segments = 36
val angleStep = ( 2 * PI / segments) . toFloat ( )
val vertices = mutableListOf< Float> ( )
vertices. add ( 0f )
vertices. add ( 0f )
vertices. add ( 0f )
for ( i in 0 .. segments) {
val angle = i * angleStep
vertices. add ( radius * cos ( angle) )
vertices. add ( radius * sin ( angle) )
vertices. add ( 0f )
}
vertices. toFloatArray ( )
}
GLES30. glDrawArrays ( GLES30. GL_TRIANGLE_FAN, NO_OFFSET, vertex. size / VERTEX_POS_DATA_SIZE)
效果图