OpenGL ES

Android hỗ trợ đồ hoạ 2D và 3D hiệu suất cao với Open Graphics Library (OpenGL®), cụ thể là API OpenGL ES. OpenGL là một API đồ hoạ đa nền tảng chỉ định một giao diện phần mềm chuẩn cho phần cứng xử lý đồ hoạ 3D. OpenGL ES là một phiên bản của OpenGL dành cho các thiết bị được nhúng. Android hỗ trợ một số phiên bản OpenGL ES API:

  • OpenGL ES 2.0 – Thông số kỹ thuật API này được Android 2.2 (API cấp 8) trở lên hỗ trợ.
  • OpenGL ES 3.0 – Thông số kỹ thuật API này được Android 4.3 (API cấp 18) trở lên hỗ trợ.
  • OpenGL ES 3.1 – Thông số kỹ thuật API này được Android 5.0 (API cấp 21) trở lên hỗ trợ.
  • OpenGL ES 3.2 – Thông số kỹ thuật API này được Android 7.0 (API cấp 24) trở lên hỗ trợ.

Thận trọng: Một thiết bị không thể hỗ trợ bất kể phiên bản nền tảng Android API OpenGL ES 3.0 trừ phi nhà sản xuất thiết bị cung cấp của quy trình đồ hoạ này. Nếu bạn chỉ định trong tệp kê khai rằng Cần có OpenGL ES 3.0 và chắc chắn phiên bản đó sẽ hiện diện trên thiết bị. Nếu bạn chỉ định rằng cần phiên bản cấp thấp hơn nhưng bạn muốn sử dụng các tính năng 3.0 (nếu có), bạn nên kiểm tra thời gian chạy để biết phiên bản OpenGL mà thiết bị hỗ trợ. Để biết thông tin về cách để thực hiện việc này, hãy xem phần Kiểm tra phiên bản OpenGL ES.

Lưu ý: Android có hỗ trợ OpenGL ES 1.0 và 1.1, nhưng các phiên bản API này không được dùng nữa và không nên được các ứng dụng hiện đại sử dụng.

Lưu ý: API cụ thể do khung Android cung cấp tương tự như API OpenGL ES J2ME JSR239, nhưng không giống hệt nhau. Nếu bạn quen thuộc với thông số kỹ thuật của J2ME JSR239, hãy lưu ý biến thể.

Xem thêm

Thông tin cơ bản

Android hỗ trợ OpenGL thông qua API khung và Phát triển mã gốc Bộ công cụ (NDK). Chủ đề này tập trung vào giao diện khung Android. Để biết thêm thông tin về NDK, hãy xem Android NDK.

Có 2 lớp cơ bản trong khung Android cho phép bạn tạo và thao tác đồ hoạ có API OpenGL ES: GLSurfaceViewGLSurfaceView.Renderer Nếu mục tiêu của bạn là sử dụng OpenGL trong ứng dụng Android, hiểu cách triển khai các lớp học này trong một hoạt động nên là mục tiêu đầu tiên của bạn.

GLSurfaceView
Lớp này là một View, nơi bạn có thể vẽ và thao tác với các đối tượng bằng cách sử dụng Lệnh gọi API OpenGL và có chức năng tương tự như SurfaceView. Bạn có thể sử dụng cho lớp này bằng cách tạo một bản sao của GLSurfaceView và thêm Renderer cho cuộc trò chuyện đó. Tuy nhiên, nếu bạn muốn thu thập sự kiện màn hình cảm ứng, bạn nên mở rộng lớp GLSurfaceView để triển khai trình nghe cảm ứng, như trình bày trong bài học đào tạo OpenGL, Phản hồi sự kiện chạm.
GLSurfaceView.Renderer
Giao diện này xác định các phương thức cần thiết để vẽ đồ hoạ trong GLSurfaceView. Bạn phải cung cấp cách triển khai giao diện này dưới dạng riêng một lớp và đính kèm lớp đó vào thực thể GLSurfaceView bằng cách sử dụng GLSurfaceView.setRenderer()

