OpenGL ES

Android menyertakan dukungan untuk grafis 2D dan 3D performa tinggi dengan Open Graphics Library (OpenGL®), khususnya, OpenGL ES API. OpenGL adalah API grafis lintas platform yang menentukan antarmuka software standar untuk hardware pemrosesan grafis 3D. OpenGL ES adalah ragam dari spesifikasi OpenGL yang ditujukan untuk perangkat yang disematkan. Android mendukung beberapa versi OpenGL ES API:

  • OpenGL ES 1.0 dan 1.1 - Spesifikasi API ini didukung oleh Android 1.0 dan yang lebih tinggi.
  • OpenGL ES 2.0 - Spesifikasi API ini didukung oleh Android 2.2 (API level 8) dan yang lebih tinggi.
  • OpenGL ES 3.0 - Spesifikasi API ini didukung oleh Android 4.3 (API level 18) dan yang lebih tinggi.
  • OpenGL ES 3.1 - Spesifikasi API ini didukung oleh Android 5.0 (API level 21) dan yang lebih tinggi.

Perhatian: Terlepas dari versi platform Android, perangkat tidak dapat mendukung OpenGL ES 3.0 API kecuali jika produsen perangkat menyediakan implementasi pipeline grafis ini. Jika menentukan dalam manifes bahwa OpenGL ES 3.0 diperlukan, Anda dapat yakin bahwa versi tersebut akan ada di perangkat. Jika Anda menetapkan bahwa versi tingkat lebih rendah diperlukan, tetapi ingin menggunakan fitur 3.0 jika tersedia, Anda harus memeriksa pada runtime untuk melihat versi OpenGL yang didukung perangkat. Untuk informasi cara melakukannya, lihat Memeriksa versi OpenGL ES.

Catatan: API spesifik yang disediakan oleh framework Android mirip dengan J2ME JSR239 OpenGL ES API, tetapi tidak identik. Jika Anda sudah terbiasa dengan spesifikasi J2ME JSR239, waspadai variasinya.

Lihat juga

Dasar-dasar

Android mendukung OpenGL melalui API framework-nya dan Native Development Kit (NDK). Topik ini berfokus pada antarmuka framework Android. Untuk informasi selengkapnya tentang NDK, lihat Android NDK.

Ada dua class dasar dalam framework Android yang memungkinkan Anda membuat dan memanipulasi grafis dengan OpenGL ES API: GLSurfaceView dan GLSurfaceView.Renderer. Jika tujuan Anda adalah menggunakan OpenGL di aplikasi Android, memahami cara menerapkan class ini dalam aktivitas harus menjadi tujuan pertama Anda.

GLSurfaceView
Class ini adalah View tempat Anda dapat menggambar dan memanipulasi objek menggunakan panggilan OpenGL API, dan fungsinya serupa dengan SurfaceView. Anda dapat menggunakan class ini dengan membuat instance GLSurfaceView dan menambahkan Renderer ke instance tersebut. Namun, jika ingin merekam peristiwa layar sentuh, Anda harus memperluas class GLSurfaceView untuk mengimplementasikan pemroses sentuh, seperti yang ditunjukkan dalam pelajaran pelatihan OpenGL, Merespons peristiwa sentuh.
GLSurfaceView.Renderer
Antarmuka ini menentukan metode yang diperlukan untuk menggambar grafis di GLSurfaceView. Anda harus menyediakan implementasi antarmuka ini sebagai class terpisah dan melampirkannya ke instance GLSurfaceView menggunakan GLSurfaceView.setRenderer().

