OpenGL ES

Android admite gráficos 2D y 3D de alto rendimiento con Open Graphics Library (OpenGL®), específicamente, la API de OpenGL ES. OpenGL es una API de gráficos entre plataformas que especifica un interfaz de software estándar para hardware de procesamiento de gráficos 3D. OpenGL ES es una versión de OpenGL específica para dispositivos incorporados. Android admite varias versiones de OpenGL ES API:

  • OpenGL ES 2.0: Esta especificación de API es compatible con Android 2.2 (nivel de API 8) y versiones posteriores.
  • OpenGL ES 3.0: Esta especificación de API es compatible con Android 4.3 (nivel de API 18) y versiones posteriores.
  • OpenGL ES 3.1: Esta especificación de API es compatible con Android 5.0 (nivel de API 21) y versiones posteriores.
  • OpenGL ES 3.2: Esta especificación de API es compatible con Android 7.0 (nivel de API 24) y versiones posteriores.

Precaución: Independientemente de la versión de la plataforma de Android, un dispositivo no puede admitir la API de OpenGL ES 3.0, a menos que el fabricante del dispositivo proporcione un la implementación de esta canalización gráfica. Si especificas en el manifiesto que Se requiere OpenGL ES 3.0; puedes estar seguro de que se incluirá esa versión en el dispositivo. Si especificas que se requiere una versión de nivel inferior, pero quieres usar funciones de la versión 3.0, si están disponibles, se deben verificar en el momento de la ejecución para saber qué versión de OpenGL admite el dispositivo. Para obtener información sobre cómo para hacerlo, consulta Cómo comprobar la versión de OpenGL ES.

Nota: Android admite OpenGL ES 1.0 y 1.1, pero estas versiones de la API dejaron de estar disponibles y no deberían usarse en aplicaciones modernas.

Nota: La API específica que proporciona el framework de Android es similar a la API J2ME JSR239 de OpenGL ES, pero no es idéntico. Si conoces la especificación JSR 239 de J2ME, mantente alerta sobre variaciones.

Ver también

Conceptos básicos

Android admite OpenGL tanto a través de su API de framework como del desarrollo nativo (NDK). Este tema se centra en las interfaces del marco de trabajo de Android. Para obtener más información sobre el Consulta el NDK de Android.

Hay dos clases fundamentales en el framework de Android que te permiten crear y manipular gráficos con la API de OpenGL ES: GLSurfaceView y GLSurfaceView.Renderer Si tu objetivo es usar OpenGL en tu aplicación para Android, comprender cómo implementar estas clases en una actividad debería ser tu primer objetivo.

GLSurfaceView
Esta clase es una View en la que puedes dibujar y manipular objetos con Llama a la API de OpenGL y su función es similar a una SurfaceView. Puedes usar esta clase creando una instancia de GLSurfaceView y agregando tu Renderer. Sin embargo, si quieres capturar eventos de pantalla táctil, deberías extender la clase GLSurfaceView a implementar los objetos de escucha táctiles, como se muestra en la lección de capacitación de OpenGL, Cómo responder a eventos táctiles.
GLSurfaceView.Renderer
Esta interfaz define los métodos necesarios para dibujar gráficos en una GLSurfaceView. Debes implementar esta interfaz como una a la clase separada y la adjuntas a tu instancia de GLSurfaceView con GLSurfaceView.setRenderer()

La interfaz GLSurfaceView.Renderer requiere que implementes el con los siguientes métodos:

  • onSurfaceCreated(): El sistema lo llama una vez, cuando crees el GLSurfaceView. Usa este método para realizar acciones que deben ocurrir solo una vez, como establecer parámetros de entorno de OpenGL o cómo inicializar objetos gráficos de OpenGL.
  • onDrawFrame(): El sistema llama a este método cada vez que se vuelve a dibujar GLSurfaceView. Usa este método como punto de ejecución principal para dibujar (y volver a dibujar) objetos gráficos.
  • onSurfaceChanged(): El sistema llama a este método cuando cambia la geometría de GLSurfaceView, incluidos los cambios en el tamaño del GLSurfaceView o la orientación de la pantalla del dispositivo. Por ejemplo, el sistema llama este método cuando el dispositivo cambia de la orientación vertical a la horizontal. Usa este método para responder a los cambios en el contenedor GLSurfaceView

