在OpenGL ES環境中,投影和相機視角允許你以接近人眼觀察物體類似的效果來繪製圖形,這種類似物理視角的效果通過物體座標系的數學變換來實現.
投影-這種變換通過調整基於GLSurfaceView的寬高的繪製對象的座標.如果沒有計算和變換,通過OpenGL ES繪製的對象因爲與視圖窗口比例不同而發生變形.當OpenGL視圖被創建或者在OnSurfaceChanged()被renderer調用而改變時,投影變換會被計算.更多關於OpenGL ES 投影和座標映射關係的資料,請看: Mapping coordinates for drawn objects.
相機視角-這種變換通過一個虛擬的相機位置來調整繪製物體的座標.需要重點指出是OpenGL ES 並沒有提供一個真正的相機對象,而是通過提供公共方法通過變換繪製對象來提供類似相機的模擬效果.相機視角變換只會在GLSurfaceView創建的時候計算一次,或者因爲用戶動作或者程序功能而動態 的改變.
這一課講解了如何創建投影和相機視角並把他們應用到GLSurfaceView中的圖形中去.
定義投影
投影變換的數據是在GLSurfaceView.Renderer類的OnSurfaceChanged()方法中被計算出來的.下面的示例代碼使用GLSurfaceView的寬和高,並通過調用Matrix.frustumM()方法填充投影變換矩陣:
// mMVPMatrix is an abbreviation for "Model View Projection Matrix"
private final float[] mMVPMatrix = new float[16];
private final float[] mProjectionMatrix = new float[16];
private final float[] mViewMatrix = new float[16];
@Override
public void onSurfaceChanged(GL10 unused, int width, int height) {
GLES20.glViewport(0, 0, width, height);
float ratio = (float) width / height;
// this projection matrix is applied to object coordinates
// in the onDrawFrame() method
Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
}
這段代碼填充了一個投影矩陣, mProjectionMatrix 能夠與相機視角變換組合,這個知識點會在下一課中講解.
注意:僅僅只是對繪製對象應用投影變換的結果是什麼也展示不了,通常,爲了在屏幕上顯示任何圖形,你還必須應用相機視角變換.
定義相機視角
完成給繪製對象添加相機視角變換的過程只是在renderer中繪製流程的一部分.在下面的代碼示例中,通過使用Matrix.setLookAtM()來計算相機視角變換,然後將它與之前的投影矩陣組合起來,組合起來的變換矩陣被傳遞給繪製圖形:
@Override
public void onDrawFrame(GL10 unused) {
...
// Set the camera position (View matrix)
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
// Calculate the projection and view transformation
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
// Draw shape
mTriangle.draw(mMVPMatrix);
}
爲了使用上面的投影矩陣和相機視角變換組合的矩陣,首先:把matrix變量添加到之前定義 Triangle中的頂點着色器:
public class Triangle {
private final String vertexShaderCode =
// This matrix member variable provides a hook to manipulate
// the coordinates of the objects that use this vertex shader
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"void main() {" +
// the matrix must be included as a modifier of gl_Position
// Note that the uMVPMatrix factor *must be first* in order
// for the matrix multiplication product to be correct.
" gl_Position = uMVPMatrix * vPosition;" +
"}";
// Use to access and set the view transformation
private int mMVPMatrixHandle;
...
}
接下來,修改 draw()方法中圖圖形對象,接受組合的變換矩陣並應用到圖形上:
public void draw(float[] mvpMatrix) { // pass in the calculated transformation matrix
...
// get handle to shape's transformation matrix
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
// Pass the projection and view transformation to the shader
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
// Draw the triangle
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
一旦你正確計算並應用投影和相機視角變換,你的圖形會按正確的比例繪製,看起來像這樣:
現在,你的應用已經能能按正確比例展示圖形,是時候給你的圖形動起來!
下一篇:OpenGL ES|添加動畫