OpenGL ES

Android, Open Graphics Library (OpenGL®) ile, özellikle de OpenGL ES API'si ile yüksek performanslı 2D ve 3D grafikler için destek sunar. OpenGL, 3D grafik işleme donanımı için standart bir yazılım arayüzü belirten platformlar arası grafik API'sidir. OpenGL ES, yerleşik cihazlar için tasarlanan OpenGL spesifikasyonunun bir biçimidir. Android, OpenGL ES API'nin çeşitli sürümlerini destekler:

  • OpenGL ES 1.0 ve 1.1 - Bu API spesifikasyonu, Android 1.0 ve üzeri tarafından desteklenir.
  • OpenGL ES 2.0 - Bu API spesifikasyonu, Android 2.2 (API düzeyi 8) ve sonraki sürümler tarafından desteklenir.
  • OpenGL ES 3.0 - Bu API spesifikasyonu, Android 4.3 (API düzeyi 18) ve sonraki sürümler tarafından desteklenir.
  • OpenGL ES 3.1 - Bu API spesifikasyonu, Android 5.0 (API düzeyi 21) ve sonraki sürümler tarafından desteklenir.

Dikkat: Android platform sürümü ne olursa olsun, cihaz üreticisi bu grafik ardışık düzeninin uygulamasını sağlamadığı sürece OpenGL ES 3.0 API'yi destekleyemez. Manifest'te OpenGL ES 3.0'ın gerektiğini belirtirseniz bu sürümün cihazda mevcut olacağından emin olabilirsiniz. Daha alt düzey bir sürümün gerektiğini belirtirseniz ancak varsa 3.0 özelliklerini kullanmak isterseniz, cihazın hangi OpenGL sürümünü desteklediğini görmek için çalışma zamanında kontrol etmeniz gerekir. Bunun nasıl yapılacağı hakkında bilgi edinmek için OpenGL ES sürümünü kontrol etme bölümüne bakın.

Not: Android çerçevesi tarafından sağlanan spesifik API J2ME JSR239 OpenGL ES API'ye benzer, ancak aynı değildir. J2ME JSR239 spesifikasyonu hakkında bilginiz varsa varyasyonlara karşı dikkatli olun.

Ayrıca bakın:

Temel bilgiler

Android, OpenGL'yi hem çerçeve API'si hem de Yerel Geliştirme Kiti (NDK) aracılığıyla destekler. Bu konu, Android çerçeve arayüzlerine odaklanmaktadır. NDK hakkında daha fazla bilgi için Android NDK'ya bakın.

Android çerçevesinde, OpenGL ES API ile grafikler oluşturup bunlarda değişiklik yapmanıza olanak tanıyan iki temel sınıf vardır: GLSurfaceView ve GLSurfaceView.Renderer. Hedefiniz Android uygulamanızda OpenGL kullanmaksa, bu sınıfları bir etkinlikte nasıl uygulayacağınızı anlamak ilk hedefiniz olmalıdır.

GLSurfaceView
Bu sınıf, OpenGL API çağrılarını kullanarak nesneleri çizebileceğiniz ve değiştirebileceğiniz bir View sınıftır. Bu sınıf, işlevleri SurfaceView ile benzerdir. GLSurfaceView örneği oluşturup Renderer öğenizi buna ekleyerek bu sınıfı kullanabilirsiniz. Bununla birlikte, dokunmatik ekran etkinliklerini yakalamak istiyorsanız Dokunma etkinliklerine yanıt verme başlıklı OpenGL eğitim dersinde gösterildiği gibi, dokunma işleyicileri uygulamak için GLSurfaceView sınıfını genişletmeniz gerekir.
GLSurfaceView.Renderer
Bu arayüz, GLSurfaceView biçiminde grafik çizmek için gereken yöntemleri tanımlar. Bu arayüzün uygulamasını ayrı bir sınıf olarak sağlamanız ve GLSurfaceView.setRenderer() kullanarak GLSurfaceView örneğinize eklemeniz gerekir.