Paquetes de OpenGL ES

Una vez que hayas establecido una vista de contenedor para OpenGL ES con GLSurfaceView y GLSurfaceView.Renderer, puedes comenzar llamando a las APIs de OpenGL con las siguientes clases:

  • Clase de API de OpenGL ES 2.0
    • android.opengl.GLES20: Este paquete proporciona la a OpenGL ES 2.0 y está disponible a partir de Android 2.2 (nivel de API 8).
  • Paquetes de API de OpenGL ES 3.0/3.1/3.2
    • android.opengl: Este paquete proporciona la interfaz para OpenGL ES 3.0/3.1 . La versión 3.0 está disponible a partir de Android 4.3 (API nivel 18). La versión 3.1 está disponible a partir de Android 5.0 (nivel de API 21). La versión 3.2 está disponible a partir de Android 7.0 (API nivel 24).

Si quieres comenzar a crear una app con OpenGL ES de inmediato, sigue las Cómo mostrar gráficos con OpenGL ES .

Cómo declarar requisitos de OpenGL

Si tu aplicación utiliza funciones de OpenGL que no están disponibles en todos los dispositivos, debes incluir estos requisitos en tu archivo AndroidManifest.xml . Estas son las declaraciones de manifiesto de OpenGL más comunes:

  • Requisitos de la versión de OpenGL ES: Si tu aplicación requiere un versión de OpenGL ES, debes declarar ese requisito agregando la siguiente configuración a tu manifiesto como que se muestra a continuación.

    Para OpenGL ES 2.0:

    <!-- Tell the system this app requires OpenGL ES 2.0. -->
    <uses-feature android:glEsVersion="0x00020000" android:required="true" />
    

    Cuando agregas esta declaración, Google Play restringe la posibilidad de que no se pueda usar tu aplicación instalarse en dispositivos que no son compatibles con OpenGL ES 2.0. Si tu aplicación es exclusivamente para dispositivos compatibles con OpenGL ES 3.0, también puedes especificarlo en tu manifiesto:

    Para OpenGL ES 3.0:

    <!-- Tell the system this app requires OpenGL ES 3.0. -->
    <uses-feature android:glEsVersion="0x00030000" android:required="true" />
    

    Para OpenGL ES 3.1:

    <!-- Tell the system this app requires OpenGL ES 3.1. -->
    <uses-feature android:glEsVersion="0x00030001" android:required="true" />
    

    Para OpenGL ES 3.2:

    <!-- Tell the system this app requires OpenGL ES 3.2. -->
    <uses-feature android:glEsVersion="0x00030002" android:required="true" />
    

    Nota: La API de OpenGL ES 3.x es retrocompatible con la API 2.0, lo que significa que puedes flexible con la implementación de OpenGL ES en tu aplicación. Si declaras el código de OpenGL ES 2.0 API como requisito en tu manifiesto, puedes usar esa versión de API como predeterminada, comprueba para conocer la disponibilidad de la API 3.x en el tiempo de ejecución y, luego, usar las funciones de OpenGL ES 3.x si dispositivo lo admita. Para obtener más información sobre cómo comprobar la versión de OpenGL ES compatible con una dispositivo, consulta Cómo consultar la versión de OpenGL ES.

  • Requisitos de compresión de texturas: Si tu aplicación usa textura de compresión, debes declarar los formatos que admite tu aplicación en el archivo de manifiesto usando <supports-gl-texture>. Obtén más información sobre la compresión de texturas disponible consulta Compatibilidad con la compresión de texturas.

    Si declaras los requisitos de compresión de texturas en el manifiesto, se ocultará tu aplicación de los usuarios con dispositivos que no admiten al menos uno de los tipos de compresión declarados. Para ver más para obtener más información sobre el funcionamiento del filtrado de Google Play para las compresiones de texturas, consulta la Sección de Google Play y filtrado de compresión de texturas de la documentación de <supports-gl-texture>.

