OpenGL ES環(huán)境允許你以更接近于你眼睛看到的物理對象的方式來顯示你繪制的對象勺爱。物理查看的模擬是通過對你所繪制的對象的坐標(biāo)進(jìn)行數(shù)學(xué)變換完成的:
- Projection(投影) — 這個變換是基于他們所顯示的GLSurfaceView的寬和高來調(diào)整繪制對象的坐標(biāo)的甲献。沒有這個計算變換,通過OpenGL繪制的形狀會在不同顯示窗口變形痊剖。這個投影變化通常只會在OpenGL view的比例被確定或者在你渲染器的onSurfaceChanged()方法中被計算。想要了解更多的關(guān)于投影和坐標(biāo)映射的相關(guān)信息垒玲,請看繪制對象的坐標(biāo)映射陆馁。
- Camera View — 這個換是基于虛擬的相機的位置來調(diào)整繪制對象坐標(biāo)的。需要著重注意的是合愈,OpenGL ES并沒有定義一個真實的相機對象叮贩,而是提供一個實用方法,通過變換繪制對象的顯示來模擬一個相機佛析。相機視圖變換可能只會在你的GLSurfaceView被確定時被計算益老,或者基于用戶操作或你應(yīng)用程序的功能來動態(tài)改變。
1 定義投影
投影變化的數(shù)據(jù)是在你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储狭,mProjectionMatrix可以在onFrameDraw()方法中與下一部分的相機視圖結(jié)合在一起互婿。
注意:如果僅僅只把投影矩陣應(yīng)用的到你繪制的對象中,通常你只會得到一個非沉杀罚空的顯示。一般情況下呛牲,你還必須為你要在屏幕上顯示的任何內(nèi)容應(yīng)用相機視圖刮萌。
2 定義相機視圖
通過在你的渲染器中添加相機視圖變換作為你繪制過程的一部分來完成你的繪制圖像的變換過程。在下面的代碼中娘扩,通過Matrix.setLookAtM()方法計算相機視圖變換着茸,然后將其與之前計算出的投影矩陣結(jié)合到一起。合并后的矩陣接下來會傳遞給繪制的圖形琐旁。
@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);
}
3 應(yīng)用投影和相機變換
為了使用在上一部分內(nèi)容中展示的投影和相機視圖變換的合并矩陣涮阔,首先要在之前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()方法來接收聯(lián)合變換矩陣灰殴,并將它們應(yīng)用到圖形中:
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);
}
一旦你正確的計算并應(yīng)用投影和相機視圖變換敬特,你的繪圖對象將會以正確的比例繪制,它看起來應(yīng)該像下面這樣:
現(xiàn)在你已經(jīng)有一個可以以正確比例顯示圖形的應(yīng)用了牺陶。后面的章節(jié)伟阔,我們可以了解如何為你的圖形添加運動了。
源碼地址:https://github.com/Xiaoben336/OpenGLES20Study