OpenGL ES

يشتمل Android على رسومات ثنائية وثلاثية الأبعاد عالية الأداء من خلال Open Graphics Library (OpenGL®)، لا سيما واجهة OpenGL ES API. OpenGL هو واجهة برمجة تطبيقات للرسومات عبر الأنظمة الأساسية تحدد واجهة برنامج قياسية لأجهزة معالجة الرسومات ثلاثية الأبعاد. أمّا OpenGL ES، فهو يتطابق مع مواصفات OpenGL المصمّمة للأجهزة المضمّنة. يتوافق نظام التشغيل Android مع العديد من إصدارات واجهة برمجة التطبيقات OpenGL ES:

  • OpenGL ES 2.0 - تتوافق مواصفات واجهة برمجة التطبيقات هذه مع الإصدار Android 2.2 (المستوى 8 لواجهة برمجة التطبيقات) والإصدارات الأحدث.
  • OpenGL ES 3.0 - يتم دعم مواصفات واجهة برمجة التطبيقات هذه في الإصدار Android 4.3 (المستوى 18) والإصدارات الأحدث.
  • OpenGL ES 3.1 - تتوافق مواصفات واجهة برمجة التطبيقات هذه مع الإصدار Android 5.0 (المستوى 21 من واجهة برمجة التطبيقات) والإصدارات الأحدث.
  • OpenGL ES 3.2 - تتوافق مواصفات واجهة برمجة التطبيقات هذه مع الإصدار Android 7.0 (المستوى 24 من واجهة برمجة التطبيقات) والإصدارات الأحدث.

تحذير: بغض النظر عن إصدار نظام Android الأساسي، لا يمكن للجهاز استخدام واجهة برمجة التطبيقات OpenGL ES 3.0 ما لم توفّر الشركة المصنّعة للجهاز عملية تنفيذ لمسار الرسومات هذا. وإذا حدّدت في البيان أنّ OpenGL ES 3.0 مطلوب، يمكنك التأكّد من توفّر هذا الإصدار على الجهاز. إذا حددت أن يلزم استخدام إصدار من مستوى أدنى، ولكنك تريد استخدام ميزات الإصدار 3.0 في حال توفرها، يجب التحقق في وقت التشغيل لمعرفة إصدار OpenGL المتوافق مع الجهاز. ولمزيد من المعلومات حول طريقة إجراء ذلك، يمكنك الاطّلاع على التحقق من إصدار OpenGL ES.

ملاحظة: يتوافق Android مع OpenGL ES 1.0 و1.1، ولكن تم إيقاف هذَين الإصدارَين من واجهة برمجة التطبيقات نهائيًا ويجب ألا يتم استخدامهما في التطبيقات الحديثة.

ملاحظة: تشبه واجهة برمجة التطبيقات المحددة التي يوفرها إطار عمل Android واجهة برمجة التطبيقات J2ME JSR239 OpenGL ES API، ولكنها ليست متطابقة. إذا كنت على دراية بمواصفات J2ME JSR239، ننصحك بالانتباه إلى أي اختلافات.

راجع أيضًا

الأساسيات

يدعم Android برنامج OpenGL من خلال واجهة برمجة التطبيقات لإطار العمل وحزمة تطوير البرامج الأصلية (NDK). يركز هذا الموضوع على واجهات إطار عمل Android. لمزيد من المعلومات حول NDK، راجع Android NDK.

هناك فئتان أساسيتان في إطار عمل Android تتيحان لك إنشاء الرسومات ومعالجتها باستخدام OpenGL ES API، وهما: GLSurfaceView وGLSurfaceView.Renderer. إذا كان هدفك هو استخدام OpenGL في تطبيق Android، فيجب أن يكون هدفك الأول هو فهم كيفية تنفيذ هذه الفئات في نشاط معيّن.

