OpenGL ES

Android obsługuje wysoką wydajność grafiki 2D i 3D dzięki Open Graphics Library. (OpenGL®), a w szczególności z interfejsu OpenGL ES API. OpenGL to wieloplatformowy interfejs API graficzny, który określa standardowy interfejs oprogramowania dla procesora graficznego 3D. OpenGL ES to rodzaj interfejsu OpenGL specyfikacja przeznaczona dla urządzeń umieszczonych na stronie. Android obsługuje kilka wersji OpenGL ES Interfejs API:

  • OpenGL ES 2.0 – ta specyfikacja interfejsu API jest obsługiwana w systemie Android 2.2 (poziom API 8) i nowszym.
  • OpenGL ES 3.0 – ta specyfikacja interfejsu API jest obsługiwana w Androidzie 4.3 (poziom API 18) i nowszym.
  • OpenGL ES 3.1 – ta specyfikacja interfejsu API jest obsługiwana przez Androida 5.0 (poziom API 21) i nowsze wersje.
  • OpenGL ES 3.2 – ta specyfikacja interfejsu API jest obsługiwana w Androidzie 7.0 (poziom API 24) i nowszych.

Uwaga: Urządzenie bez względu na wersję platformy Androida nie obsługuje interfejsu API OpenGL ES 3.0, chyba że producent urządzenia udostępnia wdrożenia tego potoku graficznego. Jeśli w pliku manifestu wskażesz, że Wymagany jest interfejs OpenGL ES 3.0 – możesz mieć pewność, że ta wersja będzie dostępna na urządzeniu. Jeśli określisz, że wymagana jest wersja niższego poziomu, ale Jeśli chcesz używać funkcji w wersji 3.0, jeśli są dostępne, sprawdź w czasie działania aby sprawdzić, jaką wersję OpenGL obsługuje urządzenie. Dowiedz się, jak jak to zrobić, zobacz Sprawdzanie wersji OpenGL ES.

Uwaga: Android obsługuje standard OpenGL ES 1.0 i 1.1, ale te wersje interfejsu API są wycofane i nie powinny być używane przez nowoczesne aplikacje.

Uwaga: Konkretny interfejs API udostępniany przez platformę Androida jest podobny do interfejsu J2ME JSR239 OpenGL ES API. ale nie jest identyczna. Jeśli znasz specyfikację J2ME JSR239, zwróć uwagę na odmian.

Patrz też

Podstawy

Android obsługuje OpenGL zarówno przez interfejs API platformy, jak i środowisko programistyczne Zestaw (NDK). Ta część koncentruje się na interfejsach platformy Android. Więcej informacji na temat NDK: zobacz pakiet Android NDK.

Na platformie Androida są 2 podstawowe klasy, które umożliwiają tworzenie i manipulowanie grafika z interfejsem OpenGL ES API: GLSurfaceView i GLSurfaceView.Renderer Jeśli chcesz używać trybu OpenGL w aplikacji na Androida, Twoim pierwszym celem będzie zrozumienie, jak wdrożyć te zajęcia w ćwiczeniu.

GLSurfaceView
Ta klasa to View, w której możesz rysować i manipulować obiektami za pomocą Interfejs OpenGL API wywołuje i działa podobnie do SurfaceView. Za pomocą tę klasę, tworząc instancję GLSurfaceView i dodając Renderer. Jeśli jednak chcesz przechwytywać zdarzeń na ekranie dotykowym, rozszerz klasę GLSurfaceView na jak zaimplementować detektory dotykowe, jak pokazano na lekcji dotyczącej trenowania OpenGL, Reagowanie na zdarzenia dotknięcia
GLSurfaceView.Renderer
Ten interfejs definiuje metody wymagane do rysowania grafiki w GLSurfaceView. Należy zapewnić implementację tego interfejsu jako oddziel klasę i dołącz ją do instancji GLSurfaceView za pomocą GLSurfaceView.setRenderer()

Interfejs GLSurfaceView.Renderer wymaga zaimplementowania następujące metody:

  • onSurfaceCreated(): system nazywa to raz podczas tworzenia GLSurfaceView. Użyj tej metody, aby wykonać czynności, które trzeba wykonać tylko raz, takich jak ustawienie parametrów środowiska OpenGL lub inicjowanie obiektów graficznych OpenGL.
  • onDrawFrame(): system wywołuje tę metodę przy każdym ponownym odczytaniu GLSurfaceView. Użyj tej metody jako głównego punktu wykonywania dla przez rysowanie (i ponowne rysowanie) obiektów graficznych.
  • onSurfaceChanged(): system wywołuje tę metodę, gdy zmieni się geometria GLSurfaceView, w tym rozmiar GLSurfaceView lub orientację ekranu urządzenia. Na przykład wywołania systemowe tej metody, gdy orientacja urządzenia zmieni się z pionowej na poziomą. Użyj tej metody, aby: reagować na zmiany w kontenerze GLSurfaceView.

Pakiety OpenGL ES

Po utworzeniu widoku kontenera dla OpenGL ES za pomocą interfejsów GLSurfaceView i GLSurfaceView.Renderer można rozpocząć interfejsów API OpenGL do wywoływania za pomocą tych klas:

  • Klasa interfejsu API OpenGL ES 2.0
    • android.opengl.GLES20 – ten pakiet zawiera: interfejsu OpenGL ES 2.0 i jest dostępny od Androida 2.2 (poziom API 8).
  • Pakiety interfejsów API OpenGL ES 3.0/3.1/3.2
    • android.opengl – ten pakiet udostępnia interfejs OpenGL ES 3.0/3.1. zajęcia. Dostępna jest wersja 3.0 od Androida 4.3 (poziom API 18). Dostępna jest wersja 3.1 począwszy od Androida 5.0 (poziom interfejsu API 21). Dostępna jest wersja 3.2 od Androida 7.0 (interfejs API) na poziomie 24).

Jeśli chcesz od razu zacząć tworzyć aplikację z użyciem OpenGL ES, wykonaj Wyświetlanie grafiki przez OpenGL ES zajęcia.

Deklarowanie wymagań dotyczących OpenGL

Jeśli aplikacja korzysta z funkcji OpenGL, które nie są dostępne na wszystkich urządzeniach, musisz dodać parametr te wymagania w pliku AndroidManifest.xml . Oto najpopularniejsze deklaracje w pliku manifestu OpenGL:

  • Wymagania dotyczące wersji OpenGL ES – jeśli aplikacja wymaga określonego wersja OpenGL ES, musisz zadeklarować to wymaganie, dodając do pliku manifestu następujące ustawienia jako: poniżej.

    OpenGL ES 2.0:

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

    Jeśli dodasz tę deklarację, Google Play ograniczy możliwość instalowane na urządzeniach, które nie obsługują OpenGL ES 2.0. Jeśli aplikacja jest przeznaczona wyłącznie obsługujące OpenGL ES 3.0, możesz też określić to w pliku manifestu:

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

    Uwaga: Interfejs API OpenGL ES 3.x jest zgodny wstecznie z interfejsem API 2.0, co oznacza, że w sposób elastyczny podczas implementacji standardu OpenGL ES w aplikacji. Przez zadeklarowanie trybu OpenGL Interfejs ES 2.0 API jest wymagany w pliku manifestu. Możesz używać tej wersji interfejsu API jako domyślnego. Sprawdź , aby sprawdzić dostępność interfejsu API 3.x w czasie działania, a następnie użyj funkcji OpenGL ES 3.x, jeśli urządzenie ją obsługuje. Aby dowiedzieć się więcej o sprawdzaniu wersji OpenGL ES obsługiwanej przez urządzenia, zobacz Sprawdzanie wersji OpenGL ES.

  • Wymagania dotyczące kompresji tekstur – jeśli aplikacja używa tekstury. formatów kompresji, w pliku manifestu musisz zadeklarować formaty obsługiwane przez aplikację za pomocą <supports-gl-texture>. Aby uzyskać więcej informacji o dostępnej kompresji tekstur formatów: patrz Obsługa kompresji tekstur.

    Zadeklarowanie w pliku manifestu wymagań dotyczących kompresji tekstur ukrywa aplikację przed użytkownikami z urządzeniami, które nie obsługują co najmniej jednego z zadeklarowanych przez Ciebie typów kompresji. Więcej o tym, jak działa filtrowanie w Google Play pod kątem kompresji tekstur, znajdziesz w Sekcja Google Play i filtrowanie kompresji tekstur w dokumentacji <supports-gl-texture>.

Mapowanie współrzędnych rysowanych obiektów

Jednym z podstawowych problemów z wyświetlaniem grafiki na urządzeniach z Androidem jest to, że mogą różnią się rozmiarem i kształtem. OpenGL zakłada kwadrat, jednolity układ współrzędnych i, domyślnie, rysuje te współrzędne na ekranie, który zazwyczaj nie jest kwadratowy, tak jakby był on idealnie kwadratowy.

Rysunek 1. Domyślny układ współrzędnych OpenGL (po lewej) zmapowany na typowego Androida. ekran urządzenia (po prawej).

Ilustracja powyżej przedstawia jednolity układ współrzędnych przyjęty dla klatki OpenGL na od lewej oraz jak te współrzędne mapują się na ekran typowego urządzenia w orientacji poziomej, po prawej. Aby rozwiązać ten problem, można zastosować tryby projekcji OpenGL i widoki kamery można przekształcić współrzędne tak, aby obiekty graficzne miały prawidłowe proporcje na każdym wyświetlaczu.

Aby zastosować projekcję i widoki z kamery, należy utworzyć macierz projekcji i widok z kamery i zastosować je w potoku renderowania OpenGL. Macierz projekcji ponownie oblicza współrzędne grafiki, aby były prawidłowo mapowane na ekrany urządzeń z systemem Android. Widok z kamery tworzy przekształcenie, które renderuje obiekty z określonej pozycji oka.

Projekcja i obraz z kamery w OpenGL ES 2.0 i nowszych

W interfejsach API ES 2.0 i 3.0 możesz zastosować projekcję i widok z kamery, najpierw dodając element matrycy. do cieniowania wierzchołków obiektów graficznych. Po dodaniu tego elementu macierzy generować i stosować macierze projekcji i obrazu z kamery do swoich obiektów.

  1. Dodaj macierz do cieniowania wierzchołków – utwórz zmienną do macierzy projekcji widoku. i uwzględnić go jako mnożnik pozycji cieniowania. Moduł cieniowania wierzchołków poniżej kod, dołączony użytkownik uMVPMatrix umożliwia korzystanie z funkcji projekcji i oglądania z kamery macierze ze współrzędnymi obiektów korzystających z tego cieniowania.

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

    Uwaga: przykład powyżej definiuje jedną macierz przekształceń w cieniowaniu wierzchołków, do którego stosujesz połączoną matrycę projekcji i obraz z kamery. lub macierz. W zależności od wymagań aplikacji możesz zdefiniować osobną prognozę elementy macierzy i matrycy kamery w cieniowaniu wierzchołków, aby można je było zmieniać dzięki czemu mogą pracować niezależnie.

  2. Otwórz macierz cieniowania – po utworzeniu w maszynie cieniowania wierzchołków za pomocą projekcji i widoku kamery, można uzyskać dostęp do tej zmiennej, aby zastosować projekcję. i matryc obrazu. Ten kod pokazuje, jak zmodyfikować metodę onSurfaceCreated() implementacji GLSurfaceView.Renderer, aby uzyskać dostęp do macierzy zdefiniowaną powyżej w module cieniowania wierzchołków.

    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. Utwórz macierze obrazu i projekcji – wygeneruj projekcję i macierze wyświetlania i zastosowania obiektów graficznych. Poniższy przykładowy kod pokazuje, jak zmodyfikować onSurfaceCreated() i onSurfaceChanged() metod implementacji GLSurfaceView.Renderer do tworzenia macierzy obrazu z kamery oraz macierz projekcyjną opartą na współczynniku proporcji ekranu urządzenia.

    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. Zastosuj projekcję i matryce obrazu – aby zastosować projekcję i przekształceń widoku z kamery, pomnóż macierze przez siebie i umieść je w wierzchołku program do cieniowania. Ten przykładowy kod pokazuje, jak można połączyć metodę onDrawFrame() implementacji GLSurfaceView.Renderer macierz projekcyjną i widok kamery utworzone w powyższym kodzie, a następnie zastosuj je do grafiki. obiektów do renderowania przez 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
        ...
    }
    

Pełen przykład zastosowania projekcji i widoku z kamery w środowisku OpenGL ES 2.0 znajdziesz w artykule Wyświetlanie grafiki w interfejsie OpenGL ES. zajęcia.

Kształt twarzy i skrętów

W systemie OpenGL ściana kształtu to powierzchnia definiowana przez trzy lub więcej punktów w trójwymiarowym widoku kosmosu. Zestaw trzech lub więcej trójwymiarowych punktów (w interfejsie OpenGL nazywany wierzchołkami) ma przednią ścianę. i twarz z tyłu. Skąd wiadomo, która twarz jest z przodu, a która z tyłu? Dobre pytanie. odpowiedź dotyczy zawinięcia, czyli kierunku, w którym definiuje się punkty kształtu.

Współrzędne
wierzchołki trójkąta

Rysunek 1. Grafika przedstawiająca listę współrzędnych, która przekłada się na kolejność rysowania w lewo.

W tym przykładzie punkty na trójkącie zostały określone w takiej kolejności, aby zostały narysowane w lewo. Kolejność rysowania tych współrzędnych określa zwinięcie kierunek kształtu. Domyślnie w trybie OpenGL twarz rysowana w lewo jest przednią. Trójkąt widoczny na Rysunku 1 jest zdefiniowany tak, aby patrzeć na przednią stronę kształt (zinterpretowany przez OpenGL), a druga strona to tylna ściana.

Dlaczego ważne jest, aby wiedzieć, która ściana kształtu jest przednia? Odpowiedź dotyczy często używana funkcja OpenGL zwana zbieraniem twarzy. Strukcje twarzy są dostępne dla trybu OpenGL. które pozwala potokowi renderowania zignorować (a nie obliczyć ani narysować) tylnej strony kształt, oszczędzanie czasu, pamięci i cykle przetwarzania:

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

Jeśli próbujesz użyć funkcji zaznaczania twarzy, nie wiedząc, po których stronach kształtów Jeśli przód i tył, i z tyłu są wyświetlane, grafika OpenGL będzie nieco cienka lub może w ogóle nie będzie widoczna. Zatem zawsze definiuj współrzędne kształtów OpenGL w kolejności rysowania w kierunku przeciwnym do ruchu wskazówek zegara.

Uwaga: można ustawić środowisko OpenGL w taki sposób, aby traktowało twarzy w kierunku zgodnym z ruchem wskazówek zegara, ale wymaga to więcej kodu i może dezorientować. programistów OpenGL, jeśli chcesz ich poprosić o pomoc. Dlatego nie rób tego.

Wersje OpenGL i zgodność urządzeń

Specyfikacje interfejsu API OpenGL ES 1.0 i 1.1 są obsługiwane od Androida 1.0. Programowanie graficzne przy użyciu interfejsu API OpenGL ES 1.0/1.1 znacznie się różni od interfejsu API 2.0 i wyższych. OpenGL ES 2.0 jest obsługiwany przez wszystkie urządzenia z Androidem 2.2 (poziom interfejsu API 8) i jest najwcześniejsza wersja zalecana dla nowych aplikacji tworzonych przy użyciu OpenGL ES. OpenGL ES 3.0 jest obsługiwany w systemie Android 4.3 (poziom interfejsu API 18) lub nowszym na urządzeniach, które zapewniają i wdrożyć interfejs API OpenGL ES 3.0. Informacje o względnej liczbie urządzeń z Androidem obsługujące daną wersję OpenGL ES, zapoznaj się z sekcją Panel wersji OpenGL ES.

Uważnie rozważ wymagania dotyczące grafiki i wybierz interfejs API która będzie najlepsza dla Twojej aplikacji. Więcej informacji: Wybór wersji interfejsu API OpenGL.

Interfejs OpenGL ES 3.0 API oferuje dodatkowe funkcje i zapewnia lepszą wydajność niż interfejs API 2.0. również zgodne wstecznie. Oznacza to, że można określić kierowanie na aplikację, standardu OpenGL ES 2.0 i warunkowo uwzględniaj funkcje graficzne OpenGL ES 3.0, jeśli są dostępne. Dla: więcej informacji na temat sprawdzania dostępności interfejsu API 3.0 znajdziesz w artykule Sprawdzanie wersji OpenGL ES

Obsługa kompresji tekstur

Kompresja tekstur może znacznie zwiększyć wydajność aplikacji OpenGL przez zmniejsza wymagania dotyczące pamięci i efektywniej wykorzystuje przepustowość pamięci. Android zapewnia obsługę formatu kompresji ETC1 jako standardowej funkcji, klasy użytkowej ETC1Util i narzędzie do kompresji etc1tool (znajdujące się w SDK dla Androida na stronie <sdk>/tools/). Oto przykład aplikacji na Androida, która używa kompresję tekstur, zobacz przykładowy kod CompressedTextureActivity w pakiecie SDK na Androida (<sdk>/samples/<version>/ApiDemos/src/com/example/android/apis/graphics/).

Format ETC1 jest obsługiwany przez wszystkie urządzenia z Androidem, które obsługują standard OpenGL ES 2.0 lub nowszy.

Uwaga: format kompresji tekstur ETC1 nie obsługuje tekstur ze znakiem przezroczystość (kanał alfa). Jeśli Twoja aplikacja wymaga tekstur z przezroczystością, zbadania innych formatów kompresji tekstur dostępnych na urządzeniach docelowych. O Metodą renderowania tekstur kanału alfa przy użyciu ETC1 jest powiązanie dwóch obiektów tekstur ETC1: najpierw danymi o kolorze, drugi z danymi kanału alfa, a następnie połączyć wartości z obu możesz użyć funkcji cieniowania fragmentów.

Formaty kompresji tekstur ETC2/EAC będą dostępne podczas korzystania z interfejsu OpenGL ES 3.0 API. Ten format tekstur zapewnia znakomite współczynniki kompresji oraz wysoką jakość obrazu obsługuje też przezroczystość (kanał alfa).

Oprócz formatów ETC urządzenia z Androidem obsługują różne funkcje kompresji tekstur, oparte na chipsety GPU i implementacje OpenGL. Zalecamy sprawdzenie obsługi kompresji tekstur na na urządzenia, na które jest kierowana aplikacja, w celu określenia typów kompresji . Aby określić, które formaty tekstur są obsługiwane przez dane urządzenie, należy Wyślij zapytanie do urządzenia i sprawdź nazwy rozszerzeń OpenGL. określające formaty kompresji tekstur (oraz inne funkcje OpenGL) obsługiwane przez urządzenia. Oto niektóre powszechnie obsługiwane formaty kompresji tekstur:

  • Adaptable Scalable Texture Compression (ASTC) – format kompresji tekstur. która ma zastąpić wcześniejsze formaty. Większa elastyczność w porównaniu z wcześniejszymi formatami dzięki obsłudze różnych bloki.
    • GL_KHR_texture_compression_astc_ldr
    • GL_KHR_texture_compression_astc_hdr(wysoki zakres dynamiczny)
  • S3TC (DXTn/DXTC) – kompresja tekstur S3 (S3TC) obejmuje kilka (od DXT1 do DXT5) i jest mniej powszechnie dostępna. Format obsługuje tekstury RGB z 4- lub 8-bitowy kanał alfa. Te formaty są reprezentowane przez następujące rozszerzenie OpenGL nazwa:
    • GL_EXT_texture_compression_s3tc
    . Niektóre urządzenia obsługują tylko format DXT1. ta ograniczona obsługa jest reprezentowana przez następującą nazwę rozszerzenia OpenGL:
    • GL_EXT_texture_compression_dxt1

Poniższe formaty kompresji tekstur są uważane za formaty starszego typu i nie są zalecane do wykorzystania w nowych aplikacjach:

  • ATITC (ATC) – kompresja tekstur ATI (ATITC lub ATC) jest dostępna szeroki wybór urządzeń i obsługuje stałą szybkość kompresji tekstur RGB z i bez kanału alfa. Ten format może być reprezentowany przez kilka nazw rozszerzeń OpenGL, na przykład:
    • GL_AMD_compressed_ATC_texture
    • GL_ATI_texture_compression_atitc
  • PVRTC – kompresja tekstury PowerVR (PVRTC) jest dostępna w różnych urządzeń oraz obsługuje tekstury 2-bitowe i 4-bitowe na piksel z kanałem alfa lub bez niego. Jest on reprezentowany przez następującą nazwę rozszerzenia OpenGL:
    • GL_IMG_texture_compression_pvrtc
  • 3DC – kompresja tekstury 3DC (3DC) to mniej powszechnie dostępny format, obsługuje tekstury RGB z kanałem alfa. Format jest reprezentowany przez następujące tryby OpenGL nazwa rozszerzenia:
    • GL_AMD_compressed_3DC_texture

Ostrzeżenie: te formaty kompresji tekstur nie są obsługiwane na wszystkich urządzeniach. Obsługa tych formatów może się różnić w zależności od producenta i urządzenia. Dla: jak określić formaty kompresji tekstur na danym urządzeniu, zobacz przejdź do następnej sekcji.

Uwaga: gdy już wybierzesz formaty kompresji tekstur aplikacji, upewnij się, że są one zadeklarowane w pliku manifestu za pomocą polecenia <supports-gl-texture> Użycie tej deklaracji umożliwia filtrowanie według usług zewnętrznych, takich jak Google Play, i pozwala aplikacja jest instalowana tylko na urządzeniach, które obsługują formaty wymagane przez aplikację. Więcej informacji: Deklaracje w pliku manifestu OpenGL.

Określanie rozszerzeń OpenGL

Implementacje standardu OpenGL różnią się w zależności od urządzenia z Androidem, jeśli chodzi o rozszerzenia interfejsu API OpenGL ES. które są obsługiwane. Te rozszerzenia obejmują kompresję tekstury, ale zwykle obejmują też inne do zestawu funkcji OpenGL.

Aby określić, które formaty kompresji tekstur i inne rozszerzenia OpenGL są obsługiwane w konkretne urządzenie:

  1. Uruchom poniższy kod na urządzeniach docelowych, aby określić stopień kompresji tekstur obsługiwane formaty:

    Kotlin

    var extensions = gl.glGetString(GL10.GL_EXTENSIONS)
    

    Java

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

    Ostrzeżenie: wyniki tego wywołania różnią się w zależności od modelu urządzenia. Ty należy uruchomić to wywołanie na kilku urządzeniach docelowych, aby określić typowe typy kompresji obsługiwane.

  2. Sprawdź wynik działania tej metody, aby określić, które rozszerzenia OpenGL są obsługiwane na urządzenia.

Pakiet rozszerzeń do Androida (AEP)

AEP zapewnia, że aplikacja obsługuje ustandaryzowany zestaw rozszerzeń OpenGL wymienionych powyżej i nie tylko zestawu podstawowego opisanego w specyfikacji OpenGL 3.1. Pakowanie tych rozszerzeń w jednym miejscu tworzy spójny zestaw funkcji na różnych urządzeniach, pozwalając jednocześnie programistom w pełni wykorzystać potencjał urządzeń mobilnych z GPU.

Poprawia również obsługę obrazów, buforów pamięci masowej cieniowania i liczników atomowych w cieniowanie fragmentów.

Aby aplikacja mogła korzystać z interfejsu AEP, jej plik manifestu musi zawierać deklarację, że jest ono wymagane. Dodatkowo musi go obsługiwać wersja platformy.

Wszystkie dodatkowe funkcje określone w narzędziu AEP są dostępne w podstawowej wersji OpenGL ES 3.2. specyfikacji. Jeśli aplikacja wymaga OpenGL ES 3.2, nie musisz wymagać AEP.

Zadeklaruj w pliku manifestu wymagania dotyczące AEP:

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

Aby sprawdzić, czy wersja platformy obsługuje AEP, użyj Metoda hasSystemFeature(String), przekazywanie danych FEATURE_OPENGLES_EXTENSION_PACK. Następujący fragment kodu: Oto przykład:

Kotlin

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

Java

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

Jeśli metoda zwraca wartość prawda, AEP jest obsługiwane.

Więcej informacji na temat programu AEP znajdziesz na jego stronie: Rejestr Khronos OpenGL ES.

Sprawdzam wersję OpenGL ES

Na urządzeniach z Androidem dostępnych jest kilka wersji OpenGL ES. Możesz określić minimalnej wersji interfejsu API wymaganej przez aplikację w pliku manifestu, ale możesz też jednocześnie korzystać z funkcji nowszych interfejsu API. Przykład: interfejs API OpenGL ES 3.0 jest zgodny wstecz z wersją 2.0, dlatego warto napisać aplikację w taki sposób, aby wykorzystywała funkcje OpenGL ES 3.0, ale wraca do interfejsu API 2.0, jeśli Interfejs API 3.0 jest niedostępny.

Przed użyciem funkcji OpenGL ES w wersji wyższej niż wymagana minimalna aplikacji manifestu, aplikacja powinna sprawdzić wersję interfejsu API dostępnego na urządzeniu. Możesz to zrobić na 2 sposoby:

  1. Spróbuj utworzyć kontekst OpenGL ES wyższego poziomu (EGLContext) oraz sprawdzić wynik.
  2. Utwórz kontekst OpenGL ES obsługiwanego minimum i sprawdź wartość wersji.

Poniższy przykładowy kod pokazuje, jak sprawdzić dostępną wersję OpenGL ES przez utworzenie EGLContext i sprawdzam wynik. Ten przykład pokazuje, jak sprawdzić Wersja 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;
  }
}

Jeśli metoda createContext() powyżej zwraca wartość null, kod powinien utworzyć OpenGL ES 2.0 i przełącz się na używanie tylko tego interfejsu API.

Poniższy przykładowy kod pokazuje, jak sprawdzić wersję OpenGL ES przez utworzenie minimalnej wartości najpierw obsługiwany kontekst, a potem sprawdź ciąg znaków wersji:

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.

Przy tej metodzie, jeśli urządzenie obsługuje wyższe wersje interfejsu API, musi zniszczyć minimalny kontekst OpenGL ES i stworzyć nowy dostępnej wersji interfejsu API.

Wybór wersji interfejsu API OpenGL

Zarówno OpenGL ES w wersji 2.0, jak i 3.0 zapewniają wysokie interfejsów graficznych wydajności do tworzenia gier 3D, wizualizacji oraz interfejsów użytkownika. Grafika programowanie dla OpenGL ES 2.0 i 3.0 jest w dużym stopniu podobne, gdzie wersja 3.0 reprezentuje nadzbiór interfejsu API 2.0 z dodatkowymi funkcjami. Programowanie dla interfejsów API OpenGL ES 1.0/1.1 i OpenGL ES 2.0 i 3.0 znacznie się różnią i nie są zalecane w przypadku nowych aplikacji. Przed rozpoczęciem programowania deweloperzy powinni dokładnie wziąć pod uwagę poniższe czynniki. tych interfejsów API:

  • Zgodność urządzeń – deweloperzy powinni wziąć pod uwagę typy urządzeń, Wersje Androida i wersje OpenGL ES dostępne dla klientów. Więcej informacji na temat konfiguracji zgodności z OpenGL na różnych urządzeniach, patrz wersje OpenGL urządzeń.
  • Obsługa tekstur – interfejs API OpenGL ES 3.0 zapewnia najlepszą obsługę tekstur. kompresji, ponieważ gwarantuje ona dostępność formatu kompresji ETC2, który obsługuje i przejrzystością. Implementacje interfejsu API 2.0 obejmują obsługę ETC1, ale ten format tekstury nie obsługuje przezroczystości. Aby wdrożyć przezroczystość przy użyciu skompresowanego pliku dla tekstur należy użyć dwóch tekstur ETC1 (rozdzielonych na kolor i alfa) lub podać zasoby w innych formatach kompresji obsługiwanych przez urządzenia, na które kierujesz reklamy. Aby dowiedzieć się więcej, Więcej informacji znajdziesz w sekcji Obsługa kompresji tekstur.

Zgodność i obsługa tekstur może wpływać na decyzji, należy wybrać wersję interfejsu API OpenGL na podstawie tego, co uważasz za najlepsze. użytkowników.