OpenGL ES

מערכת Android כוללת תמיכה בגרפיקה דו-ממדית ותלת-ממדית בעלת ביצועים גבוהים באמצעות Open Graphics Library (OpenGL), באופן ספציפי, OpenGL ES API. OpenGL הוא API גרפיקה בפלטפורמות שונות מציין ממשק תוכנה סטנדרטי לחומרה לעיבוד גרפיקה בתלת ממד. OpenGL ES הוא גרסה של OpenGL מיועד למכשירים מוטמעים. מערכת Android תומכת בכמה גרסאות של OpenGL ES API:

  • OpenGL ES 2.0 – מפרט ה-API הזה נתמך על ידי Android מגרסה 2.2 (API ברמה 8) ואילך.
  • OpenGL ES 3.0 – מפרט ה-API הזה נתמך על ידי Android מגרסה 4.3 (רמת API 18) ואילך.
  • OpenGL ES 3.1 – מפרט ה-API הזה נתמך על ידי Android מגרסה 5.0 (רמת API 21) ואילך.
  • OpenGL ES 3.2 – מפרט ה-API הזה נתמך ב-Android מגרסה 7.0 (רמת API 24) ואילך.

אזהרה: ללא קשר לגרסת פלטפורמת Android, המכשיר לא יכול לתמוך את OpenGL ES 3.0 API אלא אם יצרן המכשיר מספק של צינור עיבוד הנתונים הגרפי הזה. אם תציינו במניפסט צריך להשתמש ב-OpenGL ES 3.0, אבל אין לך ספק שהגרסה הזו תהיה זמינה במכשיר. אם ציינתם שנדרשת גרסה ברמה נמוכה יותר, אבל אם רוצים להשתמש בתכונות 3.0, אם הן זמינות, צריך לבדוק אותן בזמן הריצה כדי לראות איזו גרסה של OpenGL נתמכת במכשיר. לקבלת מידע על האופן שבו לשם כך, ראו בדיקה של גרסת OpenGL ES.

הערה: מערכת Android כוללת תמיכה ב-OpenGL ES בגרסה 1.0 ובגרסה 1.1, אבל בגרסאות האלה של ה-API הוצאו משימוש ולא ישמשו באפליקציות מודרניות.

הערה: ממשק ה-API הספציפי שמסופק על ידי Android framework דומה ל-J2ME JSR239 OpenGL ES API, אבל אינה זהה. אם אתם מכירים את המפרט של J2ME JSR239, עליכם לשים לב למפרט של שונות.

ראה גם

העקרונות הבסיסיים

מערכת Android תומכת ב-OpenGL גם באמצעות framework API וגם דרך הפיתוח Native ערכה (NDK). הנושא הזה מתמקד בממשקים של Android framework. לקבלת מידע נוסף על NDK: לצפייה ב-Android NDK.

ב-framework של Android יש שני סיווגים בסיסיים שמאפשרים ליצור ולבצע פעולות. גרפיקה עם OpenGL ES API: GLSurfaceView ו GLSurfaceView.Renderer. אם היעד שלכם הוא להשתמש ב-OpenGL באפליקציית Android, המטרה הראשונה שלכם היא להבין איך ליישם את השיעורים האלה בפעילות.

GLSurfaceView
הכיתה הזו היא View שבה אפשר לשרטט ולשנות אובייקטים באמצעות קריאות ל-OpenGL API והוא דומה לפונקציה 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, אפשר להתחיל קריאה לממשקי API של OpenGL באמצעות המחלקות הבאות:

  • רמת API של OpenGL ES 2.0
    • android.opengl.GLES20 – החבילה הזו מספקת את הוא OpenGL ES 2.0 וזמין החל מ-Android 2.2 (רמת API 8).
  • OpenGL ES 3.0/3.1/3.2 חבילות API

כדי להתחיל לפתח אפליקציה עם 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 API תואם לאחור ל-API 2.0, מה שאומר שאתם יכולים גמיש ביישום של OpenGL ES. על ידי הצהרה על OpenGL ES 2.0 API כדרישה במניפסט, ניתן להשתמש בגרסת API זו כברירת מחדל, בדוק הזמינות של API 3.x בזמן הריצה ואז להשתמש בתכונות 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 ואילך