Giao diện GLSurfaceView.Renderer yêu cầu bạn triển khai các phương thức sau:

  • onSurfaceCreated(): Hệ thống gọi hàm này một lần khi tạo GLSurfaceView. Sử dụng phương pháp này để thực hiện các hành động chỉ cần thực hiện một lần, chẳng hạn như đặt tham số môi trường OpenGL hoặc khởi tạo đối tượng đồ hoạ OpenGL.
  • onDrawFrame(): Hệ thống gọi phương thức này trong mỗi lần vẽ lại GLSurfaceView. Sử dụng phương thức này làm điểm thực thi chính cho vẽ (và vẽ lại) đối tượng đồ hoạ.
  • onSurfaceChanged(): Hệ thống gọi phương thức này khi hình học GLSurfaceView thay đổi, bao gồm cả những thay đổi về kích thước của GLSurfaceView hoặc hướng của màn hình thiết bị. Ví dụ: hệ thống gọi phương thức này khi thiết bị thay đổi từ hướng dọc sang hướng ngang. Sử dụng phương thức này để phản hồi các thay đổi trong vùng chứa GLSurfaceView.

Gói OpenGL ES

Sau khi thiết lập khung hiển thị vùng chứa cho OpenGL ES bằng GLSurfaceViewGLSurfaceView.Renderer, bạn có thể bắt đầu gọi API OpenGL bằng các lớp sau:

  • Lớp API OpenGL ES 2.0
    • android.opengl.GLES20 - Gói này cung cấp để OpenGL ES 2.0 và có sẵn bắt đầu với Android 2.2 (API cấp 8).
  • Gói API OpenGL ES 3.0/3.1/3.2
    • android.opengl – Gói này cung cấp giao diện cho OpenGL ES 3.0/3.1 khác. Phiên bản 3.0 có sẵn kể từ Android 4.3 (API cấp 18). Đã có phiên bản 3.1 kể từ Android 5.0 (API cấp 21). Phiên bản 3.2 có sẵn kể từ phiên bản Android 7.0 (API) cấp 24).

Nếu bạn muốn bắt đầu tạo ứng dụng bằng OpenGL ES ngay, hãy làm theo Hiển thị đồ hoạ bằng OpenGL ES .

Khai báo yêu cầu về OpenGL

Nếu ứng dụng của bạn dùng các tính năng OpenGL không có trên tất cả thiết bị, bạn phải thêm các yêu cầu này trong tệp AndroidManifest.xml của bạn . Dưới đây là một số nội dung khai báo phổ biến nhất trong tệp kê khai OpenGL:

  • Yêu cầu về phiên bản OpenGL ES – Nếu ứng dụng của bạn yêu cầu một phiên bản phiên bản của OpenGL ES, bạn phải khai báo yêu cầu đó bằng cách thêm các chế độ cài đặt sau vào tệp kê khai dưới dạng như bên dưới.

    Đối với OpenGL ES 2.0:

    <!-- Tell the system this app requires OpenGL ES 2.0. -->
    <uses-feature android:glEsVersion="0x00020000" android:required="true" />
    

    Việc thêm nội dung khai báo này sẽ khiến Google Play hạn chế ứng dụng của bạn trên thiết bị không hỗ trợ OpenGL ES 2.0. Nếu ứng dụng của bạn dành riêng cho thiết bị hỗ trợ OpenGL ES 3.0, bạn cũng có thể chỉ định thông tin này trong tệp kê khai của mình:

    Đối với OpenGL ES 3.0:

    <!-- Tell the system this app requires OpenGL ES 3.0. -->
    <uses-feature android:glEsVersion="0x00030000" android:required="true" />
    

    Đối với OpenGL ES 3.1:

    <!-- Tell the system this app requires OpenGL ES 3.1. -->
    <uses-feature android:glEsVersion="0x00030001" android:required="true" />
    

    Đối với OpenGL ES 3.2:

    <!-- Tell the system this app requires OpenGL ES 3.2. -->
    <uses-feature android:glEsVersion="0x00030002" android:required="true" />
    

    Lưu ý: API OpenGL ES 3.x có khả năng tương thích ngược với API 2.0, tức là bạn có thể linh hoạt với việc triển khai OpenGL ES trong ứng dụng của bạn. Bằng cách khai báo OpenGL ES 2.0 API theo yêu cầu trong tệp kê khai, bạn có thể dùng phiên bản API đó làm mặc định, kiểm tra để biết tính sẵn có của API 3.x vào thời gian chạy, sau đó sử dụng các tính năng OpenGL ES 3.x nếu thiết bị hỗ trợ ngôn ngữ đó. Để biết thêm thông tin về cách kiểm tra phiên bản OpenGL ES được hỗ trợ bởi thiết bị, hãy xem Kiểm tra phiên bản OpenGL ES.

  • Yêu cầu về nén kết cấu – Nếu ứng dụng của bạn sử dụng kết cấu bạn phải khai báo các định dạng mà ứng dụng của bạn hỗ trợ trong tệp kê khai bằng cách sử dụng <supports-gl-texture>. Để biết thêm thông tin về tính năng nén kết cấu có sẵn hãy xem phần Hỗ trợ nén kết cấu.

    Việc khai báo các yêu cầu về nén kết cấu trong tệp kê khai sẽ ẩn ứng dụng của bạn với người dùng với thiết bị không hỗ trợ ít nhất một trong các loại nén đã khai báo. Để biết thêm thông tin về cách thức hoạt động của cơ chế lọc của Google Play khi nén kết cấu, hãy xem Phần Google Play và cách lọc định dạng nén kết cấu trong tài liệu <supports-gl-texture>.

