Google berkomitmen untuk mendorong terwujudnya keadilan rasial bagi komunitas Kulit Hitam. Lihat caranya.

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 merupakan ragam dari spesifikasi OpenGL yang ditujukan untuk perangkat tersemat. 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: Dukungan OpenGL ES 3.0 API di perangkat memerlukan implementasi pipeline grafis ini, yang disediakan oleh produsen perangkat. Perangkat yang menjalankan Android 4.3 atau yang lebih rendah mungkin tidak mendukungOpenGL ES 3.0 API. Untuk informasi tentang memeriksa versi OpenGL ES apa yang didukung saat waktu proses, 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 baik melalui API framework-nya maupun 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 sasaran Anda adalah menggunakan OpenGL di aplikasi Android, memahami cara menerapkan kedua class ini dalam sebuah 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 Anda ingin merekam peristiwa layar sentuh, sebaiknya Anda memperluas class GLSurfaceView untuk mengimplementasikan pemroses sentuhan, seperti ditunjukkan dalam kelas pelatihan OpenGL, Menanggapi peristiwa sentuh.
GLSurfaceView.Renderer
Antarmuka ini menentukan metode yang diperlukan untuk menggambar grafis di GLSurfaceView. Anda harus menyediakan implementasi antaramuka ini sebagai class terpisah dan menambahkannya ke instance GLSurfaceView Anda 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 menjalankan tindakan yang perlu terjadi hanya sekali, seperti menetapkan 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 container GLSurfaceView.

Paket OpenGL ES

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

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

Mendeklarasikan persyaratan OpenGL

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

  • Persyaratan versi OpenGL ES - Jika aplikasi Anda memerlukan OpenGL ES versi tertentu, Anda harus mendeklarasikan persyaratan tersebut dengan menambahkan setelan berikut ke manifes, seperti 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 menentukan ini 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 kompatibel dengan OpenGL ES 2.0 API, yang berarti Anda dapat lebih fleksibel dalam mengimplementasikan 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 OpenGL ES 3.x API pada waktu proses, lalu menggunakan fitur-fitur OpenGL ES 3.x jika perangkat mendukungnya. Untuk informasi lebih lanjut 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 informasi selengkapnya tentang format kompresi tekstur yang tersedia, lihat Dukungan kompresi tekstur.

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

Memetakan koordinat untuk objek yang digambar

Salah satu masalah dasar dalam menampilkan grafis di perangkat Android adalah variasi ukuran dan bentuk layarnya. OpenGL mengasumsikan sistem koordinat persegi dan seragam dan, secara default, menggambar koordinat tersebut ke layar perangkat Anda, yang biasanya tidak berbentuk persegi tetapi dianggap seolah-olah 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 bingkai OpenGL di sebelah kiri, dan bagaimana koordinat ini 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 Anda memiliki proporsi yang benar di tampilan apa pun.