GLSurfaceView
هذه الفئة هي View يمكنك فيها رسم العناصر ومعالجتها باستخدام طلبات البيانات من واجهة برمجة التطبيقات OpenGL، وهي تتشابه في وظيفتها مع SurfaceView. يمكنك استخدام هذه الفئة من خلال إنشاء مثيل GLSurfaceView وإضافة Renderer إليه. وإذا أردت تسجيل أحداث الشاشة التي تعمل باللمس، عليك توسيع الفئة GLSurfaceView لتنفيذ أدوات معالجة اللمس، كما هو موضَّح في درس تدريب OpenGL، الاستجابة لأحداث اللمس.
GLSurfaceView.Renderer
تحدِّد هذه الواجهة الطرق المطلوبة لرسم الرسومات في GLSurfaceView. يجب توفير تنفيذ هذه الواجهة كفئة منفصلة وإرفاقها بمثيل GLSurfaceView باستخدام GLSurfaceView.setRenderer().

تتطلب واجهة GLSurfaceView.Renderer تنفيذ الطرق التالية:

  • onSurfaceCreated(): يطلب النظام هذه الطريقة مرة واحدة عند إنشاء GLSurfaceView. استخدِم هذه الطريقة لتنفيذ الإجراءات التي يجب تنفيذها مرة واحدة فقط، مثل ضبط معلَمات بيئة OpenGL أو إعداد كائنات رسومات OpenGL.
  • onDrawFrame(): يستدعي النظام هذه الطريقة عند كل عملية إعادة سحب لـ GLSurfaceView. استخدِم هذه الطريقة كنقطة تنفيذ أساسية لرسم عناصر رسومية (وإعادة رسمها).
  • onSurfaceChanged(): يطلب النظام هذه الطريقة عندما يتغيّر الشكل الهندسي GLSurfaceView، بما في ذلك التغيُّرات في حجم GLSurfaceView أو اتجاه شاشة الجهاز. على سبيل المثال، يطلب النظام هذه الطريقة عندما يتغيّر الجهاز من الاتجاه العمودي إلى الاتجاه الأفقي. استخدِم هذه الطريقة للاستجابة للتغييرات في حاوية GLSurfaceView.

حزم OpenGL ES

بعد إنشاء عرض حاوية لـ OpenGL ES باستخدام GLSurfaceView وGLSurfaceView.Renderer، يمكنك البدء في استدعاء واجهات برمجة تطبيقات OpenGL باستخدام الفئات التالية:

  • فئة واجهة برمجة التطبيقات OpenGL ES 2.0
    • android.opengl.GLES20 - توفِّر هذه الحزمة واجهة OpenGL ES 2.0 وتتوفّر بدءًا من Android 2.2 (المستوى 8 من واجهة برمجة التطبيقات).
  • حِزم واجهة برمجة التطبيقات OpenGL ES 3.0/3.1/3.2
    • android.opengl - توفِّر هذه الحزمة الواجهة لفئات OpenGL ES 3.0/3.1. يتوفّر الإصدار 3.0 بدءًا من Android 4.3 (المستوى 18 من واجهة برمجة التطبيقات). يتوفر الإصدار 3.1 بدءًا من Android 5.0 (المستوى 21 من واجهة برمجة التطبيقات). يتوفّر الإصدار 3.2 بدءًا من Android 7.0 (المستوى 24 من واجهة برمجة التطبيقات).

إذا أردت البدء في إنشاء تطبيق باستخدام OpenGL ES على الفور، اتّبِع الفئة عرض الرسومات باستخدام OpenGL ES.

تعريف متطلبات OpenGL

إذا كان تطبيقك يستخدم ميزات OpenGL غير المتوفّرة على جميع الأجهزة، يجب تضمين هذه المتطلبات في ملف AndroidManifest.xml. في ما يلي بيانات بيان OpenGL الأكثر شيوعًا:

  • متطلبات إصدار OpenGL ES: إذا كان تطبيقك يتطلب إصدارًا معيّنًا من OpenGL ES، يجب الإفصاح عن هذا الشرط عن طريق إضافة الإعدادات التالية إلى بيان التطبيق كما هو موضّح أدناه.

    بالنسبة إلى OpenGL ES 2.0:

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

    تؤدي إضافة هذا البيان إلى منع Google Play من تثبيت تطبيقك على الأجهزة التي لا تتوافق مع OpenGL ES 2.0. إذا كان تطبيقك مخصّصًا حصريًا للأجهزة التي تتوافق مع OpenGL ES 3.0، يمكنك أيضًا تحديد ذلك في البيان:

    بالنسبة إلى OpenGL ES 3.0:

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

    بالنسبة إلى OpenGL ES 3.1:

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

    بالنسبة إلى OpenGL ES 3.2:

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

    ملاحظة: تتوافق واجهة برمجة التطبيقات OpenGL ES 3.x مع الإصدارات القديمة من 2.0 API، ما يعني أنّه يمكنك أن تصبح أكثر مرونة عند تنفيذ OpenGL ES في تطبيقك. وبعد الإعلان عن تضمين OpenGL ES 2.0 API في ملف البيان، يمكنك استخدام إصدار واجهة برمجة التطبيقات هذا كإعداد تلقائي، والتأكّد من توفّر واجهة برمجة التطبيقات 3.x API في وقت التشغيل، ثم استخدام ميزات OpenGL ES 3.x إذا كان الجهاز يتيح استخدامها. لمزيد من المعلومات حول التحقق من إصدار OpenGL ES المتوافق مع الجهاز، يمكنك الاطّلاع على التحقق من إصدار OpenGL ES.

  • متطلبات ضغط البنية - إذا كان التطبيق يستخدم تنسيقات ضغط الهيئة، يجب الإفصاح عن التنسيقات التي يدعمها تطبيقك في ملف البيان باستخدام <supports-gl-texture>. للمزيد من المعلومات حول تنسيقات ضغط البنية المتاحة، يمكنك الاطّلاع على إتاحة ضغط الهيئة.

    يؤدي تعريف متطلبات ضغط البنية في البيان إلى إخفاء تطبيقك عن المستخدمين الذين لديهم أجهزة لا تتوافق مع نوع واحد على الأقل من أنواع الضغط التي أفصحتَ عنها في البيان. للحصول على مزيد من المعلومات حول آلية عمل فلاتر Google Play لضغط المواد، يمكنك الاطّلاع على قسم Google Play وفلترة ضغط البنية ضمن مستندات <supports-gl-texture>.

تعيين إحداثيات للكائنات المرسومة

تتمثل إحدى المشكلات الأساسية في عرض الرسومات على أجهزة Android في أن شاشاتها قد تختلف من حيث الحجم والشكل. يفترض OpenGL نظام إحداثيات مربعًا موحدًا، ويرسم افتراضيًا تلك الإحداثيات بسعادة على شاشتك غير المربعة عادةً كما لو كانت مربعة تمامًا.

الشكل 1. تم ربط نظام تنسيق OpenGL التلقائي (الأيسر) بشاشة جهاز Android عادية (على اليمين).

يوضح الرسم التوضيحي أعلاه نظام الإحداثيات الموحّد المُفترض لإطار OpenGL على اليسار، وكيف يتم ربط هذه الإحداثيات بشاشة جهاز عادية في اتجاه أفقي على اليمين. ولحل هذه المشكلة، يمكنك تطبيق أوضاع عرض OpenGL وعروض الكاميرا لتحويل الإحداثيات حتى تكون العناصر الرسومية لديك النسب الصحيحة على أي شاشة.

لتطبيق الإسقاط وطرق عرض الكاميرا، يمكنك إنشاء مصفوفة عرض ومصفوفة عرض الكاميرا وتطبيقهما على مسار عرض OpenGL. تعيد مصفوفة العرض حساب إحداثيات الرسومات بحيث يتم ربطها بشكل صحيح مع شاشات أجهزة Android. تنشئ مصفوفة عرض الكاميرا عملية تحويل تعرض الكائنات من موضع عين معين.

الإسقاط وعرض الكاميرا في OpenGL ES 2.0 والإصدارات الأحدث

في واجهات برمجة التطبيقات ES 2.0 و3.0، يمكنك تطبيق الإسقاط وعرض الكاميرا من خلال إضافة عضو مصفوفة أولاً إلى عناصر تظليل الرؤوس لكائنات الرسومات. مع إضافة عضو المصفوفة هذا، يمكنك بعد ذلك إنشاء وتطبيق مصفوفات عرض الكاميرا والإسقاط على الكائنات الخاصة بك.

  1. إضافة مصفوفة إلى أدوات تظليل الرأس - يمكنك إنشاء متغيّر لمصفوفة إسقاط طريقة العرض وتضمينه كمُضاعِف لموضع أداة التظليل. في المثال التالي لرمز أداة تظليل الرأس، يتيح لك العنصر uMVPMatrix المضمَّن تطبيق مصفوفات العرض والكاميرا على إحداثيات العناصر التي تستخدم أداة التظليل هذه.

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

    ملاحظة: يحدِّد المثال أعلاه عضوًا في مصفوفة تحويل واحدة في أداة تظليل الرأس التي تطبِّق عليها مصفوفة عرض مدمجة ومصفوفة عرض الكاميرا. بناءً على متطلبات التطبيق، قد تحتاج إلى تحديد أعضاء مصفوفة عرض منفصلة وأعضاء مصفوفة عرض الكاميرا في مظلات الرأس حتى تتمكن من تغييرها بشكل مستقل.

  2. الوصول إلى مصفوفة أداة التظليل: بعد إنشاء خطاف في مظلات الرأس لتطبيق العرض والكاميرا، يمكنك الوصول إلى ذلك المتغير لتطبيق مصفوفات العرض والكاميرا. يوضِّح الرمز التالي كيفية تعديل طريقة onSurfaceCreated() لتنفيذ GLSurfaceView.Renderer للوصول إلى متغيّر المصفوفة المحدّد في أداة تظليل الرأس أعلاه.

    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. إنشاء مصفوفات الإسقاط وعرض الكاميرا - قم بإنشاء مصفوفات الإسقاط والعرض لتطبيق الكائنات الرسومية. يعرض الرمز في المثال التالي كيفية تعديل طريقتَي onSurfaceCreated() وonSurfaceChanged() لتنفيذ GLSurfaceView.Renderer لإنشاء مصفوفة عرض الكاميرا ومصفوفة عرض استنادًا إلى نسبة العرض إلى الارتفاع في شاشة الجهاز.

    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. تطبيق مصفوفات الإسقاط وعرض الكاميرا - لتطبيق تغييرات الإسقاط وعرض الكاميرا، اضرب المصفوفتين معًا ثم ضعهما في شكل الرأس. يوضّح الرمز في المثال التالي كيفية تعديل طريقة onDrawFrame() في تنفيذ GLSurfaceView.Renderer لدمج مصفوفة العرض وعرض الكاميرا التي تم إنشاؤها في الرمز أعلاه ثم تطبيق الطريقة على كائنات الرسومات التي سيتم عرضها باستخدام 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
        ...
    }
    

للحصول على مثال كامل حول طريقة تطبيق العرض وعرض الكاميرا باستخدام OpenGL ES 2.0، يمكنك الاطّلاع على الفئة عرض الرسومات باستخدام OpenGL ES.

تشكيل الوجوه المتعرجة

في OpenGL، يكون وجه الشكل عبارة عن سطح يتم تحديده بثلاث نقاط أو أكثر في مساحة ثلاثية الأبعاد. تحتوي مجموعة النقاط الثلاث أو أكثر (تسمى الرؤوس في OpenGL) على وجهين أمامي وخلفي. كيف تعرف الوجه الأمامي والخلفي؟ هذا سؤال وجيه. تتعلق الإجابة بالاتجاه المتعرج، أو بالاتجاه الذي تحدد فيه نقاط الشكل.

الإحداثيات على رؤوس المثلث

الشكل 1. رسم توضيحي لقائمة إحداثي يُترجم إلى ترتيب رسم عكس عقارب الساعة.

في هذا المثال، يتم تحديد نقاط المثلث بترتيب يتم رسمها في اتجاه عكس عقارب الساعة. يحدد الترتيب الذي يتم به رسم هذه الإحداثيات الاتجاه المتعرج للشكل. وفقًا للإعدادات التلقائية، في OpenGL، يكون الوجه المرسوم عكس اتجاه عقارب الساعة هو الوجه الأمامي. يتم تعريف المثلث المعروض في الشكل 1 بحيث تنظر إلى الوجه الأمامي للشكل (كما يتم تفسيره بواسطة OpenGL) والجانب الآخر هو الوجه الخلفي.

لماذا من المهم معرفة وجه الشكل هو الوجه الأمامي؟ تتعلق الإجابة بميزة OpenGL الشائعة المعروفة باسم "اختيار الوجه". تعتبر ميزة اختيار الوجه خيارًا في بيئة OpenGL، وهي تتيح لمسار العرض تجاهُل (عدم احتساب أو رسم) الوجه الخلفي للشكل، ما يوفّر الوقت والذاكرة ودورات المعالجة:

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

إذا حاولت استخدام ميزة انتقاء الوجوه بدون معرفة جوانب الأشكال في الأمام والخلف، فستبدو رسومات OpenGL قليلاً، أو قد لا تظهر على الإطلاق. لذا، يجب دائمًا تحديد إحداثيات OpenGL بترتيب رسم عكس اتجاه عقارب الساعة.

ملاحظة: من الممكن ضبط بيئة OpenGL لتتعامل مع الوجه في اتجاه عقارب الساعة باعتباره الوجه الأمامي، إلا أن إجراء ذلك يتطلب المزيد من الرموز وقد يؤدي إلى إرباك مطوّري OpenGL ذوي الخبرة عندما تطلب منهم المساعدة. لذا لا تفعل ذلك.

إصدارات OpenGL وتوافقها مع الأجهزة

تتوافق مواصفات OpenGL ES 1.0 و1.1 API منذ نظام Android 1.0. تختلف برمجة الرسومات مع OpenGL ES 1.0/1.1 API إلى حد كبير عن استخدام الإصدار 2.0 والإصدارات الأحدث. يتوافق OpenGL ES 2.0 على جميع أجهزة Android التي تبدأ بالإصدار Android 2.2 (المستوى 8 من واجهة برمجة التطبيقات) وهو الإصدار الأقدم المقترَح للتطبيقات الجديدة التي يتم تطويرها باستخدام OpenGL ES. يتوافق OpenGL ES 3.0 مع الإصدار Android 4.3 (المستوى 18 لواجهة برمجة التطبيقات) والإصدارات الأحدث على الأجهزة التي توفّر إمكانية تنفيذ OpenGL ES 3.0 API. وللحصول على معلومات حول العدد النسبي للأجهزة التي تعمل بنظام التشغيل Android والتي تتوافق مع إصدار معيّن من OpenGL ES، يُرجى الاطّلاع على لوحة بيانات إصدار OpenGL ES.

يجب عليك التفكير بعناية في متطلبات الرسومات واختيار إصدار واجهة برمجة التطبيقات المناسب لتطبيقك بشكل أفضل. لمزيد من المعلومات، يُرجى الاطّلاع على اختيار إصدار OpenGL API.

توفّر واجهة OpenGL ES 3.0 API ميزات إضافية وأداءً أفضل مقارنةً بالإصدار 2.0 API، وهي متوافقة أيضًا مع الأنظمة القديمة. وهذا يعني أنّه يمكنك على الأرجح كتابة تطبيقك الذي يستهدف OpenGL ES 2.0 وتضمين ميزات رسومات OpenGL ES 3.0 بشكل مشروط في حال توفّرها. لمزيد من المعلومات حول التحقق من مدى توفّر 3.0 API، يمكنك الاطّلاع على التحقق من إصدار OpenGL ES.

إتاحة ضغط الهيئة

يمكن أن يؤدي ضغط الهيئة إلى زيادة أداء تطبيق OpenGL بشكل كبير عن طريق تقليل متطلبات الذاكرة والاستفادة بشكل أكثر فعالية من معدل نقل بيانات الذاكرة. يوفّر إطار عمل Android إمكانية استخدام تنسيق ضغط ETC1 كميزة عادية، بما في ذلك فئة الأدوات ETC1Util وأداة الضغط etc1tool (المتوفّرة في حزمة تطوير البرامج (SDK) لنظام التشغيل Android على <sdk>/tools/). للحصول على مثال على تطبيق Android يستخدم ضغط الهيئة، اطّلِع على نموذج الرمز البرمجي CompressedTextureActivity في حزمة تطوير البرامج (SDK) لنظام التشغيل Android (<sdk>/samples/<version>/ApiDemos/src/com/example/android/apis/graphics/).

يتوافق تنسيق ETC1 مع جميع أجهزة Android المتوافقة مع OpenGL ES 2.0 أو الإصدارات الأحدث.

