Applicare le proiezioni e le visualizzazioni della videocamera

Nell'ambiente OpenGL ES, le visualizzazioni di proiezione e telecamera consentono di visualizzare gli oggetti disegnati in un che assomiglia di più al modo in cui vedi gli oggetti fisici con gli occhi. Questa simulazione la visualizzazione fisica si effettua mediante trasformazioni matematiche delle coordinate degli oggetti disegnati:

  • Proiezione: questa trasformazione regola le coordinate degli oggetti disegnati in base alla la larghezza e l'altezza degli elementi GLSurfaceView in cui vengono visualizzati. Senza questo calcolo, gli oggetti disegnati da OpenGL ES vengono distorti dalle proporzioni disuguali della vista finestra. Generalmente, una trasformazione di proiezione va calcolata solo quando le proporzioni La visualizzazione OpenGL viene stabilita o modificata nel metodo onSurfaceChanged() del renderer. Per ulteriori informazioni sulle proiezioni OpenGL ES e la mappatura delle coordinate, vedi Mappatura delle coordinate per i oggetti.
  • Vista videocamera - Questa trasformazione regola le coordinate degli oggetti disegnati in base a una posizione della fotocamera virtuale. È importante notare che OpenGL ES non definisce ma fornisce metodi di utilità che simulano una fotocamera trasformando il display oggetti disegnati. Una trasformazione della visualizzazione della videocamera può essere calcolata una sola volta quando stabilisci la GLSurfaceView o potrebbe cambiare dinamicamente in base alle azioni dell'utente o alle tue della funzione dell'applicazione.

Questa lezione descrive come creare una proiezione e un'inquadratura della videocamera e applicarla alle forme disegnate il tuo GLSurfaceView.

Definisci una proiezione

I dati per una trasformazione di proiezione vengono calcolati nel onSurfaceChanged() della tua classe GLSurfaceView.Renderer. Il seguente codice di esempio prende l'altezza e la larghezza di GLSurfaceView e li utilizza per compilare una trasformazione della proiezione Matrix usando il metodo Matrix.frustumM():

Kotlin

// vPMatrix is an abbreviation for "Model View Projection Matrix"
private val vPMatrix = FloatArray(16)
private val projectionMatrix = FloatArray(16)
private val viewMatrix = FloatArray(16)

override fun onSurfaceChanged(unused: GL10, width: Int, height: Int) {
    GLES20.glViewport(0, 0, width, height)

    val ratio: Float = width.toFloat() / height.toFloat()

    // this projection matrix is applied to object coordinates
    // in the onDrawFrame() method
    Matrix.frustumM(projectionMatrix, 0, -ratio, ratio, -1f, 1f, 3f, 7f)
}

Java

// vPMatrix is an abbreviation for "Model View Projection Matrix"
private final float[] vPMatrix = new float[16];
private final float[] projectionMatrix = new float[16];
private final float[] viewMatrix = 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(projectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
}

Questo codice compila una matrice di proiezione, mProjectionMatrix, che puoi poi combinare con una trasformazione della vista della videocamera nel metodo onDrawFrame(), come mostrato nella sezione successiva.

Nota: applicando semplicemente una trasformazione di proiezione al gli oggetti disegnati in genere presentano una visualizzazione molto vuota. In generale, devi applicare anche una fotocamera visualizzare le trasformazioni per far apparire gli elementi sullo schermo.

Definisci una visualizzazione della videocamera

Completa il processo di trasformazione degli oggetti disegnati aggiungendo una trasformazione della vista fotocamera come parte del processo di disegno nel renderer. Nel codice di esempio che segue, la visualizzazione della videocamera la trasformazione viene calcolata utilizzando Matrix.setLookAtM() e poi combinata con la matrice di proiezione calcolata in precedenza. La combinazione matrici di trasformazione vengono quindi passate alla forma disegnata.

Kotlin

override fun onDrawFrame(unused: GL10) {
    ...
    // Set the camera position (View matrix)
    Matrix.setLookAtM(viewMatrix, 0, 0f, 0f, 3f, 0f, 0f, 0f, 0f, 1.0f, 0.0f)

    // Calculate the projection and view transformation
    Matrix.multiplyMM(vPMatrix, 0, projectionMatrix, 0, viewMatrix, 0)

    // Draw shape
    triangle.draw(vPMatrix)

Java

@Override
public void onDrawFrame(GL10 unused) {
    ...
    // Set the camera position (View matrix)
    Matrix.setLookAtM(viewMatrix, 0, 0, 0, 3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);

    // Calculate the projection and view transformation
    Matrix.multiplyMM(vPMatrix, 0, projectionMatrix, 0, viewMatrix, 0);

    // Draw shape
    triangle.draw(vPMatrix);
}

Applicare le trasformazioni di proiezione e videocamera

Per utilizzare la matrice di trasformazione della proiezione combinata e della vista videocamera mostrata in visualizza l'anteprima delle sezioni, per prima cosa aggiungi una variabile matrice al vertex shaker definito in precedenza nel corso Triangle:

Kotlin

class Triangle {

    private val 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 var vPMatrixHandle: Int = 0

    ...
}

Java

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 vPMatrixHandle;

    ...
}

A questo punto, modifica il metodo draw() degli oggetti grafici per accettare il valore combinato matrice di trasformazione e applicarla alla forma:

Kotlin

fun draw(mvpMatrix: FloatArray) { // pass in the calculated transformation matrix
    ...

    // get handle to shape's transformation matrix
    vPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix")

    // Pass the projection and view transformation to the shader
    GLES20.glUniformMatrix4fv(vPMatrixHandle, 1, false, mvpMatrix, 0)

    // Draw the triangle
    GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount)

    // Disable vertex array
    GLES20.glDisableVertexAttribArray(positionHandle)
}

Java

public void draw(float[] mvpMatrix) { // pass in the calculated transformation matrix
    ...

    // get handle to shape's transformation matrix
    vPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");

    // Pass the projection and view transformation to the shader
    GLES20.glUniformMatrix4fv(vPMatrixHandle, 1, false, mvpMatrix, 0);

    // Draw the triangle
    GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);

    // Disable vertex array
    GLES20.glDisableVertexAttribArray(positionHandle);
}

Dopo aver calcolato e applicato correttamente le trasformazioni di proiezione e visualizzazione della videocamera, gli oggetti grafici sono disegnati nelle proporzioni corrette e dovrebbero avere il seguente aspetto:

Figura 1. Triangolo disegnato con una proiezione e una visualizzazione della fotocamera applicate.

Ora che hai un'applicazione che mostra le tue forme nelle proporzioni corrette, è il momento aggiungere movimento alle forme.