Untuk menerapkan proyeksi dan tampilan kamera, buatlah matriks proyeksi dan matriks tampilan kamera, lalu terapkan ke pipeline rendering OpenGL. Matriks proyeksi ini menghitung ulang koordinat grafis Anda sehingga dapat dipetakan dengan benar ke layar perangkat Android. Matriks tampilan kamera membuat transformasi yang merender objek dari posisi pandang 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 tambahkan keduanya 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. Contoh kode berikut menunjukkan cara memodifikasi metode onSurfaceChanged() dalam implementasi GLSurfaceView.Renderer untuk membuat matriks proyeksi berdasarkan rasio tinggi lebar 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. Contoh kode berikut menunjukkan cara memodifikasi metode onDrawFrame() dalam 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 verteks objek grafis Anda. Dengan menambahkan anggota matriks ini, Anda dapat membuat dan menerapkan matriks proyeksi dan tampilan kamera ke objek Anda.

  1. Menambahkan matriks ke shader verteks - Buatlah variabel untuk matriks proyeksi tampilan dan sertakan sebagai pengali posisi shader. Dalam 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";
        

    Perhatikan: 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 menetapkan matriks proyeksi yang terpisah dari anggota matriks penayangan kamera di shader verteks sehingga Anda dapat mengubahnya secara independen.

  2. Mengakses matriks shader - Setelah membuat hook di shader verteks untuk menerapkan proyeksi dan tampilan kamera, selanjutnya Anda dapat mengakses variabel tersebut untuk menerapkan matriks proyeksi dan matriks tampilan kamera. Kode berikut menunjukkan cara memodifikasi metode onSurfaceCreated() dalam implementasi GLSurfaceView.Renderer untuk mengakses variabel matriks yang ditentukan dalam shader verteks 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 - Buatlah matriks proyeksi dan tampilan untuk diterapkan ke objek grafis. Contoh kode berikut menunjukkan cara memodifikasi metode onSurfaceCreated() dan onSurfaceChanged() dalam implementasi GLSurfaceView.Renderer untuk membuat matriks tampilan kamera dan matriks proyeksi berdasarkan rasio tinggi lebar 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 tersebut dan tetapkan menjadi 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, ikuti kelas Menampilkan grafis dengan OpenGL ES.

Membentuk wajah dan lekukan

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

Koordinat di verteks segitiga

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

Dalam contoh ini, titik-titik segitiga ditentukan dalam suatu urutan sedemikian rupa sehingga titik-titik tersebut digambar dalam arah berlawanan. Urutan penggambaran koordinat ini menentukan arah lekukan untuk bentuk. Secara default, di OpenGL, wajah yang digambar berlawanan arah jarum jam adalah wajah depan. Segitiga yang ditunjukkan dalam Gambar 1 ditentukan sehingga Anda melihat wajah depan bentuk (sebagaimana ditafsirkan oleh OpenGL) dan sisi satunya 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 sebuah opsi pada lingkungan OpenGL yang memungkinkan pipeline rendering untuk mengabaikan (tidak menghitung atau menggambar) wajah belakang dari sebuah 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 face culling tanpa mengetahui sisi mana dari bentuk Anda yang merupakan wajah depan dan wajah belakang, grafik OpenGL 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 menetapkan lingkungan OpenGL agar memperlakukan wajah searah jarum jam sebagai wajah depan, tetapi melakukannya memerlukan lebih banyak kode dan cenderung 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 dari 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 dikembangkan dengan OpenGL. OpenGL ES 3.0 didukung pada 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 berteknologi Android yang mendukung versi OpenGL ES tertentu, lihat Dasbor versi OpenGL ES.

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

OpenGL ES 3.0 API menyediakan fitur tambahan dan performa yang lebih baik daripada versi 2.0 dan juga mendukung kompatibilitas mundur. Ini berarti Anda berpotensi dapat menulis aplikasi Anda yang menargetkan OpenGL ES 2.0 dan, secara kondisional, menyertakan fitur grafis OpenGL ES 3.0 jika tersedia. Untuk informasi selengkapnya tentang memeriksa ketersediaan OpenGL ES 3.0 API, 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 menyediakan dukungan untuk format kompresi ETC1 sebagai fitur standar, yang menyertakan 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 sebuah perangkat atau tidak, panggil metode ETC1Util.isETC1Supported().

Catatan: Format kompresi tekstur ETC1 tidak mendukung tekstur dengan transparansi (saluran alfa). Jika aplikasi Anda memerlukan tekstur dengan transparansi, sebaiknya periksa 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. Format ini juga mendukung transparansi (saluran alfa).

