OpenGL ES

اندروید شامل پشتیبانی از گرافیک‌های دوبعدی و سه بعدی با کارایی بالا با کتابخانه Open Graphics (OpenGL®)، به‌ویژه OpenGL ES API است. OpenGL یک API گرافیکی بین پلتفرمی است که یک رابط نرم افزاری استاندارد را برای سخت افزار پردازش گرافیک سه بعدی مشخص می کند. OpenGL ES طعمی از مشخصات OpenGL است که برای دستگاه های تعبیه شده در نظر گرفته شده است. اندروید چندین نسخه از OpenGL ES API را پشتیبانی می کند:

  • OpenGL ES 2.0 - این مشخصات API توسط Android 2.2 (سطح API 8) و بالاتر پشتیبانی می شود.
  • OpenGL ES 3.0 - این مشخصات API توسط اندروید 4.3 (سطح API 18) و بالاتر پشتیبانی می شود.
  • OpenGL ES 3.1 - این مشخصات API توسط اندروید 5.0 (سطح API 21) و بالاتر پشتیبانی می شود.
  • OpenGL ES 3.2 - این مشخصات API توسط Android 7.0 (سطح API 24) و بالاتر پشتیبانی می شود.

احتیاط: صرف نظر از نسخه پلتفرم اندروید، دستگاه نمی‌تواند از OpenGL ES 3.0 API پشتیبانی کند، مگر اینکه سازنده دستگاه اجرای این خط لوله گرافیکی را ارائه دهد. اگر در مانیفست مشخص کنید که OpenGL ES 3.0 مورد نیاز است، می توانید مطمئن باشید که آن نسخه در دستگاه وجود دارد. اگر مشخص کرده‌اید که یک نسخه سطح پایین‌تر مورد نیاز است اما می‌خواهید از ویژگی‌های 3.0 در صورت موجود بودن استفاده کنید، باید در زمان اجرا بررسی کنید تا ببینید دستگاه از چه نسخه‌ای از OpenGL پشتیبانی می‌کند. برای اطلاعات در مورد نحوه انجام این کار، بررسی نسخه OpenGL ES را ببینید.

توجه: اندروید از OpenGL ES 1.0 و 1.1 پشتیبانی می‌کند، اما این نسخه‌های API منسوخ شده‌اند و نباید توسط برنامه‌های مدرن استفاده شوند.

توجه: API خاص ارائه شده توسط فریمورک اندروید شبیه به J2ME JSR239 OpenGL ES API است، اما یکسان نیست. اگر با مشخصات J2ME JSR239 آشنا هستید، نسبت به تغییرات هوشیار باشید.

همچنین ببینید

اصول اولیه

اندروید از OpenGL هم از طریق چارچوب API و هم از طریق کیت توسعه بومی (NDK) پشتیبانی می کند. این موضوع بر روی رابط های فریمورک اندروید تمرکز دارد. برای اطلاعات بیشتر درباره NDK، به Android NDK مراجعه کنید.

دو کلاس اساسی در چارچوب Android وجود دارد که به شما امکان می‌دهد با OpenGL ES API گرافیک‌ها را ایجاد و دستکاری کنید: GLSurfaceView و GLSurfaceView.Renderer . اگر هدف شما استفاده از OpenGL در برنامه اندرویدی خود است، درک نحوه پیاده سازی این کلاس ها در یک فعالیت باید اولین هدف شما باشد.

GLSurfaceView
این کلاس یک View است که در آن می توانید اشیاء را با استفاده از فراخوانی های OpenGL API ترسیم و دستکاری کنید و از نظر عملکرد مشابه SurfaceView است. می توانید با ایجاد یک نمونه از GLSurfaceView و افزودن Renderer خود به آن از این کلاس استفاده کنید. با این حال، اگر می‌خواهید رویدادهای صفحه لمسی را ضبط کنید، باید کلاس GLSurfaceView را برای پیاده‌سازی شنوندگان لمسی گسترش دهید، همانطور که در درس آموزش OpenGL، پاسخ به رویدادهای لمسی نشان داده شده است.
GLSurfaceView.Renderer
این رابط روش های مورد نیاز برای ترسیم گرافیک در GLSurfaceView را تعریف می کند. شما باید پیاده سازی این رابط را به عنوان یک کلاس جداگانه ارائه کنید و آن را با استفاده از GLSurfaceView.setRenderer() به نمونه GLSurfaceView خود متصل کنید.