GLSurfaceView.Renderer arayüzü aşağıdaki yöntemleri uygulamanızı gerektirir:

  • onSurfaceCreated(): Sistem, GLSurfaceView oluşturulurken bu yöntemi bir kez çağırır. OpenGL ortam parametrelerini ayarlama veya OpenGL grafik nesnelerini başlatma gibi yalnızca bir kez gerçekleşmesi gereken işlemleri gerçekleştirmek için bu yöntemi kullanın.
  • onDrawFrame(): Sistem, GLSurfaceView öğesinin her yeniden çiziminde bu yöntemi çağırır. Bu yöntemi, grafik nesneleri çizmek (ve yeniden çizmek) için birincil yürütme noktası olarak kullanın.
  • onSurfaceChanged(): Sistem bu yöntemi, GLSurfaceView geometrisi değiştiğinde (GLSurfaceView boyutunun veya cihaz ekranının yönündeki değişiklikler dahil) çağırır. Örneğin, cihaz dikey yönden yatay yöne döndüğünde sistem bu yöntemi çağırır. GLSurfaceView kapsayıcısındaki değişikliklere yanıt vermek için bu yöntemi kullanın.

OpenGL ES paketleri

GLSurfaceView ve GLSurfaceView.Renderer kullanarak OpenGL ES için bir kapsayıcı görünümü oluşturduktan sonra aşağıdaki sınıfları kullanarak OpenGL API'leri çağırmaya başlayabilirsiniz:

Hemen OpenGL ES ile bir uygulama oluşturmaya başlamak isterseniz OpenGL ES ile grafikleri görüntüleme sınıfını uygulayın.

OpenGL gereksinimlerini bildirme

Uygulamanız tüm cihazlarda bulunmayan OpenGL özellikleri kullanıyorsa bu gereksinimleri AndroidManifest.xml dosyanıza eklemeniz gerekir. En yaygın OpenGL manifest bildirimleri aşağıda verilmiştir:

  • OpenGL ES sürüm gereksinimleri - Uygulamanız için belirli bir OpenGL ES sürümü gerekiyorsa bu gereksinimi, aşağıdaki ayarları manifest'inize aşağıda gösterildiği gibi ekleyerek beyan etmeniz gerekir.

    OpenGL ES 2.0 için:

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

    Bu beyanın eklenmesi, Google Play'in uygulamanızın OpenGL ES 2.0'ı desteklemeyen cihazlara yüklenmesini kısıtlamasına neden olur. Uygulamanız özel olarak OpenGL ES 3.0'ı destekleyen cihazlara yönelikse bunu manifest dosyanızda da belirtebilirsiniz:

    OpenGL ES 3.0 için:

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

    OpenGL ES 3.1 için:

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

    Not: OpenGL ES 3.x API, 2.0 API ile geriye dönük uyumludur. Bu da uygulamanızda OpenGL ES'yi kullanırken daha esnek olabileceğiniz anlamına gelir. OpenGL ES 2.0 API'yi manifest dosyanızda bir gereklilik olarak belirterek bu API sürümünü varsayılan olarak kullanabilir, çalışma zamanında 3.x API'nin kullanılabilir olup olmadığını kontrol edebilir ve ardından cihaz destekliyorsa OpenGL ES 3.x özelliklerini kullanabilirsiniz. Cihazlar tarafından desteklenen OpenGL ES sürümünü kontrol etme hakkında daha fazla bilgi edinmek için OpenGL ES sürümünü kontrol etme bölümüne bakın.

  • Doku sıkıştırma şartları: Uygulamanızda doku sıkıştırma biçimleri kullanılıyorsa uygulamanızın desteklediği biçimleri <supports-gl-texture> kullanarak manifest dosyanızda belirtmeniz gerekir. Kullanılabilir doku sıkıştırma biçimleri hakkında daha fazla bilgi için Doku sıkıştırma desteği bölümüne bakın.

    Manifest'inizde doku sıkıştırma gereksinimleri bildirmeniz, uygulamanızı beyan ettiğiniz sıkıştırma türlerinden en az birini desteklemeyen cihazlara sahip kullanıcılardan gizler. Google Play filtrelemesinin doku sıkıştırmalarda nasıl çalıştığı hakkında daha fazla bilgi edinmek için <supports-gl-texture> dokümanlarının Google Play ve doku sıkıştırma filtreleme bölümüne bakın.