ملاحظة: لا يدعم تنسيق ضغط البنية ETC1 الزخارف ذات الشفافية (قناة ألفا). إذا كان التطبيق يتطلب زخارف بشفافية، فيجب التحقق من تنسيقات ضغط البنية الأخرى المتاحة على الأجهزة المستهدفة. تتمثل طريقة عرض زخارف قناة ألفا باستخدام ETC1 في ربط كائنين من كائنات نسيج ETC1: الأول مع بيانات اللون، والثاني مع بيانات قناة ألفا، ثم دمج القيم من اثنين من الزخارف في أداة تظليل الأجزاء.

يمكن ضمان توفُّر تنسيقات ضغط البنية ETC2/EAC عند استخدام واجهة برمجة التطبيقات OpenGL ES 3.0. يوفر تنسيق المظهر هذا نسب ضغط ممتازة مع جودة مرئية عالية ويدعم التنسيق أيضًا الشفافية (قناة ألفا).

بالإضافة إلى تنسيقات ETC، تتيح أجهزة Android ضغط القوام استنادًا إلى شرائح وحدة معالجة الرسومات وعمليات تنفيذ OpenGL. يجب عليك التحقق من إمكانية استخدام ضغط المظهر على الأجهزة التي تستهدفها لتحديد أنواع الضغط التي يجب أن يدعمها تطبيقك. لتحديد تنسيقات الزخرفة المتوافقة مع جهاز معيّن، يجب إجراء طلب بحث عن الجهاز ومراجعة أسماء إضافات OpenGL، التي تحدد تنسيقات ضغط البنية (وميزات OpenGL الأخرى) المتوافقة مع الجهاز. في ما يلي بعض تنسيقات ضغط الهيئة التي تكون شائعة الاستخدام:

  • ضغط الهيئة القابل للتكيّف والقابل للتوسع (ASTC) - تنسيق لضغط الهيئة تم تصميمه ليحل محل التنسيقات السابقة. أكثر مرونة من التنسيقات السابقة بسبب توافقها مع أحجام قوالب مختلفة.
    • GL_KHR_texture_compression_astc_ldr
    • GL_KHR_texture_compression_astc_hdr(النطاق الديناميكي العالي)
  • S3TC (DXTn/DXTC): هناك عدة أشكال لضغط البنية S3 (S3TC) (من DXT1 إلى DXT5) وهي متاحة بشكل أقل على نطاق واسع. يتوافق هذا التنسيق مع زخارف RGB مع قنوات ألفا 4 بت أو 8 بت. ويتم تمثيل هذه التنسيقات باسم إضافة OpenGL التالي:
    • GL_EXT_texture_compression_s3tc
    لا تتيح بعض الأجهزة سوى استخدام صيغة تنسيق DXT1، ويتم تمثيل هذا الدعم المحدود باسم إضافة OpenGL التالي:
    • GL_EXT_texture_compression_dxt1

تعتبر تنسيقات ضغط المادة التالية تنسيقات قديمة ولا يُنصح باستخدامها في التطبيقات الجديدة:

  • ATITC (ATC) - يتوفر ضغط بنية ATI (ATITC أو ATC) على مجموعة متنوعة من الأجهزة ويتيح الضغط بمعدل ثابت لزخارف نموذج أحمر أخضر أزرق مع قناة ألفا أو بدونها. قد يتم تمثيل هذا التنسيق بالعديد من أسماء إضافات OpenGL، على سبيل المثال:
    • GL_AMD_compressed_ATC_texture
    • GL_ATI_texture_compression_atitc
  • PVRTC - يتوفر ضغط المظهر (PVRTC) على مجموعة متنوعة من الأجهزة ويتوافق مع زخارف 2 بت و4 بت لكل بكسل مع قناة ألفا أو بدونها. ويتم تمثيل هذا التنسيق باسم إضافة OpenGL التالي:
    • GL_IMG_texture_compression_pvrtc
  • 3DC - تنسيق ضغط البنية 3DC (3DC) هو تنسيق أقل استخدامًا ويتيح استخدام زخارف نموذج أحمر أخضر أزرق مع قناة ألفا. ويتم تمثيل هذا التنسيق باسم إضافة OpenGL التالي:
    • GL_AMD_compressed_3DC_texture

تحذير: إنّ تنسيقات ضغط البنية هذه غير متوافقة على جميع الأجهزة. وقد يختلف اعتماد هذه التنسيقات حسب الشركة المصنّعة والجهاز. للحصول على معلومات حول كيفية تحديد تنسيقات ضغط البنية على جهاز معين، يُرجى الاطّلاع على القسم التالي.

ملاحظة: بعد تحديد تنسيقات ضغط البنية التي سيتوافق معها تطبيقك، احرص على تعريفها في بيان التطبيق باستخدام <supports-gl-texture> . يؤدي استخدام هذا البيان إلى تفعيل الفلترة حسب الخدمات الخارجية مثل Google Play، بحيث يتم تثبيت تطبيقك فقط على الأجهزة التي تتوافق مع التنسيقات التي يتطلبها تطبيقك. للحصول على التفاصيل، يُرجى الاطّلاع على بيانات بيان OpenGL.

تحديد إضافات OpenGL

تختلف عمليات تنفيذ OpenGL حسب جهاز Android من حيث الإضافات المتوافقة مع OpenGL ES API. تتضمن هذه الإضافات ضغطات القوام، ولكنها عادةً ما تتضمن أيضًا إضافات أخرى إلى مجموعة ميزات OpenGL.

لتحديد تنسيقات ضغط البنية وإضافات OpenGL الأخرى المتوافقة مع جهاز معيّن:

  1. شغِّل الرمز التالي على الأجهزة المستهدفة لتحديد تنسيقات ضغط المادة المتوافقة:

    Kotlin

    var extensions = gl.glGetString(GL10.GL_EXTENSIONS)
    

    Java

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

    تحذير: تختلف نتائج هذه المكالمة حسب طراز الجهاز. يجب إجراء هذا الطلب على عدة أجهزة مستهدفة لتحديد أنواع الضغط المتوافقة بشكل شائع.

  2. راجِع نتائج هذه الطريقة لتحديد إضافات OpenGL المتوافقة مع الجهاز.

حزمة إضافات Android (AEP)

يضمن AEP أن تطبيقك يتوافق مع مجموعة موحّدة من إضافات OpenGL بما يتجاوز المجموعة الأساسية الموضّحة في مواصفات OpenGL 3.1. يؤدي تجميع هذه الإضافات معًا إلى تعزيز استخدام مجموعة متسقة من الوظائف على مستوى الأجهزة، مع السماح للمطوّرين بالاستفادة الكاملة من أحدث نسخة من أجهزة وحدة معالجة الرسومات على الأجهزة الجوّالة.

يحسّن AEP أيضًا إمكانية احتواء الصور والتخزينات الاحتياطية لأدوات تظليل الأجزاء والعدادات البسيطة في أدوات تظليل الأجزاء.

ولكي يتمكّن التطبيق من استخدام AEP، يجب أن يوضِّح بيان التطبيق أنّه مطلوب. بالإضافة إلى ذلك، يجب أن يكون إصدار النظام الأساسي متوافقًا.

يتم تضمين جميع الميزات الإضافية المحددة في AEP في مواصفات OpenGL ES 3.2 الأساسية. إذا كان تطبيقك يتطلب OpenGL ES 3.2، لن تحتاج إلى طلب AEP.

يُرجى تعريف متطلبات سياسة AEP في البيان على النحو التالي:

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

للتحقّق من أنّ إصدار النظام الأساسي يتوافق مع AEP، استخدِم الإجراء hasSystemFeature(String) وتمرير FEATURE_OPENGLES_EXTENSION_PACK كوسيطة. يوضح مقتطف الرمز التالي مثالاً على كيفية القيام بذلك:

Kotlin

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

Java

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

إذا كانت الطريقة صحيحة، يعني هذا أنّ AEP متاح.

لمزيد من المعلومات حول AEP، يُرجى الانتقال إلى صفحته على Khronos OpenGL ES Registry.

التحقُّق من إصدار OpenGL ES

تتوفّر العديد من إصدارات OpenGL ES على أجهزة Android. يمكنك تحديد الإصدار الأدنى من واجهة برمجة التطبيقات التي يتطلبها تطبيقك في البيان، ولكن قد ترغب أيضًا في الاستفادة من الميزات المتوفرة في واجهة برمجة تطبيقات أحدث في الوقت نفسه. على سبيل المثال، تتوافق واجهة برمجة التطبيقات OpenGL ES 3.0 مع الإصدار 2.0 من واجهة برمجة التطبيقات، لذا قد تحتاج إلى كتابة بيانات تطبيقك بحيث يستخدم ميزات OpenGL ES 3.0، ولكنه يعود إلى الإصدار 2.0 API إذا لم تكُن واجهة برمجة التطبيقات 3.0 متاحة.

