// C function void glDrawArrays ( GLenum mode, GLint first, GLsizei count ) public static native void glDrawArrays( int mode, int first, int count );
mode:可以有如下选项
public static final int GL_POINTS = 0x0000;//点
public static final int GL_LINES = 0x0001;//线
public static final int GL_LINE_LOOP = 0x0002;//线段
public static final int GL_LINE_STRIP = 0x0003;
public static final int GL_TRIANGLES = 0x0004;
public static final int GL_TRIANGLE_STRIP = 0x0005;
public static final int GL_TRIANGLE_FAN = 0x0006;
first:从数组第几个开始
count:绘制的点数。
下面逐一实验这些mode
一、GL_POINTS
package com.tian.studyopengles.points import android.opengl.GLES20 import android.opengl.GLSurfaceView import com.tian.studyopengles.utils.GL2Utils import javax.microedition.khronos.egl.EGLConfig import javax.microedition.khronos.opengles.GL10 class OnePointsRender : GLSurfaceView.Renderer { private val V_SHADER_SOURCE = "" + "void main(){\n" + "gl_Position = vec4(0.0,0.0,0.0,1.0);\n" + "gl_PointSize = 10.0;\n" + "}" private val F_SHADER_SOURCE = "" + "void main(){\n" + "gl_FragColor = vec4(1.0,0.0,0.0,1.0);" + "}" private var mProgram: Int = -1 override fun onDrawFrame(gl: GL10?) { GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f) GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT) GLES20.glDrawArrays(GLES20.GL_POINTS, 0, 1) } override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) { GLES20.glViewport(0, 0, width, height) } override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) { GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f) mProgram = GL2Utils.createProgram(V_SHADER_SOURCE, F_SHADER_SOURCE) GLES20.glUseProgram(mProgram) } }
这是最简单的,绘制一个固定的点。
如何绘制多个点?
package com.tian.studyopengles.points import android.opengl.GLES20 import android.opengl.GLSurfaceView import com.tian.studyopengles.utils.GL2Utils import com.tian.studyopengles.utils.LogUtils import java.nio.ByteBuffer import java.nio.ByteOrder import javax.microedition.khronos.egl.EGLConfig import javax.microedition.khronos.opengles.GL10 class MultiplePointsRender : GLSurfaceView.Renderer { private val V_SHADER_SOURCE = "" + "attribute vec4 a_Position;\n" + "void main(){\n" + "gl_Position = a_Position;\n" + "gl_PointSize = 20.0;\n" + "}" private val F_SHADER_SOURCE = "" + "void main(){\n" + "gl_FragColor = vec4(1.0,0.0,0.0,1.0);\n" + "}" private val vertexPoints = floatArrayOf( 0.0f, 0.0f, -0.5f, -0.5f, 0.5f, 0.5f ) private var mProgram: Int = -1 override fun onDrawFrame(gl: GL10?) { GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f) GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT) GLES20.glDrawArrays(GLES20.GL_POINTS, 0, 3) } override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) { GLES20.glViewport(0, 0, width, height) } override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) { mProgram = GL2Utils.createProgram(V_SHADER_SOURCE, F_SHADER_SOURCE) val buffer = ByteBuffer.allocateDirect(vertexPoints.size * 4) .order(ByteOrder.nativeOrder()) .asFloatBuffer() .put(vertexPoints) .position(0) val position = GLES20.glGetAttribLocation(mProgram, "a_Position") GLES20.glVertexAttribPointer(position, 2, GLES20.GL_FLOAT, false, 0, buffer) GLES20.glEnableVertexAttribArray(position) GLES20.glValidateProgram(mProgram) val statusArray = IntArray(1) GLES20.glGetProgramiv(mProgram, GLES20.GL_VALIDATE_STATUS, statusArray, 0) val statusInfo = GLES20.glGetProgramInfoLog(mProgram) LogUtils.i("status code == ${statusArray[0]},status info == $statusInfo") GLES20.glUseProgram(mProgram) } }
注意的点:1、shader不要写错,代码里面有工具方法,可以监测出是否出错。
2、因为是平面绘制,只用了(x,y)表示坐标,shader里面定义的是vec4 表示四个向量,此次表示默认第三和第四是(0.0,1.0)。
GLES20.glVertexAttribPointer(position, 2, GLES20.GL_FLOAT, false, 0, buffer)中的2,表示是几个数据来表示一个顶点坐标。此处是(x,y)则所以是2
3、这三行,铁三角,先定位、再赋值、最后激活。
val position = GLES20.glGetAttribLocation(mProgram, "a_Position") GLES20.glVertexAttribPointer(position, 2, GLES20.GL_FLOAT, false, 0, buffer) GLES20.glEnableVertexAttribArray(position)
二、线段
2.1)、GLES20.GL_LINES
package com.tian.studyopengles.lines import android.opengl.GLES20 import android.opengl.GLSurfaceView import com.tian.studyopengles.utils.GL2Utils import java.nio.ByteBuffer import java.nio.ByteOrder import javax.microedition.khronos.egl.EGLConfig import javax.microedition.khronos.opengles.GL10 class LineRender : GLSurfaceView.Renderer { private val V_SHADER_SOURCR = "" + "attribute vec4 a_Position;\n" + "void main(){;\n" + "gl_Position = a_Position;\n" + "gl_PointSize = 10.0;\n" + "}" private val F_SHADER_SOURCE = "" + "void main(){\n" + "gl_FragColor = vec4(1.0,0.0,0.0,1.0);\n" + "}" private var mProgram: Int = -1 private val vertexPoints = floatArrayOf( 0.5f, 0.5f, -0.5f, -0.5f, 0.1f,0.0f, 0.5f,0.0f) override fun onDrawFrame(gl: GL10?) { GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f) GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT) GLES20.glDrawArrays(GLES20.GL_LINE_STRIP, 0, 4) } override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) { GLES20.glViewport(0, 0, width, height) } override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) { mProgram = GL2Utils.createProgram(V_SHADER_SOURCR,F_SHADER_SOURCE) var buffer = ByteBuffer.allocateDirect(vertexPoints.size * 4) .order(ByteOrder.nativeOrder()) .asFloatBuffer() .put(vertexPoints) .position(0) var position = GLES20.glGetAttribLocation(mProgram,"a_Position") GLES20.glVertexAttribPointer(position,2,GLES20.GL_FLOAT,false,0,buffer) GLES20.glEnableVertexAttribArray(position) GL2Utils.validateProgram(mProgram) GLES20.glUseProgram(mProgram) } }
很简单,两个点确定一个线段。数组中v0和v1构成一条线段,v2和v3构成线段,不是共用一个点
2.2)、GLES20.GL_LINE_LOOP
loop顾名思义是一个环。v0和v1,一条线段,v1和v2一条线段,v2和v3一条线段,v3和v0一条线段。每个点使用两次,收尾连接。只要大于等于三个点,就必然是一个封闭的图形。
2.3)、GLES20.GL_LINE_STRIP
和GLES20.GL_LINE_LOOP相比,就少了收尾相连这条线段,不再是封闭的图像。
三、三角形
3.1)、GLES20.GL_TRIANGLES
三个点,构成一个三角形,v0,v1,v2构成一个,v3,v4,v5表示第二个,很好理解
package com.tian.studyopengles.triangle
import android.opengl.GLES20
import android.opengl.GLSurfaceView
import com.tian.studyopengles.utils.GL2Utils
import java.nio.ByteBuffer
import java.nio.ByteOrder
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10
class TriangleRender : GLSurfaceView.Renderer {
private val V_SHADER_SOURCE = "" +
"attribute vec4 a_Position;\n" +
"void main(){\n" +
"gl_Position = a_Position;\n" +
"gl_PointSize = 10.0;\n" +//设为10.0,便于查看
"}"
private val F_SHADER_SOURCR = "" +
"void main(){\n" +
"gl_FragColor = vec4(1.0,0.0,0.0,1.0);\n" +
"}"
private var mProgram: Int = -1
private val vertexPoints = floatArrayOf(
0.0f, 0.0f,
0.5f, 0.0f,
0.5f, 0.3f,
-0.1f, 0.0f,
-0.5f, 0.0f,
-0.5f, -0.3f
)
override fun onDrawFrame(gl: GL10?) {
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f)
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6)
}
override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
GLES20.glViewport(0, 0, width, height)
}
override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
mProgram = GL2Utils.createProgram(V_SHADER_SOURCE, F_SHADER_SOURCR)
val buffer = ByteBuffer.allocateDirect(vertexPoints.size * 4)
.order(ByteOrder.nativeOrder())
.asFloatBuffer()
.put(vertexPoints)
.position(0)
var position = GLES20.glGetAttribLocation(mProgram, "a_Position")
GLES20.glEnableVertexAttribArray(position)
GLES20.glVertexAttribPointer(position, 2, GLES20.GL_FLOAT, false, 0, buffer)
GL2Utils.validateProgram(mProgram)
GLES20.glUseProgram(mProgram)
}
}
3.2)、GLES20.GL_TRIANGLE_FAN
直接把3.1中GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6)换成GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, 6)看下效果,得到如下图:
,查资料,这个方法,是以第一个点为公共顶点。v0,v1,v2构成一个三角形,v0,v2,v3构成一个三角形,v0,v3,v4构成一个三角形,v0,v4,v5构成一个三角形
为了更直观,调整顶点坐标。
private val vertexPoints = floatArrayOf( 0.0f, 0.0f, 0.5f, 0.0f, 0.4f, 0.1f, 0.3f, 0.15f, 0.2f, 0.175f, 0.1f, 0.18f )
得到下面图像。
3.3)GLES20.GL_TRIANGLE_STRIP
还是使用原先的坐标,换成GLES20.GL_TRIANGLE_STRIP 直接变成下面图形。
private val vertexPoints = floatArrayOf( 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 0.3f, -0.1f, 0.0f, -0.5f, 0.0f, -0.5f, -0.3f )
结合线段中的理解,是不是就是两个三角形共用顶点意思,没有全部三角形共用v0的效果了?
为了验证,调整顶点坐标。
private val vertexPoints = floatArrayOf(
0.0f, 0.0f,
0.25f, 0.25f,
0.25f, -0.25f,
0.5f, 0.0f
)
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4)这个个地方改成四个点
验证,的确如上面分析一样。
总结
线段:
GL_LINES ,两个顶点确定一个线段
GL_LINE_STRIP:除了收尾两个顶点,其余的点,都会使用两次,得到的是全部连在一起的线段
GL_LINE_LOOP:是所有顶点都使用两次,到达尾部的时候,会连接起点,形成一个封闭的图形
三角形:
GL_TRIANGLES:三个顶点,确定一个三角形
GL_TRIANGLE_STRIP:除了开始和最后的三角形,中间的三角形,都会共用两个顶点。
GL_TRIANGLE_FAN:也是共用两个顶点,但是有一个更特殊的点,是全部三角形,都会共用。
后面两种完全可以使用增加一些顶点,实现同一效果。该参数,完全是方便绘制特定图形,进行封装的。