Cómo asignar coordenadas para objetos dibujados

Uno de los problemas básicos para mostrar gráficos en dispositivos Android es que las pantallas varían en tamaño y forma. OpenGL adopta un sistema de coordenadas cuadrado y uniforme y, de forma predeterminada, dibuja esas coordenadas en tu pantalla generalmente no cuadrada como si fuera perfectamente cuadrada.

Figura 1: Sistema de coordenadas predeterminado de OpenGL (izquierda) asignado a un sistema Android típico pantalla del dispositivo (derecha).

La ilustración anterior muestra el sistema de coordenadas uniforme que se adopta para un marco OpenGL en la izquierda y cómo estas coordenadas se asignan a una pantalla de dispositivo típica en orientación horizontal a la derecha. Para resolver este problema, puedes aplicar modos de proyección OpenGL y vistas de cámara a transformar coordenadas para que tus objetos gráficos tengan las proporciones correctas en cualquier pantalla.

Para aplicar vistas de cámara y proyección, debes crear una matriz de proyección y una vista de cámara de procesamiento y aplicarlos a la canalización de renderización de OpenGL. La matriz de proyección recalcula coordenadas de tus gráficos para que se asignen correctamente a las pantallas de los dispositivos Android. La vista de la cámara crea una transformación que renderiza objetos desde una posición específica del ojo.

Proyección y vista de cámara en OpenGL ES 2.0 y versiones posteriores

