O Google tem o compromisso de promover a igualdade racial para as comunidades negras. Saiba como.

Aplicar projeção e visualizações de câmera

No ambiente OpenGL ES, a projeção e as visualizações de câmera permitem exibir objetos desenhados de uma maneira mais parecida com a forma como você vê objetos com seus olhos. Essa simulação de visualização física é feita com transformações matemáticas de coordenadas de objetos desenhados:

  • Projeção: essa transformação ajusta as coordenadas de objetos desenhados com base na largura e na altura da GLSurfaceView onde eles são exibidos. Sem esse cálculo, os objetos desenhados pelo OpenGL ES são distorcidos pelas proporções desiguais da janela de visualização. Uma transformação de projeção normalmente tem que ser calculada quando as proporções da visualização do OpenGL são estabelecidas ou modificadas no método onSurfaceChanged() do renderizador. Para mais informações sobre as projeções do OpenGL ES e o mapeamento de coordenadas, consulte Mapear coordenadas para objetos desenhados.
  • Visualização da câmera: esta transformação ajusta as coordenadas de objetos desenhados com base em uma posição da câmera virtual. É importante observar que o OpenGL ES não define um objeto de câmera real, mas fornece métodos utilitários que simulam uma câmera, transformando a exibição de objetos desenhados. Uma transformação de visualização da câmera pode ser calculada apenas uma vez quando a GLSurfaceView for estabelecida, ou pode mudar dinamicamente com base em ações do usuário ou na função do aplicativo.

Esta lição descreve como criar uma projeção e uma visualização de câmera e aplicá-las a formas desenhadas na GLSurfaceView.

Definir uma projeção

Os dados para uma transformação de projeção são calculados no método onSurfaceChanged() da classe GLSurfaceView.Renderer. O código de exemplo a seguir usa a altura e a largura da GLSurfaceView para preencher uma Matrix de transformação de projeção com o método 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);
    }
    

Esse código preenche uma matriz de projeção, mProjectionMatrix, que pode ser combinada com uma transformação de visualização da câmera no método onDrawFrame(), que é mostrado na próxima seção.

Observação: aplicar apenas uma transformação de projeção aos seus objetos de desenho normalmente resulta em uma tela muito vazia. Em geral, você também precisa aplicar uma transformação de visualização da câmera para que algo apareça na tela.

Definir uma visualização de câmera

Conclua o processo de transformação de objetos desenhados adicionando uma transformação de visualização de câmera como parte do processo de desenho no renderizador. No código de exemplo a seguir, a transformação de visualização de câmera é calculada usando o método Matrix.setLookAtM() e depois combinada com a matriz de projeção calculada anteriormente. As matrizes de transformação combinadas são transmitidas para a forma desenhada.

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

Aplicar projeção e transformações de câmera

Para utilizar a matriz combinada de projeção e transformação de visualização de câmera mostrada nas seções de visualização, primeiro adicione uma variável de matriz ao sombreador de vértice definido anteriormente na 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;

        ...
    }
    

Em seguida, modifique o método draw() dos objetos gráficos para aceitar a matriz de transformação combinada e aplique-o à forma:

Kotlin

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

        // get handle to shape's transformation matrix
        vPMatrixHandle = GLES20.glGetUniformLocation(program, "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(program, "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);
    }
    

Depois de calcular e aplicar corretamente as transformações de projeção e de visualização de câmera, seus objetos gráficos são desenhados em proporções corretas e ficarão parecidos com este:

Figura 1. Triângulo desenhado com uma projeção e uma visualização de câmera aplicadas.

Agora que você tem um aplicativo que exibe suas formas nas proporções corretas, é hora de adicionar movimento a elas.