Antarmuka GLSurfaceView.Renderer mengharuskan Anda mengimplementasikan metode berikut:

  • onSurfaceCreated(): Sistem memanggil metode ini satu kali, saat membuat GLSurfaceView. Gunakan metode ini untuk melakukan tindakan yang perlu terjadi hanya sekali, seperti menyetel parameter lingkungan OpenGL atau menginisialisasi objek grafis OpenGL.
  • onDrawFrame(): Sistem memanggil metode ini di setiap penggambaran ulang GLSurfaceView. Gunakan metode ini sebagai titik eksekusi utama untuk menggambar (dan menggambar ulang) objek grafis.
  • onSurfaceChanged(): Sistem memanggil metode ini saat geometri GLSurfaceView berubah, termasuk perubahan ukuran GLSurfaceView atau orientasi layar perangkat. Misalnya, sistem memanggil metode ini saat perangkat berubah dari orientasi potret ke lanskap. Gunakan metode ini untuk merespons perubahan di penampung GLSurfaceView.

Paket OpenGL ES

Setelah membuat tampilan penampung untuk OpenGL ES menggunakan GLSurfaceView dan GLSurfaceView.Renderer, Anda dapat mulai memanggil OpenGL API menggunakan class berikut:

Jika Anda ingin segera mulai membuat aplikasi dengan OpenGL ES, ikuti class Menampilkan grafis dengan OpenGL ES.

Mendeklarasikan persyaratan OpenGL

Jika aplikasi Anda menggunakan fitur OpenGL yang hanya tersedia di perangkat tertentu, Anda harus menyertakan persyaratan ini dalam file AndroidManifest.xml. Berikut ini beberapa deklarasi manifes OpenGL yang paling umum:

  • Persyaratan versi OpenGL ES - Jika aplikasi Anda memerlukan versi OpenGL ES tertentu, Anda harus mendeklarasikan persyaratan tersebut dengan menambahkan setelan berikut ke manifes, seperti yang ditunjukkan di bawah ini.

    Untuk OpenGL ES 2.0:

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

    Menambahkan deklarasi ini menyebabkan Google Play membatasi aplikasi Anda agar tidak diinstal di perangkat yang tidak mendukung OpenGL ES 2.0. Jika aplikasi Anda ditujukan khusus untuk perangkat yang mendukung OpenGL ES 3.0, Anda juga dapat menentukannya dalam manifes:

    Untuk OpenGL ES 3.0:

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

    Untuk OpenGL ES 3.1:

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

    Catatan: OpenGL ES 3.x API memiliki kompatibilitas mundur dengan API 2.0, yang berarti Anda dapat lebih fleksibel dalam menerapkan OpenGL ES dalam aplikasi Anda. Dengan mendeklarasikan OpenGL ES 2.0 API sebagai persyaratan dalam manifes, Anda dapat menggunakan versi API tersebut sebagai default, memeriksa ketersediaan API 3.x pada saat dijalankan, lalu menggunakan fitur OpenGL ES 3.x jika perangkat mendukungnya. Untuk informasi selengkapnya tentang cara memeriksa versi OpenGL ES yang didukung oleh perangkat, lihat Memeriksa versi OpenGL ES.

  • Persyaratan kompresi tekstur - Jika aplikasi Anda menggunakan format kompresi tekstur, Anda harus mendeklarasikan format yang didukung aplikasi Anda dalam file manifes menggunakan <supports-gl-texture>. Untuk mengetahui informasi selengkapnya tentang format kompresi tekstur yang tersedia, lihat Dukungan kompresi tekstur.

    Mendeklarasikan persyaratan kompresi tekstur dalam manifes akan menyembunyikan aplikasi Anda dari pengguna dengan perangkat yang tidak mendukung setidaknya salah satu jenis kompresi yang dideklarasikan. Untuk mengetahui informasi selengkapnya tentang cara kerja pemfilteran Google Play untuk kompresi tekstur, lihat bagian Pemfilteran kompresi tekstur dan Google Play dalam dokumentasi <supports-gl-texture>.

Memetakan koordinat untuk objek yang digambar

Salah satu masalah dasar dalam menampilkan grafis di perangkat Android adalah ukuran dan bentuk layarnya dapat bervariasi. OpenGL mengasumsikan sistem koordinat persegi dan seragam dan, secara default, dengan senang hati menggambar koordinat tersebut ke layar Anda yang biasanya bukan persegi seolah-olah layar tersebut adalah persegi sempurna.

Gambar 1. Sistem koordinat OpenGL default (kiri) dipetakan ke layar perangkat Android standar (kanan).

Ilustrasi di atas menunjukkan sistem koordinat seragam yang diasumsikan untuk frame OpenGL di sebelah kiri, dan bagaimana koordinat ini sebenarnya dipetakan ke layar perangkat dalam orientasi lanskap di sebelah kanan. Untuk mengatasi masalah ini, Anda dapat menerapkan mode proyeksi OpenGL dan tampilan kamera untuk mengubah koordinat sehingga objek grafis memiliki proporsi yang benar di tampilan apa pun.

Untuk menerapkan proyeksi dan tampilan kamera, buat matriks proyeksi dan matriks tampilan kamera, lalu terapkan ke pipeline rendering OpenGL. Matriks proyeksi menghitung ulang koordinat grafis Anda sehingga dapat dipetakan dengan benar ke layar perangkat Android. Matriks tampilan kamera membuat transformasi yang merender objek dari posisi mata tertentu.

Proyeksi dan tampilan kamera di OpenGL ES 1.0

Di ES 1.0 API, terapkan proyeksi dan tampilan kamera dengan membuat setiap matriks, lalu menambahkannya ke lingkungan OpenGL.

  1. Matriks proyeksi - Buat matriks proyeksi menggunakan geometri layar perangkat untuk menghitung ulang koordinat objek sehingga dapat digambar dengan proporsi yang benar. Kode contoh berikut menunjukkan cara memodifikasi metode onSurfaceChanged() dari implementasi GLSurfaceView.Renderer untuk membuat matriks proyeksi berdasarkan rasio aspek layar dan menerapkannya ke lingkungan rendering OpenGL.

    Kotlin

    override fun onSurfaceChanged(gl: GL10, width: Int, height: Int) {
        gl.apply {
            glViewport(0, 0, width, height)
    
            // make adjustments for screen ratio
            val ratio: Float = width.toFloat() / height.toFloat()
    
            glMatrixMode(GL10.GL_PROJECTION)            // set matrix to projection mode
            glLoadIdentity()                            // reset the matrix to its default state
            glFrustumf(-ratio, ratio, -1f, 1f, 3f, 7f)  // apply the projection matrix
        }
    }
    

    Java

    public void onSurfaceChanged(GL10 gl, int width, int height) {
        gl.glViewport(0, 0, width, height);
    
        // make adjustments for screen ratio
        float ratio = (float) width / height;
        gl.glMatrixMode(GL10.GL_PROJECTION);        // set matrix to projection mode
        gl.glLoadIdentity();                        // reset the matrix to its default state
        gl.glFrustumf(-ratio, ratio, -1, 1, 3, 7);  // apply the projection matrix
    }
    
  2. Matriks transformasi kamera - Setelah menyesuaikan sistem koordinat menggunakan matriks proyeksi, Anda juga harus menerapkan tampilan kamera. Kode contoh berikut menunjukkan cara memodifikasi metode onDrawFrame() dari implementasi GLSurfaceView.Renderer untuk menerapkan tampilan model dan menggunakan utilitas GLU.gluLookAt() untuk membuat transformasi tampilan yang menyimulasikan posisi kamera.

    Kotlin

    override fun onDrawFrame(gl: GL10) {
        ...
        gl.apply {
            // Set GL_MODELVIEW transformation mode
            glMatrixMode(GL10.GL_MODELVIEW)
            glLoadIdentity()                     // reset the matrix to its default state
        }
    
        // When using GL_MODELVIEW, you must set the camera view
        GLU.gluLookAt(gl, 0f, 0f, -5f, 0f, 0f, 0f, 0f, 1.0f, 0.0f)
        ...
    }
    

    Java

    public void onDrawFrame(GL10 gl) {
        ...
        // Set GL_MODELVIEW transformation mode
        gl.glMatrixMode(GL10.GL_MODELVIEW);
        gl.glLoadIdentity();                      // reset the matrix to its default state
    
        // When using GL_MODELVIEW, you must set the camera view
        GLU.gluLookAt(gl, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
        ...
    }
    

Proyeksi dan tampilan kamera di OpenGL ES 2.0 dan yang lebih tinggi

Di ES 2.0 dan 3.0 API, terapkan proyeksi dan tampilan kamera dengan terlebih dahulu menambahkan anggota matriks ke shader vertex objek grafis Anda. Setelah anggota matriks ini ditambahkan, Anda dapat membuat dan menerapkan matriks proyeksi dan tampilan kamera ke objek Anda.

  1. Menambahkan matriks ke shader vertex - Buat variabel untuk matriks proyeksi tampilan dan sertakan sebagai pengganda posisi shader. Pada contoh kode shader verteks berikut, anggota uMVPMatrix yang disertakan memungkinkan Anda menerapkan matriks proyeksi dan tampilan kamera ke koordinat objek yang menggunakan shader ini.

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

    Catatan: Contoh di atas menetapkan satu anggota matriks transformasi di shader verteks tempat Anda menerapkan gabungan matriks proyeksi dan matriks tampilan kamera. Bergantung pada persyaratan aplikasi, Anda dapat menentukan anggota matriks proyeksi dan matriks penayangan kamera yang terpisah di shader vertex sehingga Anda dapat mengubahnya secara independen.

  2. Mengakses matriks shader - Setelah membuat hook di shader vertex untuk menerapkan proyeksi dan tampilan kamera, Anda kemudian dapat mengakses variabel tersebut untuk menerapkan matriks proyeksi dan tonton tampilan kamera. Kode berikut menunjukkan cara mengubah metode onSurfaceCreated() dalam implementasi GLSurfaceView.Renderer untuk mengakses variabel matriks yang ditentukan dalam shader vertex di atas.

    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. Membuat matriks proyeksi dan tampilan kamera - Buat matriks proyeksi dan visibilitas untuk diterapkan ke objek grafis. Kode contoh berikut menunjukkan cara memodifikasi metode onSurfaceCreated() dan onSurfaceChanged() dari implementasi GLSurfaceView.Renderer untuk membuat matriks tampilan kamera dan matriks proyeksi berdasarkan rasio aspek layar perangkat.

    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. Menerapkan matriks proyeksi dan tampilan kamera - Untuk menerapkan transformasi proyeksi dan tampilan kamera, kalikan kedua matriks, lalu tetapkan ke dalam shader verteks. Contoh kode berikut menunjukkan cara memodifikasi metode onDrawFrame() dalam implementasi GLSurfaceView.Renderer untuk menggabungkan matriks proyeksi dan tampilan kamera yang dibuat dalam kode di atas, lalu menerapkannya ke objek grafis yang akan dirender oleh OpenGL.

    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
        ...
    }
    