En las APIs de ES 2.0 y 3.0, puedes aplicar proyección y vista de cámara agregando primero un miembro de la matriz. a los sombreadores de vértices de los objetos gráficos. Con este miembro de la matriz agregado, puedes generar y aplicar matrices de proyección y visualización de cámara a tus objetos.

  1. Agrega una matriz a los sombreadores de vértices: Crea una variable para la matriz de proyección de vista. e inclúyelo como multiplicador de la posición del sombreador. En el siguiente ejemplo de sombreador de vértices código, el miembro uMVPMatrix incluido te permite aplicar proyección y visualización de cámara a las coordenadas de los objetos que usan este sombreador.

    Kotlin

    private val vertexShaderCode =
    
        // This matrix member variable provides a hook to manipulate
        // the coordinates of objects that use this vertex shader.
        "uniform mat4 uMVPMatrix;   \n" +
    
        "attribute vec4 vPosition;  \n" +
        "void main(){               \n" +
        // The matrix must be included as part 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; \n" +
    
        "}  \n"
    

    Java

    private final String vertexShaderCode =
    
        // This matrix member variable provides a hook to manipulate
        // the coordinates of objects that use this vertex shader.
        "uniform mat4 uMVPMatrix;   \n" +
    
        "attribute vec4 vPosition;  \n" +
        "void main(){               \n" +
        // The matrix must be included as part 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; \n" +
    
        "}  \n";
    

    Nota: En el ejemplo anterior, se define una única matriz de transformación. miembro del sombreador de vértices en el que se aplica una matriz de proyección combinada y una vista de cámara de salida. Según los requisitos de tu aplicación, es posible que desees definir por separado la proyección miembros de la matriz de visualización de la matriz y la cámara en tus sombreadores de vértices para que puedas cambiarlos de forma independiente.

  2. Accede a la matriz del sombreador: después de crear un hook en tus sombreadores de vértices para aplicar proyección y vista de cámara, puedes acceder a esa variable para aplicar proyección y matrices de visualización de cámara. En el siguiente código, se muestra cómo modificar el método onSurfaceCreated() de una implementación de GLSurfaceView.Renderer para acceder a la matriz definida en el sombreador de vértices anterior.

    Kotlin

    override fun onSurfaceCreated(gl: GL10, config: EGLConfig) {
        ...
        muMVPMatrixHandle = GLES20.glGetUniformLocation(program, "uMVPMatrix")
        ...
    }
    

    Java

    public void onSurfaceCreated(GL10 unused, EGLConfig config) {
        ...
        muMVPMatrixHandle = GLES20.glGetUniformLocation(program, "uMVPMatrix");
        ...
    }
    
  3. Crea matrices de proyección y visualización de cámara: genera la proyección y las matrices de visualización que se aplicarán a los objetos gráficos. El siguiente código de ejemplo muestra cómo modificar onSurfaceCreated() y Métodos onSurfaceChanged() de un Implementación de GLSurfaceView.Renderer para crear una matriz de vista de cámara y una de proyección basada en la relación de aspecto de la pantalla del dispositivo.

    Kotlin

    override fun onSurfaceCreated(gl: GL10, config: EGLConfig) {
        ...
        // Create a camera view matrix
        Matrix.setLookAtM(vMatrix, 0, 0f, 0f, -3f, 0f, 0f, 0f, 0f, 1.0f, 0.0f)
    }
    
    override fun onSurfaceChanged(gl: GL10, width: Int, height: Int) {
        GLES20.glViewport(0, 0, width, height)
    
        val ratio: Float = width.toFloat() / height.toFloat()
    
        // create a projection matrix from device screen geometry
        Matrix.frustumM(projMatrix, 0, -ratio, ratio, -1f, 1f, 3f, 7f)
    }
    

    Java

    public void onSurfaceCreated(GL10 unused, EGLConfig config) {
        ...
        // Create a camera view matrix
        Matrix.setLookAtM(vMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
    }
    
    public void onSurfaceChanged(GL10 unused, int width, int height) {
        GLES20.glViewport(0, 0, width, height);
    
        float ratio = (float) width / height;
    
        // create a projection matrix from device screen geometry
        Matrix.frustumM(projMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
    }
    
  4. Aplicar matrices de proyección y visualización de cámara: Para aplicar la proyección y de vista de cámara, multiplicar las matrices y, luego, colocarlas en el vértice sombreador. En el siguiente código de ejemplo, se muestra cómo modificar el método onDrawFrame() de una implementación de GLSurfaceView.Renderer para combinarlo la matriz de proyección y la vista de cámara creadas en el código anterior y, luego, aplicarla al gráfico que OpenGL debería renderizar.

    Kotlin

    override fun onDrawFrame(gl: GL10) {
        ...
        // Combine the projection and camera view matrices
        Matrix.multiplyMM(vPMatrix, 0, projMatrix, 0, vMatrix, 0)
    
        // Apply the combined projection and camera view transformations
        GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, vPMatrix, 0)
    
        // Draw objects
        ...
    }
    

    Java

    public void onDrawFrame(GL10 unused) {
        ...
        // Combine the projection and camera view matrices
        Matrix.multiplyMM(vPMatrix, 0, projMatrix, 0, vMatrix, 0);
    
        // Apply the combined projection and camera view transformations
        GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, vPMatrix, 0);
    
        // Draw objects
        ...
    }
    

Para ver un ejemplo completo de cómo aplicar la proyección y la vista de cámara con OpenGL ES 2.0, consulta Cómo mostrar gráficos con OpenGL ES. .

Caras de las formas y devanado

En OpenGL, la cara de una forma es una superficie definida por tres o más puntos en tres o más puntos. espacio. Un conjunto de tres o más puntos tridimensionales (llamados vértices en OpenGL) tiene una cara frontal. y una cara posterior. ¿Cómo puedes saber cuál es cuál? Buena pregunta. El tiene que ver con el devanado, o la dirección en la que defines los puntos de una forma.

Coordenadas en
vértices de un triángulo

Figura 1: Ilustración de una lista de coordenadas que se traduce en en el sentido contrario a las manecillas del reloj.

En este ejemplo, los puntos del triángulo se definen en un orden tal que se dibujan en una en el sentido contrario a las manecillas del reloj. El orden en que se dibujan estas coordenadas define el devanado dirección de la forma. De forma predeterminada, en OpenGL, la cara que se dibuja en sentido antihorario es la la cara frontal. El triángulo que se muestra en la figura 1 está definido de modo que mires la cara frontal de la forma (como la interpreta OpenGL) y el otro lado es la cara posterior.