قبل استخدام ميزات OpenGL ES من إصدار أعلى من الحد الأدنى المطلوب في بيان التطبيق، يجب أن يتحقّق التطبيق من إصدار واجهة برمجة التطبيقات المتاحة على الجهاز. يمكنك القيام بذلك بطريقتين:

  1. حاوِل إنشاء سياق OpenGL ES بمستوى أعلى (EGLContext) وتحقَّق من النتيجة.
  2. أنشئ سياق OpenGL ES المتاح بالحد الأدنى وتحقَّق من قيمة الإصدار.

يوضّح الرمز في المثال التالي كيفية التحقّق من إصدار OpenGL ES المتاح من خلال إنشاء EGLContext والتحقّق من النتيجة. يوضح هذا المثال كيفية التحقق من إصدار 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;
  }
}

إذا عرضت طريقة createContext() أعلاه قيمة فارغة، يجب أن ينشئ الرمز سياق OpenGL ES 2.0 بدلاً من ذلك وأن يعود إلى استخدام واجهة برمجة التطبيقات هذه فقط.

يوضح مثال الرمز البرمجي التالي كيفية التحقق من إصدار OpenGL ES عن طريق إنشاء حدّ أدنى من السياق المتوافق أولاً، ثم التحقّق من سلسلة الإصدار:

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.

باستخدام هذه الطريقة، إذا اكتشفت أنّ الجهاز يتوافق مع إصدار واجهة برمجة تطبيقات بمستوى أعلى، يجب محو الحد الأدنى من سياق OpenGL ES وإنشاء سياق جديد باستخدام إصدار واجهة برمجة التطبيقات الأعلى المتاح.

اختيار إصدار OpenGL API

يوفّر الإصداران 2.0 و3.0 من OpenGL ES واجهات رسومات عالية الأداء لإنشاء ألعاب ثلاثية الأبعاد وعروض مرئية وواجهات مستخدم. وتشابه إلى حد كبير تطوير الرسومات للإصدارين 2.0 و3.0 من OpenGL ES، حيث يمثل الإصدار 3.0 مجموعة فرعية من واجهة برمجة التطبيقات 2.0 مع ميزات إضافية. تختلف برمجة OpenGL ES 1.0/1.1 API عن OpenGL ES 2.0 و3.0 بشكل كبير، ولا يُنصح بها للتطبيقات الجديدة. يجب على المطورين التفكير بعناية في العوامل التالية قبل البدء في التطوير باستخدام واجهات برمجة التطبيقات هذه:

  • التوافق مع الجهاز: على المطوّرين مراعاة أنواع الأجهزة وإصدارات Android وإصدارات OpenGL ES المتوفّرة لعملائهم. لمزيد من المعلومات حول توافق OpenGL على جميع الأجهزة، يُرجى مراجعة القسم إصدارات OpenGL وتوافقها مع الأجهزة.
  • التوافق مع المظهر: توفّر واجهة برمجة التطبيقات OpenGL ES 3.0 أفضل توافق مع ضغط القوام لأنه يضمن توفّر تنسيق ضغط ETC2 الذي يتوافق مع الشفافية. تتضمن عمليات تنفيذ واجهة برمجة التطبيقات 2.0 إمكانية استخدام ETC1، إلا أن تنسيق المظهر هذا لا يتيح الشفافية. لتطبيق الشفافية في الزخارف المضغوطة، يجب إما استخدام زخارف ETC1 (التقسيم بين اللون وألفا) أو توفير الموارد بتنسيقات ضغط أخرى متوافقة مع الأجهزة التي تستهدفها. لمزيد من المعلومات، يُرجى الاطّلاع على إتاحة ضغط الهيئة.

على الرغم من أنّ التوافق والزخرفة قد يؤثران في قرارك، يجب اختيار إصدار OpenGL API استنادًا إلى ما تعتقد أنّه يوفّر أفضل تجربة للمستخدمين.