OpenGL 矩形
在前面的三角形的基礎上繪製矩形就簡單很多了,改下頂點座標就可以繪製出來,這裡有兩種繪製方式。
第一種繪製方式
class RectangleRender : GLSurfaceView.Renderer { private val vao = IntArray(1) private val vbo = IntArray(1) private val ebo = IntArray(1) private var esShader = Shader() private var 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// 左上角 ) private var indices = shortArrayOf( 0, 1, 3, // 第一個三角形 1, 2, 3// 第二個三角形 ) override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) { GLES30.glClearColor(0.2f, 0.3f, 0.3f, 1.0f) //vao GLES30.glGenVertexArrays(1, vao, 0) GLES30.glBindVertexArray(vao[0]) //vbo GLES30.glGenBuffers(1, vbo, 0) GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vbo[0]) val vertexBuffer = DataUtil.createByteBuffer(vertices) //複製資料到opengl GLES30.glBufferData( //頂點緩衝物件當前繫結到GL_ARRAY_BUFFER目標上 GLES30.GL_ARRAY_BUFFER, //指定傳輸資料的大小(以位元組為單位) vertices.size * DataUtil.sizeof(GLES30.GL_FLOAT), //傳送的實際資料 vertexBuffer, //GL_STATIC_DRAW :資料不會或幾乎不會改變。 //GL_DYNAMIC_DRAW:資料會被改變很多。 //GL_STREAM_DRAW :資料每次繪製時都會改變 GLES30.GL_STATIC_DRAW ) //設定頂點陣列指標 GLES30.glVertexAttribPointer( //shader中 layout(location = 0)的值 0, //頂點屬性的大小。頂點屬性是一個vec3,它由3個值組成,所以大小是3 3, //資料的型別 GLES30.GL_FLOAT, //GL_TRUE,資料被標準化,所有資料都會被對映到0(對於有符號型signed資料是-1)到1之間。我們把它設定為GL_FALSE false, //步長,它告訴我們在連續的頂點屬性組之間的間隔 位元組單位 3 * DataUtil.sizeof(GLES30.GL_FLOAT), //資料偏移量 這裡只有頂點 位置資料在陣列的開頭,所以這裡是0 0 ) GLES30.glEnableVertexAttribArray(0) //vbo end //vao end //ebo start GLES30.glGenBuffers(1, ebo, 0) GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, ebo[0]) val indexBuffer = DataUtil.createByteBuffer(indices) //複製資料到opengl GLES30.glBufferData( //頂點緩衝物件當前繫結到GL_ELEMENT_ARRAY_BUFFER目標上 GLES30.GL_ELEMENT_ARRAY_BUFFER, //指定傳輸資料的大小(以位元組為單位) indices.size * DataUtil.sizeof(GLES30.GL_SHORT), //傳送的實際資料 indexBuffer, //GL_STATIC_DRAW :資料不會或幾乎不會改變。 //GL_DYNAMIC_DRAW:資料會被改變很多。 //GL_STREAM_DRAW :資料每次繪製時都會改變 GLES30.GL_STATIC_DRAW ) //ebo end //shader esShader.loadProgramFromAsset(MyApp.context, "triangle_vert.glsl", "triangle_frag.glsl") } override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) { GLES30.glViewport(0, 0, width, height) } override fun onDrawFrame(gl: GL10?) { GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT) esShader.use() GLES30.glBindVertexArray(vao[0]) GLES30.glDrawElements( //圖元的型別 GLES30.GL_TRIANGLES, //定點個數 6, //定點資料型別 GLES30.GL_UNSIGNED_SHORT, //頂點偏移量 0 ) } }
這裡跟繪製三角形有區別的地方是使用了索引來繪製,建立索引跟建立vbo是一樣的。看程式碼裡面的註釋。
繪製時使用
GLES30.glDrawElements( //圖元的型別 GLES30.GL_TRIANGLES, //定點個數 6, //定點資料型別 GLES30.GL_UNSIGNED_SHORT, //頂點偏移量 0 )
這樣可以節省頂點資料。
第二種繪製方式
這種就是定義6個頂點,繪製兩個三角形
class RectangleRender2 : GLSurfaceView.Renderer { private val vao = IntArray(1) private val vbo = IntArray(1) private var esShader = Shader() private var vertices = floatArrayOf( -0.5f, 0.5f, 0.0f, -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f, // second triangle -0.5f, 0.5f, 0.0f, 0.5f, 0.5f, 0.0f, 0.5f, -0.5f, 0.0f ) override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) { GLES30.glClearColor(0.2f, 0.3f, 0.3f, 1.0f) //vao GLES30.glGenVertexArrays(1, vao, 0) GLES30.glBindVertexArray(vao[0]) //vbo GLES30.glGenBuffers(1, vbo, 0) GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vbo[0]) val vertexBuffer = DataUtil.createByteBuffer(vertices) //複製資料到opengl GLES30.glBufferData( //頂點緩衝物件當前繫結到GL_ARRAY_BUFFER目標上 GLES30.GL_ARRAY_BUFFER, //指定傳輸資料的大小(以位元組為單位) vertices.size * DataUtil.sizeof(GLES30.GL_FLOAT), //傳送的實際資料 vertexBuffer, //GL_STATIC_DRAW :資料不會或幾乎不會改變。 //GL_DYNAMIC_DRAW:資料會被改變很多。 //GL_STREAM_DRAW :資料每次繪製時都會改變 GLES30.GL_STATIC_DRAW ) //設定頂點陣列指標 GLES30.glVertexAttribPointer( //shader中 layout(location = 0)的值 0, //頂點屬性的大小。頂點屬性是一個vec3,它由3個值組成,所以大小是3 3, //資料的型別 GLES30.GL_FLOAT, //GL_TRUE,資料被標準化,所有資料都會被對映到0(對於有符號型signed資料是-1)到1之間。我們把它設定為GL_FALSE false, //步長,它告訴我們在連續的頂點屬性組之間的間隔 位元組單位 3 * DataUtil.sizeof(GLES30.GL_FLOAT), //資料偏移量 這裡只有頂點 位置資料在陣列的開頭,所以這裡是0 0 ) GLES30.glEnableVertexAttribArray(0) //vbo end //vao end //shader esShader.loadProgramFromAsset(MyApp.context, "triangle_vert.glsl", "triangle_frag.glsl") } override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) { GLES30.glViewport(0, 0, width, height) } override fun onDrawFrame(gl: GL10?) { GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT) esShader.use() GLES30.glBindVertexArray(vao[0]) GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, 6) } }
程式碼比較簡單、也有註釋,就這樣了。