¿Por qué es importante saber cuál es la cara frontal de una forma? La respuesta tiene que ver de uso general de OpenGL, llamada eliminación de caras. La selección de caras es una opción para OpenGL que permite que la canalización de renderización ignore (no calcule ni dibuje) la cara posterior de una lo que ahorra tiempo, memoria y ciclos de procesamiento:

Kotlin

gl.apply {
    // enable face culling feature
    glEnable(GL10.GL_CULL_FACE)
    // specify which faces to not draw
    glCullFace(GL10.GL_BACK)
}

Java

// enable face culling feature
gl.glEnable(GL10.GL_CULL_FACE);
// specify which faces to not draw
gl.glCullFace(GL10.GL_BACK);

Si intentas usar la función de eliminación de caras sin saber qué lados de tus formas son al frente y atrás, tus gráficos de OpenGL se verán un poco delgados o tal vez no se muestren. Por lo tanto, siempre define las coordenadas de tus formas de OpenGL en un orden de dibujo en sentido antihorario.

Nota: Es posible configurar un entorno OpenGL para que trate el en el sentido de las manecillas del reloj que en la cara frontal, pero hacerlo requiere más código y es probable que se confunda desarrolladores experimentados de OpenGL cuando les pidas ayuda. Te recomendamos que no lo hagas.

Versiones de OpenGL y compatibilidad de dispositivos

Las especificaciones de la API de OpenGL ES 1.0 y 1.1 son compatibles desde Android 1.0. La programación de gráficos con la API de OpenGL ES 1.0/1.1 es significativamente diferente a usar la 2.0. y versiones posteriores. OpenGL ES 2.0 es compatible con todos los dispositivos Android a partir de Android 2.2 (nivel de API 8) y se la primera versión recomendada para las nuevas aplicaciones que se desarrollan con OpenGL ES. OpenGL ES 3.0 es compatible con Android 4.3 (nivel de API 18) y versiones posteriores en dispositivos que proporcionan una de la API de OpenGL ES 3.0. Para obtener información sobre la cantidad relativa de dispositivos con tecnología Android compatibles con una versión determinada de OpenGL ES, consulta la Panel de versión de OpenGL ES.

Debes considerar cuidadosamente los requisitos de gráficos y elegir la API que funcione mejor para tu aplicación. Para obtener más información, consulta Elegir una versión de la API de OpenGL

La API de OpenGL ES 3.0 proporciona funciones adicionales y un mejor rendimiento que la API 2.0, y es también es retrocompatible. Esto significa que, potencialmente, puedes escribir la segmentación de tu aplicación OpenGL ES 2.0 e incluir condicionalmente funciones gráficas de OpenGL ES 3.0, si están disponibles Para más información sobre cómo comprobar la disponibilidad de la API 3.0, consulta Cómo comprobar la versión de OpenGL ES

Compatibilidad con la compresión de texturas

La compresión de texturas puede aumentar significativamente el rendimiento de tu aplicación OpenGL reduciendo los requisitos de memoria y haciendo un uso más eficiente del ancho de banda de la memoria. Android proporciona compatibilidad con el formato de compresión ETC1 como función estándar, que incluye una la clase de utilidad ETC1Util y la herramienta de compresión etc1tool (ubicada en el SDK de Android en <sdk>/tools/). Aquí tienes un ejemplo de una aplicación para Android que usa compresión de texturas, consulta la muestra de código CompressedTextureActivity en el SDK de Android <sdk>/samples/<version>/ApiDemos/src/com/example/android/apis/graphics/.

El formato ETC1 es compatible con todos los dispositivos Android que admiten OpenGL ES 2.0 o versiones posteriores.

Nota: El formato de compresión de texturas ETC1 no admite texturas con un transparencia (canal alfa). Si tu aplicación requiere texturas transparentes, deberías investigar otros formatos de compresión de texturas disponibles en tus dispositivos de destino. R El método para renderizar texturas de canales alfa utilizando ETC1 consiste en enlazar dos objetos de textura ETC1: primero con datos de color, luego con datos de canales alfa y, después, combinar los valores de los dos texturas en el sombreador de fragmentos.