Untuk contoh lengkap cara menerapkan proyeksi dan tampilan kamera dengan OpenGL ES 2.0, lihat class Menampilkan grafis dengan OpenGL ES.

Membentuk wajah dan lekukan

Di OpenGL, wajah bentuk adalah permukaan yang ditentukan oleh tiga titik atau lebih dalam ruang tiga dimensi. Kumpulan tiga atau lebih titik tiga dimensi (disebut verteks di OpenGL) memiliki wajah depan dan wajah belakang. Bagaimana cara menentukan wajah depan dan belakang? Pertanyaan yang bagus. Jawabannya ada hubungannya dengan lilitan, atau arah tempat Anda menentukan titik-titik suatu bentuk.

Koordinat pada titik sudut
segitiga

Gambar 1. Ilustrasi daftar koordinat yang diterjemahkan menjadi urutan menggambar berlawanan arah jarum jam.

Dalam contoh ini, titik-titik segitiga ditentukan dalam urutan sedemikian rupa sehingga digambar dalam arah berlawanan arah jarum jam. Urutan penggambaran koordinat ini menentukan arah lilitan untuk bentuk. Secara default, di OpenGL, wajah yang digambar berlawanan arah jarum jam adalah wajah depan. Segitiga yang ditampilkan pada Gambar 1 didefinisikan sehingga Anda hanya melihat tampilan depan bentuk ini (sebagaimana ditafsirkan oleh OpenGL) dan sisi lainnya adalah wajah belakang.