Selain format ETC, perangkat Android memiliki dukungan yang beragam untuk kompresi tekstur berdasarkan chipset GPU dan implementasi OpenGL. Anda perlu mempelajari dukungan kompresi tekstur di perangkat yang Anda targetkan untuk menentukan jenis kompresi apa yang sebaiknya didukung oleh aplikasi Anda. Untuk menentukan format tekstur apa yang didukung di perangkat tertentu, Anda harus mengkueri perangkat dan mempelajari nama ekstensi OpenGL, yang mengidentifikasi format kompresi tekstur apa saja (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 laju 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 tidak begitu luas. Format ini mendukung tekstur RGB dengan saluran alfa 4 bit atau 8 bit. Formats 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 tidak begitu luas dan mendukung tekstur RGB dengan saluran alfa. Format ini diwakili 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 apa yang digunakan di perangkat tertentu, lihat bagian berikutnya.

Perhatikan: Setelah Anda menentukan format kompresi tekstur mana 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 oleh aplikasi Anda. Untuk 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 di perangkat tertentu:

  1. Jalankan kode berikut di perangkat target 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 apa yang umumnya didukung.

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

Paket Ekstensi Android (AEP)

AEP memastikan bahwa aplikasi Anda mendukung seperangkat ekstensi OpenGL standar di atas dan di luar set inti yang dijelaskan dalam spesifikasi OpenGL 3.1. Memaketkan ekstensi ini bersama-sama memungkitkan set fungsionalitas yang konsisten di seluruh perangkat, sekaligus memungkinkan developer memanfaatkan sepenuhnya perangkat GPU seluler terbaru.

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

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 Anda di manifes, tetapi, pada secara bersamaan, Anda juga dapat memanfaatkan fitur-fitur di API yang lebih baru. Misalnya, OpenGL ES 3.0 API mendukung kompatibilitas mundur dengan versi 2.0 dari API ini, jadi sebaiknya Anda menulis aplikasi yang dapat memanfaatkan fitur-fitur OpenGL ES 3.0, tetapi kembali ke versi 2.0 jika versi 3.0 tidak tersedia.

Sebelum menggunakan fitur OpenGL ES dari versi yang lebih tinggi daripada versi minimum yang diperlukan dalam manifes aplikasi Anda, 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 level lebih tinggi (EGLContext) dan periksa hasilnya.
  2. Buat konteks OpenGL ES minimum yang didukung dan periksa nilai versinya.

Contoh kode 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 nilai null, kode Anda perlu membuat konteks OpenGL ES 2.0 dan kembali menggunakan API tersebut.

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 berperforma tinggi untuk membuat game, visualisasi, dan antarmuka pengguna 3D. Pemrograman grafis untuk OpenGL ES 2.0 dan 3.0 sebagian besar mirip, di mana versi 3.0 mewakili superset versi 2.0 dengan fitur-fitur tambahan. Pemrograman untuk OpenGL ES 1.0/1.1 API berbeda signifikan dengan OpenGL ES 2.0 dan 3.0, sehingga developer harus mempertimbangkan faktor-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 berdasarkan 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.
  • Kenyamanan Coding - OpenGL ES 1.0/1.1 API menyediakan pipeline fungsi tetap dan fungsi kenyamanan yang tidak tersedia di OpenGL ES 2.0 atau 3.0 API. Developer yang baru mengenal OpenGL ES mungkin akan 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 terprogram sepenuhnya melalui penggunaan shader. Dengan kontrol langsung yang lebih besar atas pipeline pemrosesan grafis, developer dapat menciptakan efek yang akan sangat sulit dihasilkan menggunakan OpenGL ES 1.0/1.1 API.
  • Dukungan Tekstur - OpenGL ES 3.0 API memiliki dukungan terbaik untuk kompresi tekstur karena menjamin ketersediaan format kompresi ETC2, yang mendukung transparansi. Implementasi OpenGL ES 1.x dan 2.0 API biasanya mencakup dukungan untuk ETC1, tetapi format tekstur ini tidak mendukung transparansi sehingga Anda harus menyediakan resource dalam format kompresi lain yang didukung oleh perangkat yang Anda targetkan. Untuk informasi selengkapnya, lihat Dukungan kompresi tekstur.

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