בממשקי ה-API של ES 2.0 ו-3.0, מחילים תצוגת מצלמה ומסך על ידי הוספת חבר במטריצה ועד לתוכנות ההצללה (shader) של הקודקודים של האובייקטים הגרפיים. כשמוסיפים את המטריצה, אפשר ליצור ולהחיל מטריצות של הקרנה ומצלמה על האובייקטים.

  1. הוספת מטריצה לתוכנות הצללה (shader) של קודקוד – יצירת משתנה למטריצת ההקרנה של התצוגה ולכלול אותו כמכפיל של מיקום הצללה. בדוגמה הבאה של תוכנת ההצללה (shader) של קודקוד קוד, החברות ב-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";
    

    הערה: הדוגמה שלמעלה מגדירה מטריצה יחידה של טרנספורמציה חבר בהצללה של קודקוד שעליו מחילים מטריצת היטל משולבת ותצוגת מצלמה במטריצה. בהתאם לדרישות האפליקציה, יכול להיות שתרצו להגדיר היטל נפרד מצלמה ומטריצה, שמציגים את המטריצות במטריצות בתוכנות הצללה (shader) של הקודקודים, כדי שאפשר יהיה לשנות אותן באופן עצמאי.

  2. לגשת למטריצת ההצללה – אחרי שיוצרים הוק (hooks) בגוון קודקודים להחיל היטל ותצוגת מצלמה, ניתן לגשת למשתנה הזה כדי להחיל היטל QKV. הקוד הבא מראה איך לשנות את השיטה 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 (רמת API 8) הגרסה המוקדמת ביותר שמומלצת לאפליקציות חדשות שפותחו באמצעות OpenGL ES. OpenGL ES 3.0 נתמך עם Android 4.3 (רמת API 18) ואילך, במכשירים שמספקים של OpenGL ES 3.0 API. לקבלת מידע על המספר היחסי של מכשירים מבוססי Android שתומכות בגרסה נתונה של OpenGL ES, אפשר לעיין מרכז הבקרה לגרסאות של OpenGL ES

עליך לשקול בקפידה את הדרישות הגרפיות ולבחור את ה-API המתאימה ביותר לאפליקציה שלכם. מידע נוסף זמין במאמר הבא: בחירת גרסת OpenGL API

OpenGL ES 3.0 API מספק תכונות נוספות וביצועים טובים יותר מאשר 2.0 API, גם בתאימות לאחור. פירוש הדבר הוא שיש לכם אפשרות לכתוב את הטירגוט של האפליקציה OpenGL ES 2.0 וכולל באופן מותנה תכונות גרפיקה של OpenGL ES 3.0 אם הן זמינות. עבור מידע נוסף לבדיקת הזמינות של API 3.0: מתבצעת בדיקה של גרסת OpenGL ES

תמיכה בדחיסת טקסטורה

דחיסת המרקם יכולה לשפר משמעותית את הביצועים של אפליקציית OpenGL על ידי צמצום דרישות הזיכרון וניצול יעיל יותר של רוחב הפס של הזיכרון. מכשיר Android framework מספקת תמיכה בפורמט דחיסת ETC1 כתכונה סטנדרטית, כולל סיווג השירות ETC1Util וכלי הדחיסה etc1tool (נמצא בתוך Android SDK ב-<sdk>/tools/). דוגמה לאפליקציה ל-Android שמשתמשת דחיסת טקסטורה. ראו את דוגמת הקוד CompressedTextureActivity ב-Android SDK (<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 API. פורמט טקסטורה זה מציע יחסי דחיסה מצוינים עם איכות חזותית גבוהה תומך גם בשקיפות (ערוץ אלפא).

מעבר לפורמטים של ETC, במכשירי Android יש תמיכה מגוונת בדחיסת טקסטורה שמבוססת על ערכות שבבים של GPU והטמעות OpenGL. עליך לבדוק את התמיכה בדחיסת טקסטורה המכשירים שאליהם אתם מטרגטים כדי לקבוע אילו סוגי דחיסה האפליקציה שלכם תמיכה. כדי לקבוע אילו פורמטים של טקסטורה נתמכים במכשיר מסוים, מבצעים שאילתה במכשיר ובודקים את השמות של תוספי OpenGL, שמזהים אילו פורמטים של דחיסת טקסטורה (ותכונות OpenGL אחרות) נתמכים על ידי במכשיר. הנה כמה פורמטים נפוצים של דחיסת נתוני טקסטורה:

  • Adaptable Scalable Texture Compression (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) זמינה מגוון רחב של מכשירים ותומכת בדחיסה בקצב קבוע למרקמים של RGB עם או בלי ערוץ אלפא. הפורמט הזה יכול להיות מיוצג על ידי כמה שמות של תוספי OpenGL, לדוגמה:
    • GL_AMD_compressed_ATC_texture
    • GL_ATI_texture_compression_atitc
  • PVRTC – דחיסת הנתונים באמצעות טקסטורת PowerVR (PVRTC) זמינה מגוון מכשירים ותומך במרקמים של 2 סיביות ו-4 ביט לפיקסל עם או בלי ערוץ אלפא. פורמט זה מיוצג על ידי השם הבא של תוסף OpenGL:
    • GL_IMG_texture_compression_pvrtc
  • 3DC – דחיסת טקסטורה 3DC (3DC) היא פורמט זמין פחות תומכת במרקמים של RGB עם ערוץ אלפא. פורמט זה מיוצג על ידי 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. אריזת התוספים האלה יחד מעודדות רמה עקבית של פונקציונליות במכשירים שונים, ובמקביל מאפשרות למפתחים ליהנות מכל היתרונות את היתרון של החיתוך החדש ביותר של מכשירי GPU ניידים.

ה-AEP גם משפר את התמיכה בתמונות, במאגרי אחסון זמני של הצללה (shader) ובמוניות אטומיות תוכנות הצללה למקטעים.

כדי שהאפליקציה תוכל להשתמש ב-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);

אם השיטה מחזירה את הערך True, יש תמיכה ב-AEP.

לקבלת מידע נוסף על ה-AEP, אפשר להיכנס לדף שלו בכתובת Khronos OpenGL ES Registry.

מתבצעת בדיקה של גרסת OpenGL ES

קיימות כמה גרסאות של OpenGL ES שזמינות במכשירי Android. אפשר לציין את הגרסה המינימלית של ה-API הדרושה במניפסט שלך, אבל מומלץ גם לנצל את היתרונות של התכונות בממשק API חדש יותר באותו זמן. לדוגמה, את OpenGL ES 3.0 API תואם לאחור עם גרסת 2.0 של ה-API, לכן כדאי לכתוב את האפליקציה כך שהיא תשתמש בתכונות OpenGL ES 3.0, אבל לחזור ל-API 2.0 אם 3.0 API לא זמין.

לפני השימוש בתכונות OpenGL ES מגרסה גבוהה יותר מהמינימום הנדרש ב- מניפסט של האפליקציה, על האפליקציה לבדוק את גרסת ה-API שזמינה במכשיר. אפשר לעשות זאת באחת משתי הדרכים הבאות:

  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() מופיעה למעלה מחזירה null, הקוד אמור ליצור OpenGL במקום זאת, להקשר של ES 2.0 ולחזור להשתמש רק ב-API הזה.

קטע הקוד הבא מדגים איך בודקים את גרסת 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.

בגישה זו, אם תגלה שהמכשיר תומך בגרסת API ברמה גבוהה יותר, להרוס את ההקשר המינימלי של OpenGL ES וליצור הקשר חדש עם של גרסת ה-API הזמינה.

בחירה בגרסת OpenGL API

OpenGL ES בגרסה 2.0 וגרסה 3.0 מספקות רמה גבוהה יותר ממשקים גרפיים מבוססי-ביצועים ליצירת משחקים בתלת-ממד, תצוגות חזותיות וממשקי משתמש. גרפיקה תהליך הקידום של OpenGL ES 2.0 ו-3.0 דומה ברובו, וגרסה 3.0 מייצגת קבוצת-על של 2.0 API עם תכונות נוספות. תכנות ל-OpenGL ES 1.0/1.1 API לעומת OpenGL ES גרסאות 2.0 ו-3.0 שונות באופן משמעותי, ולא מומלץ באפליקציות חדשות. מפתחים צריכים לשקול בזהירות את הגורמים הבאים לפני שמתחילים בפיתוח עם ממשקי ה-API האלה:

  • תאימות מכשירים - מפתחים צריכים להביא בחשבון את סוגי המכשירים, גרסאות Android וגרסאות OpenGL ES זמינות ללקוחות שלהן. אפשר לקבל מידע נוסף בתאימות ל-OpenGL בכל המכשירים, אפשר לעיין בגרסאות OpenGL תאימות המכשיר.
  • תמיכה בטקסטורה – ה-OpenGL ES 3.0 API תומך במרקם בצורה הטובה ביותר לבצע דחיסה כי היא מבטיחה את הזמינות של פורמט הדחיסה ETC2, שתומך במידה הולמת. עם זאת, הטמעות ה-API בגרסה 2.0 כוללות תמיכה ב-ETC1 פורמט הטקסטורה הזה לא תומך בשקיפות. ליישם שקיפות באמצעות קובצי דחיסה של טקסטורות, עליך להשתמש בשתי מרקמים של ETC1 (פיצול בין צבע לאלפא) או לספק משאבים בפורמטים אחרים של דחיסה שנתמכים על ידי המכשירים שאתם מטרגטים. לקבלת מידע נוסף, ראו תמיכה בדחיסת טקסטורה.

אמנם התאימות והתמיכה בטקסטורה עשויות להשפיע על החלטה, עליך לבחור גרסת OpenGL API על סמך מה שלדעתך מספקת את החוויה הטובה ביותר למשתמשים.