Apa perlunya mengetahui wajah mana yang merupakan wajah depan? Jawabannya ada hubungannya dengan fitur OpenGL yang umum digunakan, yang disebut face culling. Face culling adalah opsi untuk lingkungan OpenGL yang memungkinkan pipeline rendering mengabaikan (tidak menghitung atau menggambar) tampilan belakang suatu bentuk, sehingga menghemat waktu, memori, dan siklus pemrosesan:

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

Jika Anda mencoba menggunakan fitur pemusnahan wajah tanpa mengetahui sisi bentuk mana yang berada di depan dan belakang, grafis OpenGL Anda akan terlihat sedikit tipis, atau mungkin tidak muncul sama sekali. Jadi, selalu tentukan koordinat bentuk OpenGL dengan urutan menggambar berlawanan arah jarum jam.

Catatan: Anda dapat menyetel lingkungan OpenGL agar memperlakukan wajah searah jarum jam sebagai tampilan depan, tetapi cara ini memerlukan lebih banyak kode dan mungkin akan membingungkan developer OpenGL berpengalaman saat Anda meminta bantuan mereka. Jadi, jangan lakukan itu.

Versi OpenGL dan kompatibilitas perangkat

Spesifikasi OpenGL ES 1.0 dan 1.1 API telah didukung sejak Android 1.0. Mulai Android 2.2 (API level 8), framework mendukung spesifikasi OpenGL ES 2.0 API. OpenGL ES 2.0 didukung oleh sebagian besar perangkat Android dan direkomendasikan untuk aplikasi baru yang sedang dikembangkan dengan OpenGL. OpenGL ES 3.0 didukung dengan Android 4.3 (API level 18) dan yang lebih tinggi, di perangkat yang menyediakan implementasi OpenGL ES 3.0 API. Untuk informasi tentang jumlah relatif perangkat Android yang mendukung versi OpenGL ES tertentu, lihat Dasbor versi OpenGL ES.

Pemrograman grafis dengan OpenGL ES 1.0/1.1 API sangat berbeda dibandingkan menggunakan versi 2.0 dan yang lebih tinggi. API versi 1.x memiliki lebih banyak metode praktis dan pipeline grafis tetap, sedangkan OpenGL ES 2.0 dan 3.0 API memberikan kontrol langsung yang lebih besar atas pipeline melalui penggunaan shader OpenGL. Anda harus mempertimbangkan persyaratan grafis dengan cermat dan memilih versi API yang paling sesuai untuk aplikasi Anda. Untuk informasi selengkapnya, lihat Memilih versi OpenGL API.

OpenGL ES 3.0 API menyediakan fitur tambahan dan performa yang lebih baik daripada API 2.0 dan juga kompatibel dengan versi sebelumnya. Ini berarti, Anda berpotensi dapat menulis aplikasi yang menargetkan OpenGL ES 2.0 dan secara kondisional menyertakan fitur grafis OpenGL ES 3.0 jika tersedia. Untuk informasi selengkapnya tentang memeriksa ketersediaan API 3.0, lihat Memeriksa versi OpenGL ES

Dukungan kompresi tekstur