رابط GLSurfaceView.Renderer به پیاده سازی روش های زیر نیاز دارد:

  • onSurfaceCreated() : سیستم یکبار این متد را هنگام ایجاد GLSurfaceView فراخوانی می کند. از این روش برای انجام اقداماتی استفاده کنید که فقط یک بار باید انجام شوند، مانند تنظیم پارامترهای محیط OpenGL یا مقداردهی اولیه اشیاء گرافیکی OpenGL.
  • onDrawFrame() : سیستم این متد را در هر رسم مجدد از GLSurfaceView فراخوانی می کند. از این روش به عنوان نقطه اجرای اولیه برای ترسیم (و ترسیم مجدد) اشیاء گرافیکی استفاده کنید.
  • onSurfaceChanged() : سیستم زمانی این روش را فراخوانی می کند که هندسه GLSurfaceView تغییر کند، از جمله تغییر در اندازه GLSurfaceView یا جهت گیری صفحه دستگاه. برای مثال، هنگامی که دستگاه از جهت عمودی به افقی تغییر می کند، سیستم این روش را فراخوانی می کند. از این روش برای پاسخ به تغییرات در ظرف GLSurfaceView استفاده کنید.

بسته های OpenGL ES

هنگامی که با استفاده از GLSurfaceView و GLSurfaceView.Renderer یک نمای کانتینری برای OpenGL ES ایجاد کردید، می‌توانید با استفاده از کلاس‌های زیر شروع به فراخوانی OpenGL API کنید:

  • کلاس OpenGL ES 2.0 API
    • android.opengl.GLES20 - این بسته رابط OpenGL ES 2.0 را فراهم می کند و با اندروید 2.2 (سطح API 8) در دسترس است.
  • بسته های API OpenGL ES 3.0/3.1/3.2
    • android.opengl - این بسته رابط را برای کلاس های OpenGL ES 3.0/3.1 فراهم می کند. نسخه 3.0 با اندروید 4.3 (سطح API 18) در دسترس است. نسخه 3.1 با اندروید 5.0 (سطح API 21) در دسترس است. نسخه 3.2 با اندروید 7.0 (سطح API 24) در دسترس است.

اگر می‌خواهید فوراً شروع به ساختن یک برنامه با OpenGL ES کنید، کلاس Displaying graphics with 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> مراجعه کنید.

نگاشت مختصات برای اشیاء ترسیم شده

یکی از مشکلات اساسی در نمایش گرافیک در دستگاه های اندرویدی این است که صفحه نمایش آنها می تواند اندازه و شکل متفاوتی داشته باشد. OpenGL یک سیستم مختصات مربعی و یکنواخت را فرض می‌کند و به طور پیش‌فرض، با خوشحالی آن مختصات را روی صفحه نمایش معمولی غیرمربع شما می‌کشد، گویی کاملاً مربع است.

شکل 1. سیستم مختصات پیش فرض OpenGL (سمت چپ) که به یک صفحه دستگاه Android معمولی (راست) نگاشت شده است.

تصویر بالا سیستم مختصات یکنواختی را نشان می‌دهد که برای یک قاب OpenGL در سمت چپ فرض شده است، و اینکه چگونه این مختصات در واقع به یک صفحه دستگاه معمولی در جهت افقی در سمت راست نگاشت می‌شوند. برای حل این مشکل، می‌توانید حالت‌های طرح‌دهی OpenGL و نماهای دوربین را برای تغییر مختصات اعمال کنید تا اشیاء گرافیکی شما نسبت‌های صحیحی را در هر نمایشگر داشته باشند.

به منظور اعمال طرح ریزی و نماهای دوربین، یک ماتریس طرح ریزی و یک ماتریس نمای دوربین ایجاد می کنید و آنها را در خط لوله رندر OpenGL اعمال می کنید. ماتریس پروجکشن مختصات گرافیک شما را مجدداً محاسبه می کند تا به درستی به صفحه نمایش دستگاه اندروید نگاشت شوند. ماتریس نمای دوربین دگرگونی ایجاد می کند که اشیا را از یک موقعیت چشمی خاص رندر می کند.