Se garantiza que los formatos de compresión de texturas ETC2/EAC estarán disponibles cuando se use OpenGL ES API 3.0. Este formato de textura ofrece excelentes relaciones de compresión con una alta calidad visual y la también admite la transparencia (canal alfa).

Más allá de los formatos ETC, los dispositivos Android tienen compatibilidad variada con la compresión de texturas según sus implementaciones de OpenGL y los chipsets de GPU. Debes investigar la compatibilidad con la compresión de texturas en los dispositivos a los que apuntas para determinar qué tipos de compresión debe y asistencia. Para determinar los formatos de texturas que son compatibles con un dispositivo determinado, debes hacer lo siguiente: consultar el dispositivo y revisar los nombres de extensión de OpenGL que identifican los formatos de compresión de texturas (y otras funciones de OpenGL) que admite la dispositivo. Estos son algunos formatos de compresión de texturas que se suelen admitir:

  • Compresión de textura escalable y adaptable (ASTC): Es un formato de compresión de texturas. y está diseñado para sustituir a los formatos anteriores. Son más flexibles que los formatos anteriores debido a la compatibilidad con diversos formatos tamaños de bloques.
    • GL_KHR_texture_compression_astc_ldr
    • GL_KHR_texture_compression_astc_hdr(alto rango dinámico)
  • S3TC (DXTn/DXTC): La compresión de texturas S3 (S3TC) tiene diferentes variaciones de formato (DXT1 a DXT5) y su disponibilidad no es tan amplia. El formato admite texturas RGB con canales alfa de 4 bits o de 8 bits. Estos formatos se representan con la siguiente extensión de OpenGL nombre:
    • GL_EXT_texture_compression_s3tc
    Algunos dispositivos solo admiten la variación de formato DXT1. esta asistencia limitada está representada por el siguiente nombre de extensión de OpenGL:
    • GL_EXT_texture_compression_dxt1

Los siguientes formatos de compresión de texturas se consideran formatos heredados y no se recomiendan para su uso en aplicaciones nuevas:

  • ATITC (ATC): La compresión de texturas ATI (ATITC o ATC) está disponible en un una amplia variedad de dispositivos y admite compresión de velocidad fija para texturas RGB con y sin esta. un canal alfa. Este formato puede estar representado por varios nombres de extensión OpenGL, por ejemplo:
    • GL_AMD_compressed_ATC_texture
    • GL_ATI_texture_compression_atitc
  • PVRTC: la compresión de texturas PowerVR (PVRTC) está disponible en un variedad de dispositivos y admite texturas de 2 y 4 bits por píxel con o sin un canal alfa. Este formato se representa con el siguiente nombre de extensión de OpenGL:
    • GL_IMG_texture_compression_pvrtc
  • 3DC: La compresión de texturas 3DC (3DC) es un formato menos disponible que admite texturas RGB con un canal alfa. Este formato se representa con el siguiente código OpenGL: nombre de la extensión:
    • GL_AMD_compressed_3DC_texture

Advertencia: Estos formatos de compresión de texturas no compatible con todos los dispositivos. La compatibilidad con estos formatos puede variar según el fabricante y el dispositivo. Para para determinar qué formatos de compresión de texturas tiene un dispositivo en particular, consulta la siguiente sección.

Nota: Una vez que decidas qué formatos de compresión de texturas será compatible, asegúrate de declararlos en tu manifiesto usando <supports-gl-texture> . El uso de esta declaración habilita el filtrado por servicios externos, como Google Play, para que Tu app solo se instala en dispositivos que admiten los formatos que requiere. Para obtener más información, consulta Declaraciones de manifiesto de OpenGL.

Cómo determinar las extensiones de OpenGL

Las implementaciones de OpenGL varían según el dispositivo Android en términos de las extensiones para la API de OpenGL ES compatibles. Estas extensiones incluyen compresiones de texturas, pero también suelen incluir otras al conjunto de funciones de OpenGL.