Ánh xạ toạ độ cho các đối tượng đã vẽ

Một trong những vấn đề cơ bản khi hiển thị đồ hoạ trên thiết bị Android là màn hình của thiết bị có thể có kích thước và hình dạng khác nhau. OpenGL giả định một hệ toạ độ hình vuông, đồng nhất và theo mặc định, vẽ các toạ độ đó lên màn hình thông thường không phải hình vuông như thể nó là hình vuông hoàn toàn.

Hình 1. Hệ thống toạ độ OpenGL mặc định (bên trái) được ánh xạ tới một Android thông thường màn hình thiết bị (phải).

Hình minh hoạ ở trên cho thấy hệ toạ độ đồng nhất được giả định cho khung OpenGL trên sang trái và cách những toạ độ này ánh xạ đến màn hình thiết bị thông thường theo hướng ngang ở bên phải. Để giải quyết vấn đề này, bạn có thể áp dụng chế độ chiếu OpenGL và khung hiển thị máy ảnh cho biến đổi toạ độ để đối tượng đồ hoạ của bạn có tỷ lệ chính xác trên mọi màn hình.

Để áp dụng phép chiếu và khung hiển thị máy ảnh, bạn cần tạo ma trận chiếu và khung hiển thị máy ảnh ma trận và áp dụng chúng vào quy trình kết xuất OpenGL. Ma trận chiếu sẽ tính lại toạ độ của đồ hoạ để chúng ánh xạ chính xác tới màn hình thiết bị Android. Chế độ xem camera ma trận tạo ra phép biến đổi kết xuất các đối tượng từ một vị trí mắt cụ thể.

Chế độ xem máy ảnh và phép chiếu trong OpenGL ES 2.0 trở lên

