立方体有6个面,8个顶点,因此绘制立方体其实就是绘制6个面。
attribute vec4 a_Position;
attribute vec4 a_color;
varying vec4 v_color;
void main()
{
v_color = a_color;
gl_Position = a_Position;
}
a_Position为顶点数据,a_color为顶点颜色数据,v_color为varying变量,传递给我片段shader使用。
precision mediump float;
uniform vec4 u_color;
varying vec4 v_color;
void main()
{
gl_FragColor = v_color;
}
private fun createProgram() {
var vertexCode =
AssetsUtils.readAssetsTxt(
context = context,
filePath = "glsl/cube_vs.glsl"
)
var fragmentCode =
AssetsUtils.readAssetsTxt(
context = context,
filePath = "glsl/cube_fs.glsl"
)
mProgramHandle = GLTools.createAndLinkProgram(vertexCode, fragmentCode)
}
cube_vs.cube_fs.glsl分别表示顶点shader和片段shader的文件,存放于assets/glsl目录下,readAssetsTxt为读取assets目录下文件的公用方法。
vPositionLoc = GLES20.glGetAttribLocation(mProgramHandle, "a_Position")
mColorLoc = GLES20.glGetAttribLocation(mProgramHandle, "a_color")
private val r: Float = 0.5f
//顶点坐标
var vertexBuffer = GLTools.array2Buffer(
floatArrayOf(
-r, r, r,//0
-r, -r, r,//1
r, -r, r,//2
r, r, r,//3
r, -r, -r,//4
r, r, -r,//5
-r, -r, -r,//6
-r, r, -r//7
)
)
var mIndices = shortArrayOf(
0, 1, 2, 0, 2, 3,
3, 2, 4, 3, 4, 5,
5, 4, 6, 5, 6, 7,
7, 6, 1, 7, 1, 0,
7, 0, 3, 7, 3, 5,
6, 1, 2, 6, 2, 4
)
val mIndicesBuffer = GLTools.array2Buffer(mIndices)
var colorBuffer = GLTools.array2Buffer(
floatArrayOf(
1f,1f,0f,1f,
1f,1f,0f,1f,
1f,1f,0f,1f,
1f,1f,0f,1f,
1f,0f,0f,1f,
1f,0f,0f,1f,
1f,0f,0f,1f,
1f,0f,0f,1f
)
)
GLES20.glUseProgram(mProgramHandle)
//设置顶点数据
vertexBuffer.position(0)
GLES20.glEnableVertexAttribArray(vPositionLoc)
GLES20.glVertexAttribPointer(vPositionLoc, 3, GLES20.GL_FLOAT, false, 0, vertexBuffer)
//设置颜色数据
colorBuffer.position(0)
GLES20.glEnableVertexAttribArray(mColorLoc)
GLES20.glVertexAttribPointer(mColorLoc, 3, GLES20.GL_FLOAT, false, 0, colorBuffer)
GLES20.glDrawElements(
GLES20.GL_TRIANGLES,
mIndices.size,
GLES20.GL_UNSIGNED_SHORT,
mIndicesBuffer
)
效果图如下:
我们仅仅看到一个矩形,并没有看到立方体啊?实际上我们已经绘制立方体了,只不过其他面被前面的面挡住了导致我们看不到其他面,如何才能看到其他面呢?这时候需要使用mvp矩阵。
attribute vec4 a_Position;
attribute vec4 a_color;
uniform mat4 mvpMatrix;
varying vec4 v_color;
void main()
{
v_color = a_color;
gl_Position = mvpMatrix * a_Position;
}
添加了mvpMatrix矩阵。
mvpMatrixLoc = GLES20.glGetUniformLocation(mProgramHandle,"mvpMatrix")
override fun onSurfaceChanged(p0: GL10?, width: Int, height: Int) {
GLES20.glViewport(0, 0, width, height)
var modelMatrix = FloatArray(16)
Matrix.setIdentityM(modelMatrix, 0)
var viewMatrix = FloatArray(16)
Matrix.setIdentityM(viewMatrix, 0)
Matrix.setLookAtM(viewMatrix, 0,
0F, 5F, 10F,
0F, 0F, 0F,
0F, 1F, 0F)
var projectionMatrix = FloatArray(16)
Matrix.setIdentityM(projectionMatrix, 0)
val ratio = width.toFloat() / height
//设置透视投影
Matrix.frustumM(projectionMatrix, 0, -ratio, ratio, -1f, 1f, 3f, 20f)
var mTempMvMatrix = FloatArray(16)
Matrix.setIdentityM(mTempMvMatrix, 0)
Matrix.multiplyMM(mTempMvMatrix, 0, viewMatrix, 0, modelMatrix, 0)
Matrix.multiplyMM(mMvpMatrix, 0, projectionMatrix, 0, mTempMvMatrix, 0)
}
在onSurfaceChanged中设置矩阵,绘制的时候设置矩阵数据:
GLES20.glUniformMatrix4fv(mvpMatrixLoc, 1, false, mMvpMatrix, 0)
效果如下:
我们发现立方体穿透了,出现这样的效果是因为没有开启深度检测,在绘制前清除深度缓存并开启深度检测,代码如下:
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT or GLES20.GL_DEPTH_BUFFER_BIT)
GLES20.glEnable(GLES20.GL_DEPTH_TEST)
效果如下:
我们将立方体旋转45度,这样就可以看到立方体的侧面了,将模型矩阵旋转45度代码如下:
var modelMatrix = FloatArray(16)
Matrix.setIdentityM(modelMatrix, 0)
Matrix.rotateM(modelMatrix,0,45F,0F,1F,0F)
OpenGL ES for Android 总览
OpenGL ES for Android 环境搭建
OpenGL ES 绘制纹理
OpenGL ES for Android 绘制三角形