מערכת 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
android.opengl
– החבילה הזו מספקת את הממשק ל-OpenGL ES 3.0/3.1 הסוגים. גרסה 3.0 זמינה החל מ-Android 4.3 (רמת API 18). גרסה 3.1 זמינה החל מ-Android 5.0 (רמת API 21). גרסה 3.2 זמינה החל מ-Android 7.0 (API רמה 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 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 מתבסס על מערכת קואורדינטות אחידה וריבועית, וכברירת מחדל, בשמחה משרטטת את הקואורדינטות האלה על מסך בדרך כלל שאינו ריבועי, כאילו הוא ריבועי לגמרי.
באיור שלמעלה ניתן לראות את מערכת הקואורדינטות האחידה, שהנחתה היא מסגרת OpenGL ואיך הקואורדינטות האלה ממופות בפועל למסך רגיל של מכשיר בפריסה לרוחב מימין. כדי לפתור את הבעיה, ניתן להפעיל מצבי הקרנת OpenGL ותצוגות מצלמה על תשנה את הקואורדינטות כך שהאובייקטים הגרפיים יהיו בפרופורציות הנכונות בכל תצוגה.
כדי להחיל תצוגות היטל ומצלמה, עליך ליצור מטריצת היטל ותצוגת מצלמה במטריצה ולהחיל אותם על צינור עיבוד ה-OpenGL. מטריצת ההיטל מחשבת מחדש את של הגרפיקה כדי שיופו בצורה נכונה למסכי מכשירי Android. התצוגה מהמצלמה ומטריצה יוצרת טרנספורמציה שמציגה אובייקטים ממיקום ספציפי של עין.
תצוגת הקרנה ומצלמה ב-OpenGL ES 2.0 ואילך
בממשקי ה-API של ES 2.0 ו-3.0, מחילים תצוגת מצלמה ומסך על ידי הוספת חבר במטריצה ועד לתוכנות ההצללה (shader) של הקודקודים של האובייקטים הגרפיים. כשמוסיפים את המטריצה, אפשר ליצור ולהחיל מטריצות של הקרנה ומצלמה על האובייקטים.
- הוספת מטריצה לתוכנות הצללה (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) של הקודקודים, כדי שאפשר יהיה לשנות אותן באופן עצמאי.
- לגשת למטריצת ההצללה – אחרי שיוצרים הוק (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"); ... }
- יוצרים מטריצות של הקרנה וצפייה במצלמה - יוצרים את ההקרנה ו
לראות מטריצות שצריך להחיל על האובייקטים הגרפיים. הקוד לדוגמה הבא מראה איך לשנות
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); }
- החלת מטריצות של הקרנה וצפייה במצלמה - כדי להחיל את ההיטל ו
את הטרנספורמציות בתצוגת המצלמה, מכפילים את המטריצות ביחד ואז מגדירים אותן
שמבוסס על תוכנת ההצללה. הקוד לדוגמה הבא מראה איך לשנות את השיטה
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) יש פנים קדמיות ופרצוף אחורי. איך אפשר לדעת אילו פנים קדמיות ואילו אחוריות? שאלה טובה. התשובה קשורה לליפוף, או הכיוון שבו אתם מגדירים את הנקודות של הצורה.
בדוגמה הזו, נקודות המשולש מוגדרות בסדר כך שהן משורטטות בכיוון נגד כיוון השעון. הסדר שבו משורטטים הקואורדינטות מגדיר את הליפוף הכיוון של הצורה. כברירת מחדל, ב-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
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 אחרים נתמכים מכשיר ספציפי:
- מריצים את הקוד הבא על מכשירי היעד כדי לקבוע איזו דחיסה של טקסטורה
הפורמטים הנתמכים:
Kotlin
var extensions = gl.glGetString(GL10.GL_EXTENSIONS)
Java
String extensions = gl.glGetString(GL10.GL_EXTENSIONS);
אזהרה: התוצאות של השיחה משתנות בהתאם לדגם המכשיר! שלך חייבים להריץ את הקריאה הזו במספר מכשירי יעד כדי לקבוע אילו סוגי דחיסה נפוצים נתמך.
- לבדוק את הפלט של השיטה הזו כדי לקבוע אילו תוספי 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 שזמינה במכשיר. אפשר לעשות זאת באחת משתי הדרכים הבאות:
- אפשר לנסות ליצור הקשר ברמה גבוהה יותר של OpenGL ES (
EGLContext
) וגם לבדוק את התוצאה. - יצירת הקשר 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 על סמך מה שלדעתך מספקת את החוויה הטובה ביותר למשתמשים.