Appliquer des vues de caméra et des projections

Dans l'environnement OpenGL ES, la projection et les vues de caméra vous permettent d'afficher les objets dessinés dans un qui ressemble davantage à la façon dont vous voyez des objets physiques avec vos yeux. Cette simulation de l'affichage physique se fait par le biais de transformations mathématiques des coordonnées des objets dessinés:

  • Projection : cette transformation ajuste les coordonnées des objets dessinés en fonction de la largeur et la hauteur du GLSurfaceView où elles sont affichées ; Sans ce calcul, les objets dessinés par OpenGL ES sont faussés par les proportions inégales de la vue fenêtre. En général, une transformation de projection ne doit être calculée que lorsque les proportions des La vue OpenGL est établie ou modifiée dans la méthode onSurfaceChanged() de votre moteur de rendu. Pour en savoir plus sur les projections OpenGL ES et la cartographie des coordonnées, consultez Cartographie des coordonnées Objets.
  • Camera View (Vue de la caméra) : cette transformation ajuste les coordonnées des objets dessinés en fonction d'un la position de la caméra virtuelle. Il est important de noter qu'OpenGL ES ne définit pas de caméra mais fournit à la place des méthodes utilitaires qui simulent un appareil photo en transformant l'affichage des objets dessinés. Une transformation de vue de caméra peut être calculée une seule fois lorsque vous établissez votre GLSurfaceView, ou changer de façon dynamique en fonction des actions des utilisateurs ou de vos la fonction d'application.

Cette leçon explique comment créer une projection et une vue de caméra, et comment les appliquer aux formes dessinées dans votre GLSurfaceView.

Définir une projection

Les données d'une transformation de projection sont calculées dans onSurfaceChanged() de la classe GLSurfaceView.Renderer. L'exemple de code suivant prend la hauteur et la largeur de l'élément GLSurfaceView et l'utilise pour remplir une transformation de projection Matrix à l'aide de la méthode 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);
}

Ce code renseigne une matrice de projection, mProjectionMatrix, que vous pouvez ensuite combiner avec une transformation de vue de caméra dans la méthode onDrawFrame(), comme illustré dans la section suivante.

Remarque:Il suffit d'appliquer une transformation de projection à vos d'objets dessinent généralement un affichage très vide. En règle générale, vous devez aussi installer la transformation d'affichage pour que tout soit affiché à l'écran.

Définir une vue de caméra

Terminez le processus de transformation de vos objets dessinés en ajoutant une transformation de vue de caméra en tant que du processus de dessin dans votre moteur de rendu. Dans l'exemple de code suivant, la vue de la caméra est calculée à l'aide de la méthode Matrix.setLookAtM(). puis combinés à la matrice de projection calculée précédemment. La combinaison les matrices de transformation sont ensuite transmises à la forme tracée.

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

Appliquer des transformations de caméra et de projection

Pour utiliser la matrice de transformation combinée de la projection et de la vue de caméra présentée dans le affiche un aperçu des sections, commencez par ajouter une variable de matrice au nuanceur de sommets défini précédemment dans la classe 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;

    ...
}

Ensuite, modifiez la méthode draw() de vos objets graphiques pour accepter la combinaison et appliquez-la à la forme:

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

Une fois que vous avez correctement calculé et appliqué les transformations de projection et de vue de caméra, vos objets graphiques sont dessinés dans des proportions correctes et doivent se présenter comme suit:

Figure 1 : Triangle dessiné avec une projection et une vue de caméra appliquées.

Maintenant que vous disposez d'une application qui affiche vos formes dans des proportions correctes, il est temps de ajouter du mouvement à vos formes.