Trong API ES 2.0 và 3.0, bạn sẽ áp dụng phép chiếu và khung hiển thị camera bằng cách thêm một thành phần ma trận trước vào chương trình đổ bóng đỉnh của đối tượng đồ hoạ. Khi thêm thành viên ma trận này, bạn có thể tạo và áp dụng phép chiếu cũng như ma trận xem máy ảnh cho các đối tượng của bạn.

  1. Thêm ma trận vào chương trình đổ bóng đỉnh – Tạo một biến cho ma trận chiếu khung hiển thị và đưa nó vào dưới dạng số nhân cho vị trí của chương trình đổ bóng. Trong ví dụ sau đây về chương trình đổ bóng đỉnh mã, thành phần uMVPMatrix đi kèm cho phép bạn áp dụng chế độ chiếu và chế độ xem bằng camera ma trận đến toạ độ của các đối tượng sử dụng chương trình đổ bóng này.

    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";
    

    Lưu ý: Ví dụ ở trên xác định một ma trận biến đổi đơn trong chương trình đổ bóng đỉnh mà bạn áp dụng ma trận chiếu kết hợp và khung hiển thị camera ma trận. Tuỳ thuộc vào yêu cầu về ứng dụng, bạn có thể muốn xác định phép chiếu riêng các thành phần ma trận xem ma trận và máy ảnh trong chương trình đổ bóng đỉnh để bạn có thể thay đổi chúng một cách độc lập.

  2. Truy cập vào ma trận chương trình đổ bóng – Sau khi tạo một nội dung hấp dẫn trong chương trình đổ bóng đỉnh để áp dụng phép chiếu và chế độ xem camera, sau đó bạn có thể truy cập biến đó để áp dụng phép chiếu và ma trận xem camera. Đoạn mã sau đây cho biết cách sửa đổi phương thức onSurfaceCreated() của quá trình triển khai GLSurfaceView.Renderer để truy cập vào ma trận biến được xác định trong chương trình đổ bóng đỉnh ở trên.

    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. Tạo ma trận phép chiếu và ma trận xem máy ảnh – Tạo phép chiếu và ma trận xem được áp dụng cho đối tượng đồ hoạ. Đoạn mã ví dụ sau đây biểu thị cách sửa đổi onSurfaceCreated() và Phương thức onSurfaceChanged() của một Triển khai GLSurfaceView.Renderer để tạo ma trận chế độ xem camera và ma trận chiếu dựa trên tỷ lệ khung hình màn hình của thiết bị.

    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. Áp dụng ma trận chiếu và ma trận xem máy ảnh – Để áp dụng phép chiếu và biến đổi chế độ xem camera, nhân các ma trận với nhau rồi đặt chúng vào đỉnh chương trình đổ bóng. Mã ví dụ sau đây cho thấy cách sửa đổi phương thức onDrawFrame() của quá trình triển khai GLSurfaceView.Renderer để kết hợp ma trận chiếu và khung hiển thị camera được tạo trong mã trên rồi áp dụng cho thành phần đồ hoạ các đối tượng được OpenGL kết xuất.

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

Để xem ví dụ đầy đủ về cách áp dụng phép chiếu và khung hiển thị camera với OpenGL ES 2.0, hãy xem phần Hiển thị đồ hoạ bằng OpenGL ES .

Mặt hình dạng và uốn lượn

Trong OpenGL, mặt của một hình dạng là một bề mặt được xác định bởi ba điểm trở lên trong không gian ba chiều . Một tập hợp gồm ba điểm ba chiều trở lên (được gọi là các đỉnh trong OpenGL) có mặt trước và một khuôn mặt phía sau. Làm sao để biết mặt nào là mặt trước và mặt nào sau? Đây là một câu hỏi rất hay! Chiến lược phát hành đĩa đơn câu trả lời liên quan đến quanh co hoặc hướng mà theo đó bạn xác định các điểm của hình dạng.

Toạ độ tại
các đỉnh của tam giác

Hình 1. Hình minh hoạ danh sách toạ độ chuyển thành thứ tự vẽ ngược chiều kim đồng hồ.

Trong ví dụ này, các điểm của tam giác được xác định theo thứ tự sao cho chúng được vẽ theo ngược chiều kim đồng hồ. Thứ tự vẽ các toạ độ này xác định phương thức cuộn dây hướng cho hình dạng. Theo mặc định, trong OpenGL, khuôn mặt được vẽ ngược chiều kim đồng hồ là mặt trước. Hình tam giác trong Hình 1 được xác định sao cho bạn nhìn vào mặt trước của hình dạng (như được giải thích bởi OpenGL) và mặt còn lại là mặt sau.

Tại sao việc biết được khuôn mặt của một hình dạng nào là khuôn mặt trước lại quan trọng? Câu trả lời có liên quan đến tính năng thường dùng của OpenGL, được gọi là chọn lọc khuôn mặt. Chọn khuôn mặt là một tuỳ chọn cho OpenGL môi trường cho phép quy trình kết xuất bỏ qua (không tính toán hoặc vẽ) mặt sau của hình dạng, tiết kiệm thời gian, bộ nhớ và chu kỳ xử lý:

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

Nếu bạn cố gắng sử dụng tính năng chọn khuôn mặt mà không biết cạnh nào của hình dạng là trước và sau, đồ hoạ OpenGL của bạn sẽ trông hơi mỏng hoặc có thể không hiển thị. Vì vậy, hãy luôn xác định toạ độ của các hình dạng OpenGL theo thứ tự vẽ ngược chiều kim đồng hồ.

Lưu ý: Bạn có thể thiết lập môi trường OpenGL để xử lý mặt trước theo chiều kim đồng hồ, nhưng làm vậy sẽ cần nhiều mã hơn và có nhiều khả năng gây nhầm lẫn có kinh nghiệm về OpenGL khi bạn yêu cầu họ trợ giúp. Vậy nên, đừng làm việc đó.

Phiên bản OpenGL và khả năng tương thích với thiết bị

Thông số kỹ thuật API OpenGL ES 1.0 và 1.1 đã được hỗ trợ kể từ Android 1.0. Lập trình đồ hoạ với API OpenGL ES 1.0/1.1 khác biệt đáng kể so với việc sử dụng API 2.0 và các phiên bản cao hơn. OpenGL ES 2.0 được hỗ trợ bởi tất cả các thiết bị Android bắt đầu từ Android 2.2 (API cấp 8) và phiên bản sớm nhất được đề xuất cho các ứng dụng mới được phát triển bằng OpenGL ES. OpenGL ES 3.0 được hỗ trợ với Android 4.3 (API cấp 18) trở lên, trên các thiết bị cung cấp triển khai API OpenGL ES 3.0. Để biết thông tin về số lượng thiết bị chạy Android tương đối có hỗ trợ một phiên bản OpenGL ES nhất định, hãy xem Trang tổng quan về phiên bản OpenGL ES.

Bạn nên xem xét kỹ các yêu cầu về đồ hoạ rồi chọn API phiên bản phù hợp nhất với ứng dụng của bạn. Để biết thêm thông tin, hãy xem Chọn phiên bản API OpenGL.

OpenGL ES API 3.0 có thêm nhiều tính năng và hiệu năng tốt hơn 2.0 API, đồng thời tương thích ngược. Điều này có nghĩa là bạn có thể viết tiêu chí nhắm mục tiêu ứng dụng OpenGL ES 2.0 và có điều kiện đưa các tính năng đồ hoạ OpenGL ES 3.0 vào nếu có. Cho biết thêm thông tin về cách kiểm tra tính sẵn có của API 3.0, hãy xem Kiểm tra phiên bản OpenGL ES

Hỗ trợ nén kết cấu

Nén kết cấu có thể làm tăng đáng kể hiệu suất của ứng dụng OpenGL của bạn bằng cách giúp giảm yêu cầu về bộ nhớ và sử dụng băng thông bộ nhớ hiệu quả hơn. Hệ điều hành Android khung này cung cấp hỗ trợ cho định dạng nén ETC1 như một tính năng tiêu chuẩn, bao gồm Lớp tiện ích ETC1Util và công cụ nén etc1tool (nằm trong Android SDK tại <sdk>/tools/). Ví dụ về một ứng dụng Android sử dụng nén kết cấu, hãy xem mã mẫu CompressedTextureActivity trong SDK Android (<sdk>/samples/<version>/ApiDemos/src/com/example/android/apis/graphics/).

Định dạng ETC1 được tất cả thiết bị Android hỗ trợ OpenGL ES 2.0 trở lên hỗ trợ.

Lưu ý: Định dạng nén kết cấu ETC1 không hỗ trợ hoạ tiết có độ trong suốt (kênh alpha). Nếu ứng dụng của bạn yêu cầu hoạ tiết có độ trong suốt, bạn nên tìm hiểu các định dạng nén kết cấu khác có trên thiết bị mục tiêu của bạn. Đáp phương pháp kết xuất kết cấu kênh alpha bằng ETC1 là liên kết hai đối tượng kết cấu ETC1: đầu tiên với dữ liệu màu, thứ hai là với dữ liệu kênh alpha và sau đó kết hợp các giá trị của hai hoạ tiết trong chương trình đổ bóng mảnh.

Đảm bảo các định dạng nén hoạ tiết ETC2/EAC sẽ hoạt động khi sử dụng OpenGL ES API 3.0. Định dạng hoạ tiết này cung cấp tỷ lệ nén tuyệt vời với chất lượng hình ảnh cao và cũng hỗ trợ độ trong suốt (kênh alpha).

Ngoài các định dạng ETC, các thiết bị Android đã hỗ trợ nhiều định dạng nén kết cấu dựa trên Chipset GPU và cách triển khai OpenGL của họ. Bạn nên tìm hiểu khả năng hỗ trợ nén kết cấu trên các thiết bị bạn đang nhắm mục tiêu để xác định loại nén mà ứng dụng của bạn sẽ của Google. Để xác định định dạng hoạ tiết nào được hỗ trợ trên một thiết bị cho trước, bạn phải truy vấn thiết bị và xem lại tên tiện ích OpenGL, xác định định dạng nén kết cấu (và các tính năng OpenGL khác) được hỗ trợ bởi thiết bị. Sau đây là một số định dạng nén kết cấu thường được hỗ trợ:

  • Áp dụng nén kết cấu có thể mở rộng (ASTC) – Định dạng nén kết cấu được thiết kế để thay thế các định dạng trước đây. Linh hoạt hơn so với các định dạng trước đây do hỗ trợ nhiều định dạng kích thước khối.
    • GL_KHR_texture_compression_astc_ldr
    • GL_KHR_texture_compression_astc_hdr(dải động cao)
  • S3TC (DXTn/DXTC) – Nén kết cấu S3 (S3TC) có một vài (DXT1 đến DXT5) và ít có sẵn hơn. Định dạng hỗ trợ hoạ tiết RGB với Kênh alpha 4 bit hoặc 8 bit alpha. Các định dạng này được biểu thị bằng tiện ích OpenGL sau tên:
    • GL_EXT_texture_compression_s3tc
    Một số thiết bị chỉ hỗ trợ biến thể định dạng DXT1; hỗ trợ có giới hạn này được thể hiện bằng tên tiện ích OpenGL sau:
    • GL_EXT_texture_compression_dxt1

Các định dạng nén kết cấu sau đây được xem là định dạng cũ và không nên dùng để sử dụng trong các ứng dụng mới:

  • ATITC (ATC) – Nén kết cấu ATI (ATITC hoặc ATC) được hỗ trợ trên nhiều loại thiết bị và hỗ trợ nén tốc độ cố định cho hoạ tiết RGB có và không có kênh alpha. Định dạng này có thể được biểu thị bằng một số tên tiện ích OpenGL, ví dụ:
    • GL_AMD_compressed_ATC_texture
    • GL_ATI_texture_compression_atitc
  • PVRTC - Nén kết cấu PowerVR (PVRTC) có sẵn trên đa dạng thiết bị và hỗ trợ kết cấu 2 bit và 4 bit cho mỗi điểm ảnh có hoặc không có kênh alpha. Định dạng này được biểu thị bằng tên tiện ích OpenGL sau đây:
    • GL_IMG_texture_compression_pvrtc
  • 3DC – Nén kết cấu 3DC (3DC) là một định dạng ít được cung cấp rộng rãi hơn hỗ trợ hoạ tiết RGB với kênh alpha. Định dạng này được biểu thị bằng OpenGL sau tên tiện ích:
    • GL_AMD_compressed_3DC_texture

Cảnh báo: Các định dạng nén kết cấu này không được hỗ trợ trên tất cả các thiết bị. Việc hỗ trợ các định dạng này có thể khác nhau tuỳ theo nhà sản xuất và thiết bị. Cho thông tin về cách xác định định dạng nén kết cấu nào có trên một thiết bị cụ thể, hãy xem phần tiếp theo.

