Android運(yùn)用投影與相機(jī)視角

2018-08-02 18:37 更新

編寫:jdneo - 原文:http://developer.android.com/training/graphics/opengl/projection.html

在OpenGL ES環(huán)境中,利用投影和相機(jī)視角可以讓顯示的繪圖對(duì)象更加酷似于我們用肉眼看到的真實(shí)物體。該物理視角的仿真是對(duì)繪制對(duì)象坐標(biāo)的進(jìn)行數(shù)學(xué)變換實(shí)現(xiàn)的:

  • 投影(Projection):這個(gè)變換會(huì)基于顯示它們的GLSurfaceView的長(zhǎng)和寬,來調(diào)整繪圖對(duì)象的坐標(biāo)。如果沒有該計(jì)算,那么用OpenGL ES繪制的對(duì)象會(huì)由于其長(zhǎng)寬比例和View窗口比例的不一致而發(fā)生形變。一個(gè)投影變換一般僅當(dāng)OpenGL View的比例在渲染器的onSurfaceChanged()方法中建立或發(fā)生變化時(shí)才被計(jì)算。關(guān)于更多OpenGL ES投影和坐標(biāo)映射的知識(shí),可以閱讀Mapping Coordinates for Drawn Objects。
  • 相機(jī)視角(Camera View):這個(gè)變換會(huì)基于一個(gè)虛擬相機(jī)位置改變繪圖對(duì)象的坐標(biāo)。注意到OpenGL ES并沒有定義一個(gè)實(shí)際的相機(jī)對(duì)象,取而代之的,它提供了一些輔助方法,通過對(duì)繪圖對(duì)象的變換來模擬相機(jī)視角。一個(gè)相機(jī)視角變換可能僅在建立你的GLSurfaceView時(shí)計(jì)算一次,也可能根據(jù)用戶的行為或者你的應(yīng)用的功能進(jìn)行動(dòng)態(tài)調(diào)整。

這節(jié)課將解釋如何創(chuàng)建一個(gè)投影和一個(gè)相機(jī)視角,并應(yīng)用它們到GLSurfaceView中的繪制圖像上。

定義一個(gè)投影

投影變換的數(shù)據(jù)會(huì)在GLSurfaceView.Renderer類的onSurfaceChanged()方法中被計(jì)算。下面的代碼首先接收GLSurfaceView的高和寬,然后利用它并使用Matrix.frustumM()方法來填充一個(gè)投影變換矩陣(Projection Transformation Matrix):

// 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);
}

該代碼填充了一個(gè)投影矩陣:mProjectionMatrix,在下一節(jié)中,我們可以在onDrawFrame()方法中將它和一個(gè)相機(jī)視角變換結(jié)合起來。

Note:在繪圖對(duì)象上只應(yīng)用一個(gè)投影變換會(huì)導(dǎo)致顯示效果看上去很空曠。一般而言,我們還要實(shí)現(xiàn)一個(gè)相機(jī)視角,使得所有對(duì)象出現(xiàn)在屏幕上。

定義一個(gè)相機(jī)視角

在渲染器中添加一個(gè)相機(jī)視角變換作為繪圖過程的一部分,以此完成我們的繪圖對(duì)象所需變換的所有步驟。在下面的代碼中,使用Matrix.setLookAtM()方法來計(jì)算相機(jī)視角變換,然后與之前計(jì)算的投影矩陣結(jié)合起來,結(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);
}

應(yīng)用投影和相機(jī)變換

為了使用在之前章節(jié)中結(jié)合了的相機(jī)視角變換和投影變換,我們首先為之前在Triangle類中定義的頂點(diǎn)著色器添加一個(gè)Matrix變量:

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;

    ...
}

之后,修改圖形對(duì)象的draw()方法,使得它接收組合后的變換矩陣,并將它應(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);
}

一旦我們正確地計(jì)算并應(yīng)用了投影變換和相機(jī)視角變換,我們的圖形就會(huì)以正確的比例繪制出來,它看上去會(huì)像是這樣:

ogl-triangle-projected

現(xiàn)在,應(yīng)用已經(jīng)可以通過正確的比例顯示圖形了,下面就為圖形添加一些動(dòng)畫效果吧!


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)