Çizilen nesnelerin koordinatlarını eşleme

Android cihazlarda grafikleri görüntülemeyle ilgili temel sorunlardan biri, ekranlarının boyut ve şekil açısından farklılık gösterebilmesidir. OpenGL kare, tek tip bir koordinat sistemi varsayar ve varsayılan olarak, bu koordinatları normalde kare olmayan ekranınıza mükemmel bir kareymiş gibi çizer.

Şekil 1. Tipik bir Android cihaz ekranıyla (sağ) eşlenen varsayılan OpenGL koordinat sistemi (sol).

Yukarıdaki çizimde, soldaki bir OpenGL çerçevesi için kabul edilen tek tip koordinat sistemi ve bu koordinatların, sağdaki yatay yönlü tipik bir cihaz ekranıyla gerçekte nasıl eşlendiği gösterilmektedir. Bu sorunu çözmek için, grafik nesnelerinizin tüm ekranlarda doğru oranlara sahip olması için koordinatları dönüştürmek üzere OpenGL projeksiyon modları ve kamera görünümleri uygulayabilirsiniz.

Projeksiyon ve kamera görünümlerini uygulamak için bir projeksiyon matrisi ve bir kamera görünümü matrisi oluşturup bunları OpenGL oluşturma ardışık düzenine uygularsınız. Projeksiyon matrisi, grafiklerinizin koordinatlarını yeniden hesaplar. Böylece grafiklerinizin Android cihaz ekranlarıyla doğru şekilde eşleştirilmesi sağlanır. Kamera görünümü matrisi, nesneleri belirli bir göz konumundan oluşturan bir dönüşüm oluşturur.

OpenGL ES 1.0'da projeksiyon ve kamera görünümü

ES 1.0 API'de, her bir matrisi oluşturup ardından OpenGL ortamına ekleyerek projeksiyon ve kamera görünümü uygularsınız.

  1. Projeksiyon matrisi - Nesne koordinatlarını doğru oranlarda çizilebilmeleri amacıyla yeniden hesaplamak için cihaz ekranının geometrisini kullanarak bir projeksiyon matrisi oluşturun. Aşağıdaki örnek kod, ekranın en boy oranına göre bir projeksiyon matrisi oluşturmak ve bunu OpenGL oluşturma ortamına uygulamak için GLSurfaceView.Renderer uygulamasının onSurfaceChanged() yönteminin nasıl değiştirileceğini gösterir.

    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. Kamera dönüşüm matrisi - Projeksiyon matrisi kullanarak koordinat sistemini ayarladıktan sonra, bir kamera görünümü de uygulamanız gerekir. Aşağıdaki örnek kod, model görünümü uygulamak için GLSurfaceView.Renderer uygulamasının onDrawFrame() yönteminin nasıl değiştirileceğini ve kamera konumunu simüle eden bir görüntüleme dönüşümü oluşturmak için GLU.gluLookAt() yardımcı programını nasıl kullanacağınızı göstermektedir.

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

OpenGL ES 2.0 ve sonraki sürümlerde projeksiyon ve kamera görünümü

