Android OpenGL ES 開發(五): OpenGL ES 使用投影和相機視圖


OpenGL ES環境允許你以更接近於你眼睛看到的物理對象的方式來顯示你繪制的對象。物理查看的模擬是通過對你所繪制的對象的坐標進行數學變換完成的:

  • Projection — 這個變換是基於他們所顯示的GLSurfaceView的寬和高來調整繪制對象的坐標的。沒有這個計算變換,通過OpenGL繪制的形狀會在不同顯示窗口變形。這個投影變化通常只會在OpenGL view的比例被確定或者在你渲染器的onSurfaceChanged()方法中被計算。想要了解更多的關於投影和坐標映射的相關信息,請看繪制對象的坐標映射。
  • Camera View — 這個換是基於虛擬的相機的位置來調整繪制對象坐標的。需要着重注意的是,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,mProjectionMatrix可以在onFrameDraw()方法中與下一部分的相機視圖結合在一起。

注意:如果僅僅只把投影矩陣應用的到你繪制的對象中,通常你只會得到一個非常空的顯示。一般情況下,你還必須為你要在屏幕上顯示的任何內容應用相機視圖。

定義相機視圖

通過在你的渲染器中添加相機視圖變換作為你繪制過程的一部分來完成你的繪制圖像的變換過程。在下面的代碼中,通過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);
}

應用投影和相機變換

為了使用在上一部分內容中展示的投影和相機視圖變換的合並矩陣,首先要在之前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);
}

一旦你正確的計算並應用投影和相機視圖變換,你的繪圖對象將會以正確的比例繪制,它看起來應該像下面這樣:

現在你已經有一個可以以正確比例顯示圖形的應用了。后面的章節,我們可以了解如何為你的圖形添加運動了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM