یک محیط OpenGL ES بسازید

برای ترسیم گرافیک با OpenGL ES در برنامه اندرویدی خود، باید یک View Container برای آنها ایجاد کنید. یکی از راه‌های ساده‌تر برای انجام این کار، پیاده‌سازی GLSurfaceView و GLSurfaceView.Renderer است. یک GLSurfaceView یک محفظه نمایش برای گرافیک است که با OpenGL و GLSurfaceView.Renderer ترسیم شده است.Renderer آنچه را که در آن نمای ترسیم شده است کنترل می کند. برای اطلاعات بیشتر در مورد این کلاس ها، راهنمای توسعه دهنده OpenGL ES را ببینید.

GLSurfaceView تنها یک راه برای گنجاندن گرافیک OpenGL ES در برنامه شما است. برای نمایش گرافیکی تمام صفحه یا تقریباً تمام صفحه، انتخاب معقولی است. توسعه‌دهندگانی که می‌خواهند گرافیک OpenGL ES را در بخش کوچکی از طرح‌بندی‌های خود بگنجانند، باید نگاهی به TextureView بیندازند. برای توسعه دهندگان واقعی که خودتان انجام می دهید، ایجاد نمای OpenGL ES با استفاده از SurfaceView نیز امکان پذیر است، اما این نیاز به نوشتن مقدار کمی کد اضافی دارد.

این درس نحوه تکمیل حداقل پیاده سازی GLSurfaceView و GLSurfaceView.Renderer را در یک فعالیت کاربردی ساده توضیح می دهد.

استفاده OpenGL ES را در مانیفست اعلام کنید

برای اینکه برنامه شما از API OpenGL ES 2.0 استفاده کند، باید اعلان زیر را به مانیفست خود اضافه کنید:

<uses-feature android:glEsVersion="0x00020000" android:required="true" />

اگر برنامه شما از فشرده‌سازی بافت استفاده می‌کند، باید همچنین فرمت‌های فشرده‌سازی را که برنامه شما پشتیبانی می‌کند، اعلام کنید تا فقط بر روی دستگاه‌های سازگار نصب شود.

<supports-gl-texture android:name="GL_OES_compressed_ETC1_RGB8_texture" />
<supports-gl-texture android:name="GL_OES_compressed_paletted_texture" />

برای اطلاعات بیشتر در مورد فرمت های فشرده سازی بافت، راهنمای توسعه دهنده OpenGL را ببینید.

یک فعالیت برای گرافیک OpenGL ES ایجاد کنید

برنامه‌های اندرویدی که از OpenGL ES استفاده می‌کنند، مانند هر برنامه دیگری که رابط کاربری دارد، فعالیت‌هایی دارند. تفاوت اصلی با سایر برنامه ها این است که در چیدمان فعالیت خود قرار می دهید. در حالی که در بسیاری از برنامه‌ها ممکن است از TextView ، Button و ListView استفاده کنید، در برنامه‌ای که از OpenGL ES استفاده می‌کند، می‌توانید GLSurfaceView نیز اضافه کنید.

مثال کد زیر اجرای حداقلی از یک فعالیت را نشان می دهد که از GLSurfaceView به عنوان نمای اولیه خود استفاده می کند:

کاتلین

class OpenGLES20Activity : Activity() {

    private lateinit var gLView: GLSurfaceView

    public override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Create a GLSurfaceView instance and set it
        // as the ContentView for this Activity.
        gLView = MyGLSurfaceView(this)
        setContentView(gLView)
    }
}

جاوا

public class OpenGLES20Activity extends Activity {

    private GLSurfaceView gLView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Create a GLSurfaceView instance and set it
        // as the ContentView for this Activity.
        gLView = new MyGLSurfaceView(this);
        setContentView(gLView);
    }
}

توجه: OpenGL ES 2.0 به Android 2.2 (API Level 8) یا بالاتر نیاز دارد، بنابراین مطمئن شوید که پروژه Android شما آن API یا بالاتر را هدف قرار می دهد.

یک شی GLSurfaceView بسازید

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

کد ضروری برای GLSurfaceView حداقل است، بنابراین برای پیاده سازی سریع، معمول است که فقط یک کلاس داخلی در فعالیتی که از آن استفاده می کند ایجاد کنید:

کاتلین

import android.content.Context
import android.opengl.GLSurfaceView