ES 2.0 ve 3.0 API'larında, önce grafik nesnelerinizin köşe gölgelendiricilerine bir matris üyesi ekleyerek projeksiyon ve kamera görünümü uygularsınız. Bu matris üyesi eklendiğinde, projeksiyon ve kamera görüntüleme matrisleri oluşturup bunları nesnelerinize uygulayabilirsiniz.

  1. Köşe gölgelendiricilere matris ekleme - Görünüm projeksiyon matrisi için bir değişken oluşturun ve bunu gölgelendiricinin konumunun çarpanı olarak ekleyin. Aşağıdaki örnekte köşe gölgelendirici kodunda, verilen uMVPMatrix üyesi, bu gölgelendiriciyi kullanan nesnelerin koordinatlarına projeksiyon ve kamera görüntüleme matrislerini uygulamanıza olanak tanır.

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

    Not: Yukarıdaki örnekte, birleşik bir projeksiyon matrisi ve kamera görünümü matrisi uyguladığınız köşe gölgelendiricide tek bir dönüşüm matrisi üyesi tanımlanmaktadır. Uygulama gereksinimlerinize bağlı olarak, köşe gölgelendiricilerinizde ayrı projeksiyon matrisi ve kamera görüntüleme matrisi üyeleri tanımlamak isteyebilirsiniz. Böylece, bu üyeleri birbirinden bağımsız olarak değiştirebilirsiniz.

  2. Gölgelendirici matrisine erişim - Projeksiyon ve kamera görünümünü uygulamak için köşe gölgelendiricilerinizde bir kanca oluşturduktan sonra, projeksiyon ve kamera görüntüleme matrislerini uygulamak için bu değişkene erişebilirsiniz. Aşağıdaki kod, yukarıdaki köşe gölgelendiricide tanımlanan matris değişkenine erişmek için bir GLSurfaceView.Renderer uygulamasının onSurfaceCreated() yönteminin nasıl değiştirileceğini gösterir.

    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. Projeksiyon ve kamera görüntüleme matrisleri oluşturma - Grafik nesnelere uygulanacak projeksiyon ve görüntüleme matrislerini oluşturun. Aşağıdaki örnek kodda, kamera görüntüleme matrisi ve cihazın ekran en boy oranına göre projeksiyon matrisi oluşturmak için GLSurfaceView.Renderer uygulamasının onSurfaceCreated() ve onSurfaceChanged() yöntemlerinin nasıl değiştirileceği gösterilmektedir.

    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. Projeksiyon ve kamera görüntüleme matrislerini uygulama - Projeksiyon ve kamera görünümü dönüşümlerini uygulamak için matrisleri birbiriyle çarpıp tepe noktası gölgelendirmesine yerleştirin. Aşağıdaki örnek kod, yukarıdaki kodda oluşturulan projeksiyon matrisi ve kamera görünümünü birleştirmek için bir GLSurfaceView.Renderer uygulamasının onDrawFrame() yönteminin nasıl değiştirildiğini ve ardından bunu, OpenGL tarafından oluşturulacak grafik nesnelere nasıl uyguladığını gösterir.

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

OpenGL ES 2.0 ile projeksiyon ve kamera görünümünün nasıl uygulanacağına ilişkin tam bir örnek için OpenGL ES ile grafikleri görüntüleme sınıfına bakın.

Yüzleri şekillendirme ve sarmalama

OpenGL'de bir şeklin ön yüzü, üç boyutlu uzayda üç veya daha fazla noktayla tanımlanan bir yüzeydir. Üç veya daha fazla üç boyutlu nokta kümesinin (OpenGL'de köşeler olarak adlandırılır) bir ön yüzü ve bir arka yüzü vardır. Hangi yüzün önde, hangisinin arka olduğunu nasıl anlarsınız? Güzel soru. Yanıt, sarmal veya bir şeklin noktalarını tanımladığınız yönle ilgilidir.

Bir üçgenin köşelerindeki
koordinatlar

Şekil 1. Saat yönünün tersine çevrilmiş bir koordinat listesinin resmi.

Bu örnekte, üçgenin noktaları saat yönünün tersine çizilecek bir sırayla tanımlanmaktadır. Bu koordinatların çizilme sırası, şeklin sarmal yönünü tanımlar. Varsayılan olarak, OpenGL'de saat yönünün tersine çizilen yüz ön yüzdür. Şekil 1'de gösterilen üçgen, şeklin ön yüzüne (OpenGL tarafından yorumlandığı gibi) bakacağınız şekilde, diğer taraf ise arka yüz olacak şekilde tanımlanmıştır.

Bir şeklin hangi yüzünün ön yüz olduğunu bilmek neden önemlidir? Bu sorunun cevabı, yüz ayıklama denen Yaygın olarak kullanılan bir OpenGL özelliğiyle ilgili. Yüz temizleme, oluşturma ardışık düzeninin bir şeklin arka yüzünü yoksaymasına (hesaplamamasına veya çizmesine) izin veren OpenGL ortamı için bir seçenektir. Bu da zamandan, bellekten ve işleme döngülerinden tasarruf sağlar:

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