Kompresi tekstur dapat meningkatkan performa aplikasi OpenGL secara signifikan dengan mengurangi persyaratan memori dan memanfaatkan bandwidth memori secara lebih efisien. Framework Android memberikan dukungan untuk format kompresi ETC1 sebagai fitur standar, termasuk class utilitas ETC1Util dan alat kompresi etc1tool (terletak di Android SDK di <sdk>/tools/). Untuk contoh aplikasi Android yang menggunakan kompresi tekstur, lihat contoh kode CompressedTextureActivity di Android SDK (<sdk>/samples/<version>/ApiDemos/src/com/example/android/apis/graphics/).

Perhatian: Format ETC1 didukung oleh sebagian besar perangkat Android, tetapi ketersediaannya tidak dijamin. Untuk memeriksa apakah format ETC1 didukung di perangkat, panggil metode ETC1Util.isETC1Supported().

Catatan: Format kompresi tekstur ETC1 tidak mendukung tekstur dengan transparansi (saluran alfa). Jika aplikasi memerlukan tekstur dengan transparansi, Anda harus menyelidiki format kompresi tekstur lain yang tersedia di perangkat target.

Format kompresi tekstur ETC2/EAC dijamin akan tersedia saat menggunakan OpenGL ES 3.0 API. Format tekstur ini menawarkan rasio kompresi yang sangat baik dengan kualitas visual yang tinggi, dan formatnya juga mendukung transparansi (saluran alfa).

Selain format ETC, perangkat Android memiliki dukungan yang bervariasi untuk kompresi tekstur berdasarkan chipset GPU dan implementasi OpenGL. Anda harus menyelidiki dukungan kompresi tekstur di perangkat yang ditargetkan untuk menentukan jenis kompresi yang harus didukung aplikasi Anda. Untuk menentukan format tekstur yang didukung pada perangkat tertentu, Anda harus mengueri perangkat dan meninjau nama ekstensi OpenGL, yang mengidentifikasi format kompresi tekstur (dan fitur OpenGL lainnya) yang didukung oleh perangkat. Format kompresi tekstur yang umum didukung adalah sebagai berikut:

  • ATITC (ATC) - Kompresi tekstur ATI (ATITC atau ATC) tersedia di berbagai perangkat dan mendukung kompresi kecepatan tetap untuk tekstur RGB dengan dan tanpa saluran alfa. Format ini dapat diwakili oleh beberapa nama ekstensi OpenGL, misalnya:
    • GL_AMD_compressed_ATC_texture
    • GL_ATI_texture_compression_atitc
  • PVRTC - Kompresi tekstur PowerVR (PVRTC) tersedia di berbagai perangkat dan mendukung tekstur 2-bit dan 4-bit per piksel dengan atau tanpa saluran alfa. Format ini diwakili oleh nama ekstensi OpenGL berikut:
    • GL_IMG_texture_compression_pvrtc
  • S3TC (DXTn/DXTC) - Kompresi tekstur S3 (S3TC) memiliki beberapa variasi format (DXT1 hingga DXT5) dan ketersediaannya kurang luas. Format ini mendukung tekstur RGB dengan saluran alfa 4 bit atau 8 bit. Format ini diwakili oleh nama ekstensi OpenGL berikut:
    • GL_EXT_texture_compression_s3tc
    Beberapa perangkat hanya mendukung variasi format DXT1; dukungan terbatas ini diwakili oleh nama ekstensi OpenGL berikut:
    • GL_EXT_texture_compression_dxt1
  • 3DC - Kompresi tekstur 3DC (3DC) adalah format yang ketersediaannya kurang luas dan mendukung tekstur RGB dengan saluran alfa. Format ini direpresentasikan oleh nama ekstensi OpenGL berikut:
    • GL_AMD_compressed_3DC_texture

Peringatan: Format kompresi tekstur ini tidak didukung di semua perangkat. Dukungan untuk format ini dapat bervariasi menurut produsen dan perangkat. Untuk informasi tentang cara menentukan format kompresi tekstur yang ada di perangkat tertentu, lihat bagian berikutnya.