Para determinar qué formatos de compresión de texturas y otras extensiones de OpenGL son compatibles con un dispositivo específico:

  1. Ejecuta el siguiente código en tus dispositivos de destino para determinar qué compresión de texturas formatos admitidos:

    Kotlin

    var extensions = gl.glGetString(GL10.GL_EXTENSIONS)
    

    Java

    String extensions = gl.glGetString(GL10.GL_EXTENSIONS);
    

    Advertencia: Los resultados de esta llamada varían según el modelo del dispositivo. Tú debe ejecutar esta llamada en varios dispositivos de destino para determinar qué tipos de compresión suelen ser no es compatible.

  2. Revisa el resultado de este método para determinar qué extensiones de OpenGL son compatibles con la dispositivo.

Paquete de extensiones de Android (AEP)

El AEP garantiza que tu aplicación admita el conjunto estandarizado de extensiones de OpenGL que se mencionan más arriba y más allá el conjunto principal descrito en la especificación de OpenGL 3.1. Cómo empaquetar estas extensiones fomenta un conjunto coherente de funcionalidades en todos los dispositivos y, al mismo tiempo, permite a los desarrolladores aprovechar para aprovechar la última generación de dispositivos móviles GPU.

El AEP también mejora la compatibilidad con imágenes, búferes de almacenamiento de sombreador y contadores atómicos en sombreadores de fragmentos.

Para que tu app pueda usar el AEP, su manifiesto debe declarar que se requiere el AEP. Además, la versión de la plataforma debe ser compatible.

Todas las funciones adicionales especificadas en el AEP se incluyen en la base de OpenGL ES 3.2. especificación. Si tu app requiere OpenGL ES 3.2, no necesitas el AEP.

Sigue estos pasos para declarar que se requiere el AEP en el manifiesto:

<uses-feature android:name="android.hardware.opengles.aep"
              android:required="true" />

Para verificar que la versión de la plataforma es compatible con el AEP, usa el Método hasSystemFeature(String), pasando FEATURE_OPENGLES_EXTENSION_PACK como argumento. El siguiente fragmento de código muestra un ejemplo de cómo hacerlo:

Kotlin

var deviceSupportsAEP: Boolean =
        packageManager.hasSystemFeature(PackageManager.FEATURE_OPENGLES_EXTENSION_PACK)

Java

boolean deviceSupportsAEP = getPackageManager().hasSystemFeature
     (PackageManager.FEATURE_OPENGLES_EXTENSION_PACK);

Si el método muestra el valor true, el AEP es compatible.

Para obtener más información sobre el AEP, visita su página en el Registro de OpenGL ES de Khronos.

Cómo averiguar la versión de OpenGL ES

Hay varias versiones de OpenGL ES disponibles en los dispositivos Android. Puedes especificar la versión mínima de la API que requiere tu aplicación en el manifiesto, pero es posible que también quieras aprovechar las funciones de una API más nueva al mismo tiempo. Por ejemplo: la API de OpenGL ES 3.0 es retrocompatible con la versión 2.0 de la API, por lo que te recomendamos escribirás tu aplicación de modo que use funciones de OpenGL ES 3.0, pero recurra a la API 2.0 si la API La API 3.0 no está disponible.

Antes de usar las funciones de OpenGL ES desde una versión superior al mínimo requerido en tu manifiesto de la aplicación, esta debe comprobar la versión de la API disponible en el dispositivo. Para eso, puedes usar uno de estos métodos:

  1. Intenta crear el contexto de OpenGL ES de nivel superior (EGLContext) y verificar el resultado.
  2. Crea un contexto de OpenGL ES con compatibilidad mínima y comprueba el valor de la versión.

En el siguiente código de ejemplo, se muestra la manera de comprobar la versión disponible de OpenGL ES mediante la creación un EGLContext y verifica el resultado. En este ejemplo, se muestra cómo verificar Versión de OpenGL ES 3.0:

Kotlin

private const val EGL_CONTEXT_CLIENT_VERSION = 0x3098
private const val glVersion = 3.0
private class ContextFactory : GLSurfaceView.EGLContextFactory {