Şekillerinizin hangi taraflarının ön ve arka olduğunu bilmeden yüz ayıklama özelliğini kullanmaya çalışırsanız, OpenGL grafikleriniz biraz ince görünür veya muhtemelen hiç görünmez. Bu nedenle, OpenGL şekillerinizin koordinatlarını her zaman saat yönünün tersine çizim sırasında tanımlayın.

Not: Saat yönü yüzü ön yüz olarak değerlendirilecek şekilde bir OpenGL ortamı oluşturmak mümkündür, ancak bunu yapmak daha fazla kod gerektirir ve yardım istediğinizde deneyimli OpenGL geliştiricilerinin kafasını karıştırabilir. Bunu yapmayın.

OpenGL sürümleri ve cihaz uyumluluğu

OpenGL ES 1.0 ve 1.1 API özellikleri, Android 1.0'dan beri desteklenmektedir. Android 2.2'den (API düzeyi 8) başlayarak çerçeve, OpenGL ES 2.0 API spesifikasyonunu destekler. OpenGL ES 2.0, çoğu Android cihaz tarafından desteklenir ve OpenGL ile geliştirilmekte olan yeni uygulamalar için önerilir. OpenGL ES 3.0, OpenGL ES 3.0 API'sinin uygulanmasını sağlayan cihazlarda Android 4.3 (API düzeyi 18) ve sonraki sürümlerle desteklenir. Belirli bir OpenGL ES sürümünü destekleyen Android destekli cihazların göreli sayısı hakkında bilgi için OpenGL ES sürüm kontrol paneline bakın.

OpenGL ES 1.0/1.1 API ile grafik programlama, 2.0 ve üzeri sürümleri kullanmaktan önemli ölçüde farklıdır. API'nin 1.x sürümü, daha fazla kolaylık yöntemi ve sabit bir grafik ardışık düzenine sahiptir. OpenGL ES 2.0 ve 3.0 API'leri ise OpenGL gölgelendiricileri kullanarak ardışık düzen üzerinde daha fazla doğrudan kontrol sağlar. Grafik gereksinimlerini dikkatlice değerlendirmeli ve uygulamanız için en uygun API sürümünü seçmelisiniz. Daha fazla bilgi için OpenGL API sürümü seçme bölümüne bakın.

OpenGL ES 3.0 API, ek özellikler ve 2.0 API'den daha iyi performans sağlar ve ayrıca geriye dönük uyumludur. Bu, OpenGL ES 2.0'ı hedefleyen uygulama metninizi yazabileceğiniz ve varsa OpenGL ES 3.0 grafik özelliklerini koşullu olarak ekleyebileceğiniz anlamına gelir. 3.0 API'nin kullanılabilirliğini kontrol etme hakkında daha fazla bilgi için bkz. OpenGL ES sürümünü kontrol etme

Doku sıkıştırma desteği