Catatan: Setelah menentukan format kompresi tekstur yang akan didukung aplikasi, pastikan Anda mendeklarasikannya dalam manifes menggunakan <supports-gl-texture> . Penggunaan deklarasi ini memungkinkan pemfilteran oleh layanan eksternal seperti Google Play, sehingga aplikasi Anda hanya diinstal di perangkat yang mendukung format yang diperlukan aplikasi Anda. Untuk mengetahui detailnya, lihat Deklarasi manifes OpenGL.

Menentukan ekstensi OpenGL

Implementasi OpenGL bervariasi menurut perangkat Android dalam hal ekstensi ke OpenGL ES API yang didukung. Ekstensi ini mencakup kompresi tekstur, tetapi biasanya juga menyertakan ekstensi lain ke set fitur OpenGL.

Untuk menentukan format kompresi tekstur, dan ekstensi OpenGL lainnya, yang didukung pada perangkat tertentu:

  1. Jalankan kode berikut di perangkat target Anda untuk menentukan format kompresi tekstur yang didukung:

    Kotlin

    var extensions = gl.glGetString(GL10.GL_EXTENSIONS)
    

    Java

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

    Peringatan: Hasil dari panggilan ini bervariasi menurut model perangkat. Anda harus menjalankan panggilan ini di beberapa perangkat target untuk menentukan jenis kompresi yang umumnya didukung.

  2. Tinjau output metode ini untuk menentukan ekstensi OpenGL apa yang didukung di perangkat.

Paket Ekstensi Android (AEP)

AEP memastikan bahwa aplikasi Anda mendukung serangkaian ekstensi OpenGL terstandardisasi di atas dan di luar set inti yang dijelaskan dalam spesifikasi OpenGL 3.1. Mengemas ekstensi ini bersama-sama akan mendorong serangkaian fungsi yang konsisten di seluruh perangkat, sekaligus memungkinkan developer mendapatkan manfaat penuh dari versi terbaru perangkat GPU seluler.

AEP juga meningkatkan dukungan untuk gambar, buffer penyimpanan shader, dan penghitung atomik di shader fragmen.

Agar aplikasi Anda dapat menggunakan AEP, manifes aplikasi harus mendeklarasikan bahwa AEP diperlukan. Selain itu, versi platform harus mendukungnya.

Deklarasikan persyaratan AEP dalam manifes sebagai berikut:

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

Untuk memverifikasi bahwa versi platform mendukung AEP, gunakan metode hasSystemFeature(String), dengan meneruskan FEATURE_OPENGLES_EXTENSION_PACK sebagai argumen. Cuplikan kode berikut menunjukkan contoh cara melakukannya:

Kotlin

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

Java

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

Jika metode ini menampilkan nilai true, berarti AEP didukung.

Untuk informasi selengkapnya tentang AEP, kunjungi halamannya di Registry OpenGL ES Khronos.

Memeriksa versi OpenGL ES

Ada beberapa versi OpenGL ES yang tersedia di perangkat Android. Anda dapat menentukan versi minimum API yang diperlukan aplikasi dalam manifes, tetapi Anda juga dapat memanfaatkan fitur-fitur di API yang lebih baru secara bersamaan. Misalnya, OpenGL ES 3.0 API memiliki kompatibilitas mundur dengan API versi 2.0, jadi sebaiknya Anda menulis aplikasi agar menggunakan fitur OpenGL ES 3.0, tetapi kembali ke 2.0 API jika API 3.0 tidak tersedia.

Sebelum menggunakan fitur OpenGL ES dari versi yang lebih tinggi dari versi minimum yang diperlukan dalam manifes aplikasi, aplikasi Anda harus memeriksa versi API yang tersedia di perangkat. Anda dapat melakukannya dengan salah satu dari dua cara berikut:

  1. Coba buat konteks OpenGL ES tingkat tinggi (EGLContext) dan periksa hasilnya.
  2. Buat konteks OpenGL ES minimum yang didukung dan periksa nilai versinya.