class MyGLSurfaceView(context: Context) : GLSurfaceView(context) {

    private val renderer: MyGLRenderer

    init {

        // Create an OpenGL ES 2.0 context
        setEGLContextClientVersion(2)

        renderer = MyGLRenderer()

        // Set the Renderer for drawing on the GLSurfaceView
        setRenderer(renderer)
    }
}

جاوا

import android.content.Context;
import android.opengl.GLSurfaceView;

class MyGLSurfaceView extends GLSurfaceView {

    private final MyGLRenderer renderer;

    public MyGLSurfaceView(Context context){
        super(context);

        // Create an OpenGL ES 2.0 context
        setEGLContextClientVersion(2);

        renderer = new MyGLRenderer();

        // Set the Renderer for drawing on the GLSurfaceView
        setRenderer(renderer);
    }
}

یکی دیگر از گزینه‌های اضافه شده به پیاده‌سازی GLSurfaceView شما این است که حالت رندر را طوری تنظیم کنید که فقط زمانی که تغییری در داده‌های طراحی شما با استفاده از تنظیم GLSurfaceView.RENDERMODE_WHEN_DIRTY ایجاد شود، نما را ترسیم کند:

کاتلین

// Render the view only when there is a change in the drawing data
renderMode = GLSurfaceView.RENDERMODE_WHEN_DIRTY

جاوا

// Render the view only when there is a change in the drawing data
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);

این تنظیم از ترسیم مجدد فریم GLSurfaceView تا زمانی که requestRender() فراخوانی نکنید، جلوگیری می کند، که برای این برنامه نمونه کارآمدتر است.

یک کلاس رندر بسازید

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

  • onSurfaceCreated() - یک بار برای تنظیم محیط OpenGL ES view فراخوانی شد.
  • onDrawFrame() - برای هر ترسیم مجدد نما فراخوانی می شود.
  • onSurfaceChanged() - اگر هندسه نمای تغییر کند، برای مثال زمانی که جهت صفحه نمایش دستگاه تغییر کند، فراخوانی می شود.

در اینجا یک پیاده سازی بسیار ابتدایی از یک رندر OpenGL ES وجود دارد که کاری جز ترسیم پس زمینه سیاه در GLSurfaceView ندارد:

کاتلین

import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10

import android.opengl.GLES20
import android.opengl.GLSurfaceView

class MyGLRenderer : GLSurfaceView.Renderer {

    override fun onSurfaceCreated(unused: GL10, config: EGLConfig) {
        // Set the background frame color
        GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f)
    }

    override fun onDrawFrame(unused: GL10) {
        // Redraw background color
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)
    }

    override fun onSurfaceChanged(unused: GL10, width: Int, height: Int) {
        GLES20.glViewport(0, 0, width, height)
    }
}

جاوا

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.opengl.GLES20;
import android.opengl.GLSurfaceView;

public class MyGLRenderer implements GLSurfaceView.Renderer {

    public void onSurfaceCreated(GL10 unused, EGLConfig config) {
        // Set the background frame color
        GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    }

    public void onDrawFrame(GL10 unused) {
        // Redraw background color
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
    }

    public void onSurfaceChanged(GL10 unused, int width, int height) {
        GLES20.glViewport(0, 0, width, height);
    }
}

این تمام چیزی است که وجود دارد! مثال‌های کد بالا یک برنامه اندروید ساده ایجاد می‌کنند که با استفاده از OpenGL یک صفحه سیاه نمایش می‌دهد. در حالی که این کد کار چندان جالبی انجام نمی دهد، با ایجاد این کلاس ها، شما پایه و اساس لازم را برای شروع طراحی عناصر گرافیکی با OpenGL ایجاد کرده اید.

توجه: ممکن است تعجب کنید که چرا این روش ها دارای پارامتر GL10 هستند، وقتی از API های OpengGL ES 2.0 استفاده می کنید. این امضاهای متد به سادگی برای API های 2.0 مجدداً استفاده می شوند تا کد فریمورک اندروید را ساده تر نگه دارند.

اگر با API های OpenGL ES آشنا هستید، اکنون باید بتوانید یک محیط OpenGL ES را در برنامه خود راه اندازی کنید و شروع به ترسیم گرافیک کنید. با این حال، اگر برای شروع با OpenGL به کمک بیشتری نیاز دارید، برای چند نکته بیشتر به درس های بعدی بروید.