Doku sıkıştırma, bellek gereksinimlerini azaltarak ve bellek bant genişliğinin daha verimli bir şekilde kullanılmasını sağlayarak OpenGL uygulamanızın performansını önemli ölçüde artırabilir. Android çerçevesi, ETC1Util yardımcı sınıfı ve etc1tool sıkıştırma aracı (<sdk>/tools/ adresindeki Android SDK'sında bulunur) dahil olmak üzere standart bir özellik olarak ETC1 sıkıştırma biçimini destekler. Doku sıkıştırma kullanan bir Android uygulaması örneği için Android SDK'daki (<sdk>/samples/<version>/ApiDemos/src/com/example/android/apis/graphics/) CompressedTextureActivity kod örneğine bakın.

Dikkat: ETC1 biçimi çoğu Android cihaz tarafından desteklenir ancak kullanılabileceği garanti edilmez. ETC1 biçiminin bir cihazda desteklenip desteklenmediğini kontrol etmek için ETC1Util.isETC1Supported() yöntemini çağırın.

Not: ETC1 doku sıkıştırma biçimi, şeffaflığa (alfa kanalı) sahip dokuları desteklemez. Uygulamanız şeffaf dokular gerektiriyorsa hedef cihazlarınızda bulunan diğer doku sıkıştırma biçimlerini araştırmanız gerekir.

OpenGL ES 3.0 API kullanıldığında ETC2/EAC doku sıkıştırma biçimlerinin kullanılabilir olması garanti edilir. Bu doku biçimi, yüksek görsel kalitede mükemmel sıkıştırma oranları sunar ve aynı zamanda şeffaflığı (alfa kanalı) destekler.

ETC biçimlerinin ötesinde, Android cihazlar GPU yonga setlerine ve OpenGL uygulamalarına bağlı olarak doku sıkıştırma için farklı destek sunar. Uygulamanızın hangi sıkıştırma türlerini desteklemesi gerektiğini belirlemek için hedeflediğiniz cihazlardaki doku sıkıştırma desteğini araştırmanız gerekir. Belirli bir cihazda hangi doku biçimlerini desteklediğini belirlemek için cihazı sorgulamanız ve cihazın hangi doku sıkıştırma biçimlerini (ve diğer OpenGL özelliklerini) desteklediğini belirleyen OpenGL uzantı adlarını incelemeniz gerekir. Yaygın olarak desteklenen bazı doku sıkıştırma biçimleri şunlardır:

  • ATITC (ATC): ATI doku sıkıştırma (ATITC veya ATC) çok çeşitli cihazlarda kullanılabilir ve alfa kanalı olan ve olmayan RGB dokuları için sabit hızlı sıkıştırmayı destekler. Bu biçim, çeşitli OpenGL uzantı adları ile temsil edilebilir. Örneğin:
    • GL_AMD_compressed_ATC_texture
    • GL_ATI_texture_compression_atitc
  • PVRTC: PowerVR doku sıkıştırma (PVRTC) çeşitli cihazlarda kullanılabilir ve alfa kanalı olan veya olmayan piksel başına 2 bit ve 4 bit dokuları destekler. Bu biçim, aşağıdaki OpenGL uzantı adıyla temsil edilir:
    • GL_IMG_texture_compression_pvrtc
  • S3TC (DXTn/DXTC) - S3 doku sıkıştırma (S3TC) çeşitli biçim varyasyonlarına (DXT1 - DXT5) sahiptir ve daha az yaygın olarak kullanılır. Bu biçim, 4 bit alfa veya 8 bit alfa kanallarına sahip RGB dokularını destekler. Bu biçimler aşağıdaki OpenGL uzantı adıyla temsil edilir:
    • GL_EXT_texture_compression_s3tc
    Bazı cihazlar yalnızca DXT1 biçim varyasyonunu destekler; bu sınırlı destek aşağıdaki OpenGL uzantı adıyla temsil edilir:
    • GL_EXT_texture_compression_dxt1
  • 3DC: 3DC doku sıkıştırma (3DC), alfa kanalıyla RGB dokularını destekleyen daha az yaygın olarak kullanılan bir biçimdir. Bu biçim, aşağıdaki OpenGL uzantısı adıyla temsil edilir:
    • GL_AMD_compressed_3DC_texture

Uyarı: Bu doku sıkıştırma biçimleri tüm cihazlarda desteklenmez. Bu biçimler için destek, üreticiye ve cihaza göre değişiklik gösterebilir. Belirli bir cihazda hangi doku sıkıştırma biçimlerinin nasıl tanımlanacağını belirlemek için sonraki bölüme bakın.

Not: Uygulamanızın hangi doku sıkıştırma biçimlerini destekleyeceğini belirledikten sonra, bunları <supports-gl-texture> kullanarak manifest dosyanızda belirttiğinizden emin olun. Bu beyan kullanıldığında Google Play gibi harici hizmetlere göre filtreleme etkinleştirilir. Böylece uygulamanız yalnızca uygulamanızın gerektirdiği biçimleri destekleyen cihazlara yüklenir. Ayrıntılar için OpenGL manifest beyanları bölümünü inceleyin.

OpenGL uzantılarını belirleme

OpenGL uygulamaları, desteklenen OpenGL ES API uzantıları açısından Android cihaza göre değişir. Bu uzantılar, doku sıkıştırmaları içerir, ancak genellikle OpenGL özellik grubunun başka uzantılarını da içerir.

Belirli bir cihazda hangi doku sıkıştırma biçimlerinin ve diğer OpenGL uzantılarının desteklendiğini belirlemek için:

  1. Desteklenen doku sıkıştırma biçimlerini belirlemek için hedef cihazlarınızda aşağıdaki kodu çalıştırın:

    Kotlin

    var extensions = gl.glGetString(GL10.GL_EXTENSIONS)
    

    Java

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

    Uyarı: Bu çağrının sonuçları cihaz modeline göre değişir! Hangi sıkıştırma türlerinin yaygın olarak desteklendiğini belirlemek için bu çağrıyı birkaç hedef cihazda çalıştırmanız gerekir.

  2. Cihazda hangi OpenGL uzantılarının desteklendiğini belirlemek için bu yöntemin sonucunu inceleyin.

Android Uzantı Paketi (AEP)

AEP, uygulamanızın OpenGL 3.1 spesifikasyonunda açıklanan çekirdek grubun ötesinde standartlaştırılmış bir OpenGL uzantıları grubunu desteklemesini sağlar. Bu uzantıların bir arada sunulması, tüm cihazlarda tutarlı bir işlevsellik grubunu teşvik ederken geliştiricilerin en yeni mobil GPU cihazlarından tam olarak yararlanmalarını sağlar.

AEP, parça gölgelendiricilerdeki resim, gölgelendirici depolama arabellek ve atom sayaç desteğini de iyileştirir.

Uygulamanızın AEP'yi kullanabilmesi için uygulamanın manifesti, AEP'nin gerekli olduğunu beyan etmelidir. Ayrıca, platform sürümü bunu desteklemelidir.

AEP şartını manifest dosyasında aşağıdaki şekilde beyan edin:

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

Platform sürümünün AEP'yi desteklediğini doğrulamak için FEATURE_OPENGLES_EXTENSION_PACK bağımsız değişken olarak geçirerek hasSystemFeature(String) yöntemini kullanın. Aşağıdaki kod snippet'inde bunun nasıl yapılacağına dair bir örnek gösterilmektedir:

Kotlin

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

Java

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

Yöntem true (doğru) değerini döndürürse AEP desteklenir.

AEP hakkında daha fazla bilgi için Khronos OpenGL ES Registry'deki sayfasını ziyaret edin.

OpenGL ES sürümünü kontrol etme

Android cihazlarda kullanılabilen birkaç OpenGL ES sürümü vardır. Uygulamanızın gerektirdiği minimum API sürümünü manifestinizde belirtebilirsiniz. Ancak aynı zamanda daha yeni bir API'nin özelliklerinden yararlanmak da isteyebilirsiniz. Örneğin, OpenGL ES 3.0 API'sı, API'nin 2.0 sürümüyle geriye dönük uyumludur. Bu yüzden uygulamanızı OpenGL ES 3.0 özelliklerini kullanacak ancak 3.0 API'si kullanılamıyorsa geri 2.0 API'sını kullanacak şekilde yazmak isteyebilirsiniz.

Uygulama manifestinizde gerekli minimumdan daha yüksek bir sürümdeki OpenGL ES özelliklerini kullanmadan önce, uygulamanız, cihazdaki API sürümünü kontrol etmelidir. Bunu iki yöntemden birini kullanarak yapabilirsiniz:

  1. Daha üst düzey OpenGL ES bağlamını (EGLContext) oluşturmayı deneyin ve sonucu kontrol edin.
  2. Minimum desteklenen bir OpenGL ES bağlamı oluşturun ve sürüm değerini kontrol edin.

Aşağıdaki örnek kod, bir EGLContext oluşturup sonucu kontrol ederek mevcut OpenGL ES sürümünün nasıl kontrol edileceğini gösterir. Bu örnekte, OpenGL ES 3.0 sürümünün nasıl kontrol edileceği gösterilmektedir:

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

Yukarıdaki createContext() yöntemi null değerini döndürürse kodunuz bunun yerine bir OpenGL ES 2.0 bağlamı oluşturmalı ve yalnızca bu API'yi kullanmaya devam etmelidir.

Aşağıdaki kod örneği, önce minimum desteklenen bağlam oluşturup ardından sürüm dizesini kontrol ederek OpenGL ES sürümünün nasıl kontrol edileceğini gösterir:

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.

Bu yaklaşımla, cihazın daha üst düzey bir API sürümünü desteklediğini keşfederseniz minimum OpenGL ES bağlamını kaldırmanız ve mevcut daha yüksek API sürümüyle yeni bir bağlam oluşturmanız gerekir.

OpenGL API sürümü seçme

OpenGL ES 1.0 API sürümü (ve 1.1 uzantıları), sürüm 2.0 ve sürüm 3.0'ın tümü 3D oyunlar, görselleştirmeler ve kullanıcı arayüzleri oluşturmak için yüksek performanslı grafik arayüzleri sunar. OpenGL ES 2.0 ve 3.0 için grafik planlaması büyük ölçüde benzerdir. 3.0 sürümü, 2.0 API'nin ek özelliklere sahip bir üst kümesini temsil eder. OpenGL ES 1.0/1.1 API ile OpenGL ES 2.0 ve 3.0 için yapılan programlama arasında önemli farklar vardır. Bu nedenle, geliştiricilerin bu API'lerle geliştirmeye başlamadan önce aşağıdaki faktörleri dikkate alması gerekir:

  • Performans: Genel olarak OpenGL ES 2.0 ve 3.0, ES 1.0/1.1 API'lerinden daha hızlı grafik performansı sağlar. Ancak performans farkı, donanım üreticisinin OpenGL ES grafik ardışık düzenini uygulamasındaki farklılıklardan dolayı OpenGL uygulamanızın çalıştığı Android cihaza bağlı olarak değişebilir.
  • Cihaz Uyumluluğu - Geliştiriciler, müşterilerine sunulan cihaz türlerini, Android sürümlerini ve OpenGL ES sürümlerini göz önünde bulundurmalıdır. Cihazlar arasında OpenGL uyumluluğu hakkında daha fazla bilgi edinmek için OpenGL sürümleri ve cihaz uyumluluğu bölümüne bakın.
  • Kodlama Kolaylığı - OpenGL ES 1.0/1.1 API'si, OpenGL ES 2.0 veya 3.0 API'lerinde bulunmayan sabit işlev ardışık düzeni ve kolaylık işlevleri sağlar. OpenGL ES'yi kullanmaya yeni başlayan geliştiriciler, 1.0/1.1 sürümü için kodlamayı daha hızlı ve daha kolay bulabilir.
  • Grafik Denetimi - OpenGL ES 2.0 ve 3.0 API'leri, gölgelendiriciler sayesinde tamamen programlanabilir bir ardışık düzen sağlayarak daha yüksek düzeyde kontrol sağlar. Grafik işleme ardışık düzeni üzerinde daha doğrudan kontrole sahip olan geliştiriciler, 1.0/1.1 API'yi kullanarak oluşturulması çok zor olacak efektler oluşturabilir.
  • Doku Desteği: OpenGL ES 3.0 API, şeffaflığı destekleyen ETC2 sıkıştırma biçiminin kullanılabilirliğini garanti ettiği için doku sıkıştırma için en iyi desteğe sahiptir. 1.x ve 2.0 API uygulamaları genellikle ETC1 desteğini içerir ancak bu doku biçimi şeffaflığı desteklemez. Bu nedenle normalde hedeflediğiniz cihazların desteklediği diğer sıkıştırma biçimlerinde kaynak sağlamanız gerekir. Daha fazla bilgi için Doku sıkıştırma desteği bölümüne bakın.

Performans, uyumluluk, kolaylık, kontrol ve diğer faktörler kararınızı etkileyebilir, ancak kullanıcılarınız için en iyi deneyimi sağladığını düşündüğünüze dayalı bir OpenGL API sürümü seçmeniz gerekir.