پروجکشن و نمای دوربین در OpenGL ES 2.0 و بالاتر

در APIهای ES 2.0 و 3.0، ابتدا با افزودن یک عضو ماتریس به سایه‌زن‌های رأس اشیاء گرافیکی، پروژکشن و نمای دوربین را اعمال می‌کنید. با اضافه شدن این عضو ماتریس، سپس می توانید ماتریس های طرح ریزی و مشاهده دوربین را روی اشیاء خود ایجاد و اعمال کنید.

  1. افزودن ماتریس به سایه‌زن‌های رأس - یک متغیر برای ماتریس نمایان ایجاد کنید و آن را به عنوان ضریب موقعیت سایه‌زن اضافه کنید. در مثال زیر کد سایه زن رئوس، عضو uMVPMatrix موجود به شما امکان می دهد ماتریس های نمایش و مشاهده دوربین را به مختصات اشیایی که از این سایه زن استفاده می کنند اعمال کنید.

    کاتلین

    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"
    

    جاوا

    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 را برای دسترسی به متغیر ماتریس تعریف‌شده در سایه‌زن راس بالا تغییر داد.

    کاتلین

    override fun onSurfaceCreated(gl: GL10, config: EGLConfig) {
        ...
        muMVPMatrixHandle = GLES20.glGetUniformLocation(program, "uMVPMatrix")
        ...
    }
    

    جاوا

    public void onSurfaceCreated(GL10 unused, EGLConfig config) {
        ...
        muMVPMatrixHandle = GLES20.glGetUniformLocation(program, "uMVPMatrix");
        ...
    }
    
  3. ایجاد ماتریس های طرح ریزی و مشاهده دوربین - ماتریس های طرح ریزی و مشاهده را برای اعمال اشیاء گرافیکی ایجاد کنید. کد مثال زیر نشان می دهد که چگونه می توان متدهای onSurfaceCreated() و onSurfaceChanged() یک پیاده سازی GLSurfaceView.Renderer را برای ایجاد ماتریس نمای دوربین و یک ماتریس طرح ریزی بر اساس نسبت صفحه نمایش دستگاه تغییر داد.

    کاتلین

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

    جاوا

    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 ارائه شوند، تغییر دهید.

    کاتلین

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

    جاوا

    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 است که به خط لوله رندر اجازه می دهد تا چهره پشتی یک شکل را نادیده بگیرد (نه محاسبه یا ترسیم کند) و در زمان، حافظه و چرخه های پردازش صرفه جویی کند:

کاتلین

gl.apply {
    // enable face culling feature
    glEnable(GL10.GL_CULL_FACE)
    // specify which faces to not draw
    glCullFace(GL10.GL_BACK)
}

جاوا

// 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 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 ویژگی های اضافی و عملکرد بهتری را نسبت به API 2.0 ارائه می دهد و همچنین با نسخه قبلی سازگار است. این بدان معنی است که شما می توانید برنامه خود را با هدف قرار دادن OpenGL ES 2.0 بنویسید و در صورت در دسترس بودن، ویژگی های گرافیکی OpenGL ES 3.0 را به صورت مشروط شامل کنید. برای اطلاعات بیشتر در مورد بررسی در دسترس بودن API 3.0، به بررسی نسخه OpenGL ES مراجعه کنید.

پشتیبانی از فشرده سازی بافت

فشرده سازی بافت می تواند عملکرد برنامه OpenGL شما را با کاهش نیاز به حافظه و استفاده کارآمدتر از پهنای باند حافظه به میزان قابل توجهی افزایش دهد. چارچوب Android از فرمت فشرده سازی ETC1 به عنوان یک ویژگی استاندارد پشتیبانی می کند، از جمله کلاس ابزار ETC1Util و ابزار فشرده سازی etc1tool (واقع در Android SDK در <sdk>/tools/ ). برای مثالی از یک برنامه Android که از فشرده‌سازی بافت استفاده می‌کند، به نمونه کد CompressedTextureActivity در Android SDK ( <sdk>/samples/<version>/ApiDemos/src/com/example/android/apis/graphics/ ) مراجعه کنید.

