Xây dựng môi trường OpenGL ES

Để vẽ đồ hoạ bằng OpenGL ES trong ứng dụng Android, bạn phải tạo vùng chứa khung hiển thị cho chúng. Một trong những cách đơn giản hơn để làm việc này là triển khai cả GLSurfaceViewGLSurfaceView.Renderer. Đáp GLSurfaceView là vùng chứa khung hiển thị dành cho đồ hoạ được vẽ bằng OpenGL và GLSurfaceView.Renderer kiểm soát nội dung được vẽ trong thành phần hiển thị đó. Thông tin khác về các lớp này, xem phần OpenGL ES hướng dẫn cho nhà phát triển.

GLSurfaceView chỉ là một cách để kết hợp đồ hoạ OpenGL ES vào . Đối với chế độ xem đồ hoạ toàn màn hình hoặc gần như toàn màn hình, đây là một lựa chọn hợp lý. Những nhà phát triển muốn kết hợp đồ hoạ OpenGL ES vào một phần nhỏ bố cục nên hãy xem TextureView. Đối với các nhà phát triển tự làm, thực tế, có thể tạo khung hiển thị OpenGL ES bằng SurfaceView, nhưng việc này đòi hỏi viết khá nhiều mã bổ sung.

Bài học này giải thích cách hoàn tất quá trình triển khai tối thiểu của GLSurfaceViewGLSurfaceView.Renderer một cách đơn giản hoạt động của ứng dụng.

Khai báo việc sử dụng OpenGL ES trong tệp kê khai

Để ứng dụng của bạn sử dụng API OpenGL ES 2.0, bạn phải thêm: vào tệp kê khai của bạn:

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

Nếu ứng dụng của bạn sử dụng nén kết cấu, bạn cũng phải khai báo các định dạng nén mà ứng dụng của bạn hỗ trợ để ứng dụng chỉ được cài đặt trên thiết bị tương thích.

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

Để biết thêm thông tin về định dạng nén kết cấu, hãy xem Hướng dẫn dành cho nhà phát triển OpenGL.

Tạo một hoạt động cho đồ hoạ OpenGL ES

Ứng dụng Android sử dụng OpenGL ES có các hoạt động giống như bất kỳ ứng dụng nào khác có giao diện người dùng. Điểm khác biệt chính so với các ứng dụng khác là bố cục bố cục cho của bạn. Mặc dù trong nhiều ứng dụng, bạn có thể dùng TextView, ButtonListView, nhưng trong một ứng dụng dùng OpenGL ES, bạn có thể đồng thời thêm GLSurfaceView.

Ví dụ về mã sau đây cho thấy cách triển khai tối giản của một hoạt động sử dụng GLSurfaceView làm chế độ xem chính:

Kotlin

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

Java

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

Lưu ý: OpenGL ES 2.0 yêu cầu Android 2.2 (API cấp 8) trở lên, vì vậy, hãy đảm bảo dự án Android của bạn nhắm đến API đó trở lên.

Tạo đối tượng GLSurfaceView

GLSurfaceView là một thành phần hiển thị chuyên biệt, nơi bạn có thể vẽ OpenGL ES đồ hoạ. Bản thân nó không làm được gì nhiều. Bản vẽ thực tế của các đối tượng được kiểm soát trong GLSurfaceView.Renderer mà bạn đã đặt cho chế độ xem này. Trên thực tế, mã nguồn cho đối tượng quá mỏng, nên bạn có thể muốn bỏ qua việc mở rộng đối tượng và chỉ tạo một đối tượng chưa sửa đổi GLSurfaceView thực thể, nhưng đừng làm việc đó. Bạn cần mở rộng lớp này trong để ghi lại các sự kiện chạm, được đề cập trong bài viết Phản hồi khi chạm sự kiện.

Mã thiết yếu cho GLSurfaceView là rất nhỏ, vì vậy, để nhanh chóng thông thường, điều quan trọng là chỉ cần tạo một lớp bên trong trong hoạt động sử dụng lớp đó:

Kotlin

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

Java

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

Một thao tác bổ sung không bắt buộc khác cho quá trình triển khai GLSurfaceView là đặt chế độ kết xuất chỉ vẽ khung hiển thị khi có thay đổi đối với dữ liệu bản vẽ bằng cách sử dụng GLSurfaceView.RENDERMODE_WHEN_DIRTY cài đặt:

Kotlin

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

Java

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

Chế độ cài đặt này không cho phép vẽ lại khung GLSurfaceView cho đến khi bạn gọi requestRender(), tức là hiệu quả cho ứng dụng mẫu này.

Tạo lớp kết xuất đồ hoạ

Cách triển khai lớp GLSurfaceView.Renderer hoặc trình kết xuất trong ứng dụng sử dụng OpenGL ES là nơi mọi thứ bắt đầu trở nên thú vị. Lớp này chế độ điều khiển nội dung được vẽ trên GLSurfaceView tương ứng với nội dung đó. Có ba phương thức trong trình kết xuất được hệ thống Android gọi để xác định đâu là cách vẽ trên GLSurfaceView:

  • onSurfaceCreated() – Được gọi một lần để thiết lập môi trường OpenGL ES của khung hiển thị.
  • onDrawFrame() – Được gọi cho mỗi vẽ lại khung hiển thị.
  • onSurfaceChanged() – Được gọi nếu hình dạng của chế độ xem thay đổi, chẳng hạn như khi hướng màn hình của thiết bị thay đổi.

Đây là cách triển khai rất cơ bản cho trình kết xuất OpenGL ES, nó không chỉ thực hiện việc gì khác ngoài việc vẽ nền đen trong GLSurfaceView:

Kotlin

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

Java

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

Vậy là xong! Các mã ví dụ ở trên tạo một ứng dụng Android đơn giản hiển thị màn hình đen qua OpenGL. Mặc dù mã này không có tác dụng gì thú vị, bằng cách khi tạo các lớp này, bạn đã đặt nền móng cần thiết để bắt đầu vẽ các thành phần đồ hoạ bằng OpenGL.

Lưu ý: Bạn có thể thắc mắc tại sao các phương thức này có tham số GL10 khi sử dụng các API OpengGL ES 2.0. Các chữ ký phương thức này chỉ được sử dụng lại cho API 2.0 để giữ mã khung Android đơn giản hơn.

Nếu đã quen thuộc với API OpenGL ES thì giờ đây, bạn có thể thiết lập OpenGL ES trong ứng dụng của bạn và bắt đầu vẽ đồ hoạ. Tuy nhiên, nếu bạn cần thêm một chút trợ giúp để nhận bắt đầu với OpenGL, hãy chuyển đến các bài học tiếp theo để biết thêm một vài gợi ý.