Kode contoh berikut menunjukkan cara memeriksa versi OpenGL ES yang tersedia dengan membuat EGLContext dan memeriksa hasilnya. Contoh ini menunjukkan cara memeriksa versi 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;
  }
}

Jika metode createContext() yang ditampilkan di atas menampilkan null, kode Anda harus membuat konteks OpenGL ES 2.0 dan kembali menggunakan API tersebut saja.

Contoh kode berikut menunjukkan cara memeriksa versi OpenGL ES dengan membuat konteks minimum yang didukung terlebih dahulu, lalu memeriksa string versi:

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.

Dengan pendekatan ini, jika Anda menemukan bahwa perangkat mendukung versi API level yang lebih tinggi, Anda harus menghancurkan konteks OpenGL ES minimum dan membuat konteks baru dengan versi API lebih tinggi yang tersedia.

Memilih versi OpenGL API

OpenGL ES 1.0 API (dan ekstensi 1.1), versi 2.0, dan versi 3.0 semuanya menyediakan antarmuka grafis performa tinggi untuk membuat game, visualisasi, dan antarmuka pengguna 3D. Pemrograman grafis untuk OpenGL ES 2.0 dan 3.0 sebagian besar mirip, dengan versi 3.0 mewakili superset dari 2.0 API dengan fitur tambahan. Pemrograman untuk OpenGL ES 1.0/1.1 API versus OpenGL ES 2.0 dan 3.0 sangat berbeda, sehingga developer harus mempertimbangkan faktor berikut dengan cermat sebelum memulai pengembangan dengan API ini:

  • Performa - Secara umum, OpenGL ES 2.0 dan 3.0 memberikan performa grafis yang lebih cepat daripada ES 1.0/1.1 API. Namun, perbedaan performa ini dapat bervariasi, bergantung pada perangkat Android yang menjalankan aplikasi OpenGL Anda, karena adanya perbedaan implementasi produsen hardware untuk pipeline grafis OpenGL ES.
  • Kompatibilitas Perangkat - Developer harus mempertimbangkan jenis perangkat, versi Android, dan versi OpenGL ES yang tersedia bagi pelanggan mereka. Untuk informasi selengkapnya tentang kompatibilitas OpenGL di seluruh perangkat, lihat bagian Versi OpenGL dan kompatibilitas perangkat.
  • Kepraktisan Coding - OpenGL ES 1.0/1.1 API menyediakan pipeline fungsi tetap dan fungsi kemudahan yang tidak tersedia di OpenGL ES 2.0 atau 3.0 API. Developer yang baru mengenal OpenGL ES mungkin merasa coding untuk versi 1.0/1.1 lebih cepat dan lebih nyaman.
  • Kontrol Grafis - OpenGL ES 2.0 dan 3.0 API memberikan tingkat kontrol yang lebih tinggi dengan menyediakan pipeline yang dapat diprogram sepenuhnya melalui penggunaan shader. Dengan kontrol langsung yang lebih besar atas pipeline pemrosesan grafis, developer dapat membuat efek yang akan sangat sulit dihasilkan menggunakan API 1.0/1.1.
  • Dukungan Tekstur - OpenGL ES 3.0 API memiliki dukungan terbaik untuk kompresi tekstur karena menjamin ketersediaan format kompresi ETC2, yang mendukung transparansi. Implementasi API 1.x dan 2.0 biasanya menyertakan dukungan untuk ETC1, tetapi format tekstur ini tidak mendukung transparansi, jadi biasanya Anda harus menyediakan resource dalam format kompresi lain yang didukung oleh perangkat yang Anda targetkan. Untuk mengetahui informasi selengkapnya, lihat Dukungan kompresi tekstur.

Meskipun performa, kompatibilitas, kenyamanan, kontrol, dan faktor lainnya dapat memengaruhi keputusan Anda, Anda harus memilih versi OpenGL API berdasarkan apa yang menurut Anda akan memberikan pengalaman terbaik bagi pengguna.