Lưu ý: Sau khi quyết định chọn định dạng nén kết cấu sẽ hỗ trợ, hãy đảm bảo bạn khai báo các ứng dụng đó trong tệp kê khai bằng cách sử dụng <supports-gl-texture> Việc sử dụng nội dung khai báo này sẽ bật cơ chế lọc theo các dịch vụ bên ngoài như Google Play để ứng dụng của bạn chỉ được cài đặt trên những thiết bị hỗ trợ định dạng mà ứng dụng của bạn yêu cầu. Để biết thông tin chi tiết, hãy xem Khai báo tệp kê khai OpenGL.

Xác định tiện ích OpenGL

Cách triển khai OpenGL sẽ khác nhau tuỳ theo thiết bị Android về các tiện ích cho OpenGL ES API được hỗ trợ. Các tiện ích này bao gồm nén kết cấu, nhưng thường cũng bao gồm các thao tác nén khác tiện ích mở rộng cho bộ tính năng OpenGL.

Xác định định dạng nén kết cấu và các tiện ích OpenGL khác được hỗ trợ trên thiết bị cụ thể:

  1. Chạy mã sau trên thiết bị mục tiêu của bạn để xác định loại nén kết cấu được hỗ trợ:

    Kotlin

    var extensions = gl.glGetString(GL10.GL_EXTENSIONS)
    

    Java

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

    Cảnh báo: Kết quả của lệnh gọi này khác nhau tuỳ theo mẫu thiết bị! Bạn phải thực hiện lệnh gọi này trên một số thiết bị mục tiêu để xác định những loại nén nào thường được hỗ trợ.

  2. Xem xét kết quả của phương pháp này để xác định tiện ích OpenGL nào được hỗ trợ trên thiết bị.

Gói tiện ích Android (AEP)

AEP đảm bảo rằng ứng dụng của bạn hỗ trợ một tập hợp các tiện ích OpenGL được chuẩn hoá nêu trên và hơn thế nữa tập hợp lõi được mô tả trong thông số kỹ thuật OpenGL 3.1. Đóng gói các tiện ích này lại với nhau khuyến khích một loạt chức năng nhất quán trên các thiết bị, đồng thời cho phép nhà phát triển tận dụng tận dụng thế hệ mới nhất của thiết bị GPU di động.

AEP cũng cải thiện hỗ trợ cho hình ảnh, vùng đệm lưu trữ của chương trình đổ bóng và bộ đếm nguyên tử trong chương trình đổ bóng mảnh.

Để ứng dụng của bạn có thể sử dụng AEP, tệp kê khai của ứng dụng phải khai báo rằng AEP là bắt buộc. Ngoài ra, phiên bản nền tảng phải hỗ trợ lệnh đó.

Mọi tính năng bổ sung được chỉ định trong AEP đều có trong OpenGL ES 3.2 cơ sở đặc điểm kỹ thuật. Nếu ứng dụng của bạn yêu cầu OpenGL ES 3.2, bạn không cần yêu cầu AEP.

Khai báo yêu cầu AEP trong tệp kê khai như sau:

<uses-feature android:name="android.hardware.opengles.aep"
              android:required="true" />

Để xác minh rằng phiên bản nền tảng hỗ trợ AEP, hãy sử dụng Phương thức hasSystemFeature(String), truyền vào FEATURE_OPENGLES_EXTENSION_PACK làm đối số. Đoạn mã sau đây cho thấy ví dụ về cách thực hiện:

Kotlin

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

Java

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

Nếu phương thức này trả về giá trị true, thì AEP sẽ được hỗ trợ.

Để biết thêm thông tin về AEP, hãy truy cập trang của AEP tại Khronos OpenGL ES Registry.

Kiểm tra phiên bản OpenGL ES

Có một số phiên bản OpenGL ES có trên thiết bị Android. Bạn có thể chỉ định phiên bản tối thiểu của API mà ứng dụng của bạn yêu cầu trong tệp kê khai, nhưng có thể bạn cũng muốn tận dụng đồng thời các tính năng trong một API mới hơn. Ví dụ: OpenGL ES 3.0 API tương thích ngược với phiên bản 2.0 của API, vì vậy bạn có thể muốn viết ứng dụng của bạn để ứng dụng sử dụng các tính năng OpenGL ES 3.0, nhưng sẽ quay lại API 2.0 nếu API 3.0 không có sẵn.

Trước khi sử dụng các tính năng OpenGL ES từ một phiên bản cao hơn yêu cầu tối thiểu trong tệp kê khai ứng dụng của bạn, ứng dụng của bạn nên kiểm tra phiên bản API có trên thiết bị. Bạn có thể làm việc này bằng một trong hai cách:

  1. Cố gắng tạo ngữ cảnh OpenGL ES cấp cao hơn (EGLContext) và kiểm tra kết quả.
  2. Tạo một ngữ cảnh OpenGL ES được hỗ trợ tối thiểu và kiểm tra giá trị phiên bản.

Mã ví dụ sau đây minh hoạ cách kiểm tra phiên bản OpenGL ES hiện có bằng cách tạo EGLContext rồi kiểm tra kết quả. Ví dụ này cho biết cách kiểm tra Phiên bản 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;
  }
}

Nếu phương thức createContext() hiển thị ở trên trả về giá trị rỗng, mã của bạn phải tạo một OpenGL Thay vào đó, ngữ cảnh ES 2.0 và quay lại chỉ sử dụng API đó.

Ví dụ về mã sau đây minh hoạ cách kiểm tra phiên bản OpenGL ES bằng cách tạo một giá trị tối thiểu trước tiên, rồi kiểm tra chuỗi phiên bản:

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.

Với phương pháp này, nếu khám phá ra rằng thiết bị hỗ trợ phiên bản API cấp cao hơn, bạn phải huỷ bỏ ngữ cảnh OpenGL ES tối thiểu và tạo một ngữ cảnh mới có bối cảnh phiên bản API có sẵn.

Chọn phiên bản API OpenGL

OpenGL ES phiên bản 2.0 và phiên bản 3.0 đều cung cấp giao diện đồ hoạ hiệu suất để tạo trò chơi 3D, hình ảnh trực quan và giao diện người dùng. Đồ họa việc lập trình cho OpenGL ES 2.0 và 3.0 phần lớn là tương tự nhau, với phiên bản 3.0 đại diện cho một siêu tập hợp của API 2.0 với các tính năng bổ sung. Lập trình API OpenGL ES 1.0/1.1 so với OpenGL ES 2.0 và 3.0 khác nhau đáng kể và không được khuyến nghị cho các ứng dụng mới. Nhà phát triển nên cân nhắc kỹ lưỡng các yếu tố sau trước khi bắt đầu phát triển ứng dụng bằng các API sau:

  • Khả năng tương thích với thiết bị - Nhà phát triển nên cân nhắc các loại thiết bị, Các phiên bản Android và phiên bản OpenGL ES được cung cấp cho khách hàng của họ. Thông tin khác về khả năng tương thích OpenGL trên các thiết bị, hãy xem phiên bản OpenGL và khả năng tương thích với thiết bị.
  • Hỗ trợ hoạ tiết – API OpenGL ES 3.0 hỗ trợ hoạ tiết tốt nhất vì nó đảm bảo tính sẵn có của định dạng nén ETC2, hỗ trợ trong suốt. Tuy nhiên, việc triển khai API 2.0 bao gồm hỗ trợ cho ETC1 định dạng kết cấu này không hỗ trợ độ trong suốt. Để triển khai tính minh bạch bằng công cụ nén bạn phải sử dụng hai hoạ tiết ETC1 (phân tách giữa màu và alpha) hoặc cung cấp tài nguyên ở các định dạng nén khác được thiết bị bạn đang nhắm mục tiêu hỗ trợ. Để biết thêm thông tin, hãy xem phần Hỗ trợ nén kết cấu.

Mặc dù khả năng tương thích và khả năng hỗ trợ hoạ tiết có thể ảnh hưởng đến bạn nên chọn phiên bản OpenGL API dựa trên những gì bạn cho là mang lại trải nghiệm tốt nhất cho người dùng của bạn.