    override fun createContext(egl: EGL10, display: EGLDisplay, eglConfig: EGLConfig): EGLContext {

        Log.w(TAG, "creating OpenGL ES $glVersion context")
        return egl.eglCreateContext(
                display,
                eglConfig,
                EGL10.EGL_NO_CONTEXT,
                intArrayOf(EGL_CONTEXT_CLIENT_VERSION, glVersion.toInt(), EGL10.EGL_NONE)
        ) // returns null if 3.0 is not supported
    }
}

Java

private static double glVersion = 3.0;

private static class ContextFactory implements GLSurfaceView.EGLContextFactory {

  private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098;

  public EGLContext createContext(
          EGL10 egl, EGLDisplay display, EGLConfig eglConfig) {

      Log.w(TAG, "creating OpenGL ES " + glVersion + " context");
      int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, (int) glVersion,
              EGL10.EGL_NONE };
      // attempt to create a OpenGL ES 3.0 context
      EGLContext context = egl.eglCreateContext(
              display, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list);
      return context; // returns null if 3.0 is not supported;
  }
}

Si el método createContext() que se muestra arriba muestra un valor nulo, tu código debería crear una interfaz OpenGL. ES 2.0 en su lugar y recurrir al uso de solo esa API.

En el siguiente ejemplo de código, se demuestra cómo comprobar la versión de OpenGL ES creando una red el contexto compatible y, luego, verificar la cadena de versión:

Kotlin

// Create a minimum supported OpenGL ES context, then check:
gl.glGetString(GL10.GL_VERSION).also {
    Log.w(TAG, "Version: $it")
}
 // The version format is displayed as: "OpenGL ES <major>.<minor>"
 // followed by optional content provided by the implementation.

Java

// Create a minimum supported OpenGL ES context, then check:
String version = gl.glGetString(GL10.GL_VERSION);
Log.w(TAG, "Version: " + version );
// The version format is displayed as: "OpenGL ES <major>.<minor>"
// followed by optional content provided by the implementation.

Con este enfoque, si descubres que el dispositivo admite una versión de API de nivel superior, debes destruir el contexto mínimo de OpenGL ES y crear un nuevo contexto con el versión de API disponible.

Cómo elegir una versión de la API de OpenGL

OpenGL ES, versión 2.0 y versión 3.0, proporcionan alta interfaces gráficas de rendimiento para crear juegos en 3D, interfaces de usuario y visualizaciones. Gráficos La programación para OpenGL ES 2.0 y 3.0 es muy similar, y la versión 3.0 representa un superconjunto. de la API 2.0 con funciones adicionales. Programación para la API de OpenGL ES 1.0/1.1 y para OpenGL ES Las versiones 2.0 y 3.0 difieren significativamente y no se recomiendan para aplicaciones nuevas. Los desarrolladores deben considerar cuidadosamente los siguientes factores antes de comenzar a desarrollar con estas APIs:

  • Compatibilidad con dispositivos: los desarrolladores deben considerar los tipos de dispositivos Versiones de Android y OpenGL ES disponibles para sus clientes Más información sobre la compatibilidad de OpenGL en dispositivos, consulta las versiones de OpenGL y compatibilidad con dispositivos.
  • Compatibilidad con texturas: La API de OpenGL ES 3.0 ofrece la mejor compatibilidad con texturas porque garantiza la disponibilidad del formato de compresión ETC2, que admite para mantener la transparencia de la organización. Sin embargo, las implementaciones de la API 2.0 incluyen compatibilidad con ETC1. este formato de textura no admite transparencia. Para implementar la transparencia con imágenes texturas, debes usar dos ETC1 (divididas entre color y alfa) o proporcionar recursos en otros formatos de compresión compatibles con los dispositivos a los que se orienta. Para obtener más información, consulta Compatibilidad con la compresión de texturas.

Si bien la compatibilidad y la compatibilidad con texturas pueden influir debes elegir una versión de la API de OpenGL según lo que consideres que brinda la mejor experiencia para tus usuarios.