فرمت ETC1 توسط تمام دستگاه های اندرویدی که از OpenGL ES 2.0 یا بالاتر پشتیبانی می کنند پشتیبانی می شود.

توجه: فرمت فشرده سازی بافت ETC1 از بافت هایی با شفافیت (کانال آلفا) پشتیبانی نمی کند. اگر برنامه شما به بافت هایی با شفافیت نیاز دارد، باید سایر فرمت های فشرده سازی بافت موجود در دستگاه های مورد نظر خود را بررسی کنید. یکی از روش‌های رندر کردن بافت‌های کانال آلفا با استفاده از ETC1 این است که دو شی بافت ETC1 را پیوند دهیم: اولی با داده‌های رنگی، دومی با داده‌های کانال آلفا و سپس ترکیب مقادیر دو بافت در قطعه سایه‌زن.

فرمت‌های فشرده‌سازی بافت ETC2/EAC در هنگام استفاده از OpenGL ES 3.0 API تضمین شده است. این فرمت بافت نسبت فشرده سازی عالی با کیفیت بصری بالا را ارائه می دهد و فرمت از شفافیت (کانال آلفا) نیز پشتیبانی می کند.

فراتر از فرمت‌های ETC، دستگاه‌های اندرویدی بر اساس چیپ‌ست‌های GPU و پیاده‌سازی OpenGL از فشرده‌سازی بافت پشتیبانی می‌کنند. شما باید پشتیبانی از فشرده‌سازی بافت را در دستگاه‌هایی که هدف قرار می‌دهید بررسی کنید تا مشخص کنید برنامه شما باید از چه نوع فشرده‌سازی پشتیبانی کند. برای تعیین اینکه چه فرمت‌های بافتی در یک دستگاه خاص پشتیبانی می‌شوند، باید دستگاه را جستجو کنید و نام‌های برنامه افزودنی OpenGL را بررسی کنید، که مشخص می‌کند چه فرمت‌های فشرده‌سازی بافت (و سایر ویژگی‌های OpenGL) توسط دستگاه پشتیبانی می‌شوند. برخی از فرمت‌های فشرده‌سازی بافت که معمولاً پشتیبانی می‌شوند به شرح زیر هستند:

  • فشرده سازی بافت مقیاس پذیر سازگار (ASTC) - فرمت فشرده سازی بافت طراحی شده برای جایگزینی فرمت های قبلی. به دلیل پشتیبانی از اندازه های مختلف بلوک، نسبت به فرمت های قبلی انعطاف پذیرتر است.
    • GL_KHR_texture_compression_astc_ldr
    • GL_KHR_texture_compression_astc_hdr (محدوده دینامیکی بالا)
  • S3TC (DXT n /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. کد زیر را بر روی دستگاه های مورد نظر خود اجرا کنید تا مشخص کنید از چه فرمت های فشرده سازی بافت پشتیبانی می شود:

    کاتلین

    var extensions = gl.glGetString(GL10.GL_EXTENSIONS)
    

    جاوا

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

    هشدار: نتایج این تماس بر اساس مدل دستگاه متفاوت است! شما باید این فراخوانی را روی چندین دستگاه هدف اجرا کنید تا مشخص کنید چه نوع فشرده سازی معمولاً پشتیبانی می شود.

  2. خروجی این روش را بررسی کنید تا مشخص کنید چه برنامه‌های افزودنی OpenGL در دستگاه پشتیبانی می‌شوند.

بسته برنامه افزودنی اندروید (AEP)

AEP تضمین می کند که برنامه شما از مجموعه استاندارد شده از برنامه های افزودنی OpenGL بالاتر و فراتر از مجموعه هسته ای که در مشخصات OpenGL 3.1 توضیح داده شده است، پشتیبانی می کند. بسته‌بندی این افزونه‌ها در کنار هم مجموعه‌ای از عملکردها را در بین دستگاه‌ها تشویق می‌کند، در حالی که به توسعه‌دهندگان این امکان را می‌دهد تا از آخرین مزیت دستگاه‌های GPU موبایل استفاده کنند.

AEP همچنین پشتیبانی از تصاویر، بافرهای ذخیره سازی سایه زن و شمارنده های اتمی را در سایه زن های قطعه بهبود می بخشد.

برای اینکه برنامه شما بتواند از 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 ارسال کنید. قطعه کد زیر نمونه ای از نحوه انجام این کار را نشان می دهد:

کاتلین

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

جاوا

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

اگر متد true را برگرداند، AEP پشتیبانی می شود.

برای اطلاعات بیشتر در مورد AEP، از صفحه آن در Khronos OpenGL ES Registry دیدن کنید.

در حال بررسی نسخه OpenGL ES

نسخه های مختلفی از OpenGL ES در دستگاه های اندرویدی موجود است. می‌توانید حداقل نسخه API مورد نیاز برنامه خود را در مانیفست خود مشخص کنید، اما ممکن است بخواهید همزمان از ویژگی‌های یک API جدیدتر نیز بهره ببرید. به عنوان مثال، OpenGL ES 3.0 API با نسخه 2.0 API سازگار است، بنابراین ممکن است بخواهید برنامه خود را طوری بنویسید که از ویژگی های OpenGL ES 3.0 استفاده کند، اما اگر API 3.0 نباشد به API 2.0 برمی گردد. موجود است.

قبل از استفاده از ویژگی‌های OpenGL ES از نسخه‌ای بالاتر از حداقل مورد نیاز در مانیفست برنامه شما، برنامه شما باید نسخه API موجود در دستگاه را بررسی کند. شما می توانید این کار را به یکی از دو روش انجام دهید:

  1. سعی کنید زمینه سطح بالاتر OpenGL ES ( EGLContext ) ایجاد کنید و نتیجه را بررسی کنید.
  2. یک زمینه OpenGL ES با حداقل پشتیبانی ایجاد کنید و مقدار نسخه را بررسی کنید.

کد مثال زیر نحوه بررسی نسخه OpenGL ES موجود را با ایجاد یک EGLContext و بررسی نتیجه نشان می دهد. این مثال نحوه بررسی نسخه OpenGL ES 3.0 را نشان می دهد:

کاتلین

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

جاوا

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 را با ایجاد حداقل زمینه پشتیبانی شده ابتدا و سپس بررسی رشته نسخه نشان می دهد:

کاتلین

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

جاوا

// 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 که مجموعه‌ای از API 2.0 را با ویژگی‌های اضافی نشان می‌دهد. برنامه نویسی برای OpenGL ES 1.0/1.1 API در مقابل OpenGL ES 2.0 و 3.0 به طور قابل توجهی متفاوت است و برای برنامه های جدید توصیه نمی شود. توسعه دهندگان باید قبل از شروع توسعه با این APIها، عوامل زیر را به دقت در نظر بگیرند:

  • سازگاری با دستگاه - توسعه دهندگان باید انواع دستگاه ها، نسخه های اندروید و نسخه های OpenGL ES را در دسترس مشتریان خود در نظر بگیرند. برای اطلاعات بیشتر در مورد سازگاری OpenGL در همه دستگاه‌ها، به بخش نسخه‌های OpenGL و سازگاری دستگاه مراجعه کنید.
  • پشتیبانی از بافت - OpenGL ES 3.0 API بهترین پشتیبانی را برای فشرده سازی بافت دارد زیرا در دسترس بودن فرمت فشرده سازی ETC2 را تضمین می کند که از شفافیت پشتیبانی می کند. اجرای 2.0 API شامل پشتیبانی از ETC1 است، اما این فرمت بافت از شفافیت پشتیبانی نمی کند. برای پیاده‌سازی شفافیت با بافت‌های فشرده، باید از دو بافت ETC1 (تقسیم بین رنگ و آلفا) استفاده کنید یا منابعی را در قالب‌های فشرده‌سازی دیگری که توسط دستگاه‌های مورد نظر پشتیبانی می‌شوند، ارائه دهید. برای اطلاعات بیشتر، به پشتیبانی از فشرده سازی بافت مراجعه کنید.

در حالی که سازگاری و پشتیبانی بافت ممکن است بر تصمیم شما تأثیر بگذارد، باید یک نسخه OpenGL API را بر اساس آنچه فکر می‌کنید بهترین تجربه را برای کاربرانتان فراهم می‌کند انتخاب کنید.