老
孟
一個
有态度
的程式員

立方體有6個面,8個頂點,是以繪制立方體其實就是繪制6個面。
頂點shader:
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使用。
片段shader:
precision mediump float;
uniform vec4 u_color;
varying vec4 v_color;
void main()
{
gl_FragColor = v_color;
}
複制
建立program:
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矩陣。
修改頂點shader如下
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矩陣。
擷取mvpMatrix矩陣句柄
mvpMatrixLoc = GLES20.glGetUniformLocation(mProgramHandle,"mvpMatrix")
複制
設定mvp矩陣
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)
複制
效果如下: