Przewodnik dla początkujących

Co dzieje się z teksturą wewnątrz GPU

PNG o rozmiarze 300 KB może po cichu zająć 5 MB pamięci graficznej. Ten przewodnik pokazuje, dlaczego tak się dzieje, jak GPU zmniejszają tekstury dzięki kompresji blokowej i jak wybrać format. Każdemu pomysłowi towarzyszy coś, co możesz wypróbować.

Około 10 minut5 interaktywnych dem
Zacznij czytać

Rozdział 1

Rozmiar pliku to nie rozmiar w pamięci

PNG i JPEG służą do przechowywania i przesyłania obrazów. Zanim GPU narysuje teksturę, obraz zostaje rozpakowany do surowych tekseli, zwykle po 4 bajty każdy.

GPU próbkuje te teksele miliony razy na klatkę, więc muszą być gotowe do odczytu. Dlatego zużycie pamięci zależy tylko od rozdzielczości i formatu pikseli, a nie od tego, jak dobrze skompresowano plik. Mipmapy, czyli pomniejszone kopie dla odległych powierzchni, dokładają około jednej trzeciej.

WypróbujKalkulator pamięci graficznejZmień rozdzielczość i liczbę tekstur, aby zobaczyć, ile pamięci GPU potrzebują te same tekstury w każdym formacie.
Rozdzielczość
  • RGBA8
    32 bitów na teksel
    213 MiB
    Punkt odniesienia
    21,3 MiB na teksturę
  • BC7 · ASTC 4×4
    8 bitów na teksel
    53,3 MiB
    4× mniej
    5,3 MiB na teksturę
  • BC1 · ETC2 RGB
    4 bitów na teksel
    26,7 MiB
    8× mniej
    2,7 MiB na teksturę
  • ASTC 6×6
    3,56 bitów na teksel
    23,8 MiB
    9× mniej
    2,4 MiB na teksturę
  • ASTC 8×8
    2 bitów na teksel
    13,3 MiB
    16× mniej
    1,3 MiB na teksturę
  • ASTC 12×12
    0,89 bitów na teksel
    6 MiB
    35,7× mniej
    612 KiB na teksturę

Formaty blokowe są zaokrąglane w górę do pełnych bloków na każdym poziomie mip, więc liczby odpowiadają temu, co faktycznie przydziela GPU.

Rozdział 2

Dlaczego GPU nie może trzymać PNG

Gdy shader próbkuje teksturę, może zażądać dowolnego teksela w dowolnej kolejności. Sprzęt musi go znaleźć natychmiast.

PNG i JPEG używają kodowania o zmiennej długości: aby dotrzeć do piksela w środku, trzeba najpierw zdekodować wszystko, co jest przed nim. Formaty GPU mają stałą przepływność: każdy blok 4×4 zajmuje dokładnie tyle samo bajtów, więc adres dowolnego teksela to proste mnożenie. Tekstura pozostaje skompresowana w pamięci, a jednostka teksturująca dekoduje bloki w trakcie odczytu.

WypróbujZnajdź tekselKliknij dowolny teksel tej tekstury 32×32. Format blokowy potrafi obliczyć, gdzie jest zapisany; PNG nie.

Użyj strzałek, aby przesunąć zaznaczenie.

Wybrany teksel
x 13, y 18
Jego blok
kolumna 3, wiersz 4
Adres w BC1
(4 × 8 + 3) × 8 bajtów = bajt 280

64 bloki w kolejności w pamięci

0511

Ten sam teksel w PNG

Najpierw trzeba rozpakować wiersze od 0 do 18 (19 z 32)

Rozdział 3

Wnętrze bloku 4×4

BC1, najstarszy powszechnie używany format, najlepiej pokazuje tę ideę. Zapisuje blok 16 tekseli w zaledwie 8 bajtach.

Koder wybiera dwa kolory końcowe. Dekoder miesza je w cztery kolory leżące na prostej, a każdy teksel przechowuje 2-bitowy numer wskazujący najbliższy z nich. Bloki z łagodnymi zmianami koloru zachowują się dobrze; bloki mieszające kilka niezwiązanych kolorów – nie.

WypróbujEksplorator bloków BC1Wybierz blok 4×4 w przykładowej teksturze i zobacz, jak dokładnie zapisuje go BC1.
Blok 12, 4

Rozdział 4

Wiele formatów, różne kompromisy

Nowsze formaty wykorzystują bity sprytniej niż BC1: więcej punktów końcowych, kilka linii kolorów w bloku, lepsza alfa albo wybór rozmiaru bloku.

BC7 i ASTC 4×4 używają 8 bitów na teksel i wyglądają bardzo podobnie do oryginału. ASTC wymienia jakość na rozmiar przez rozmiar bloku: blok ma zawsze 128 bitów, więc blok 12×12 kosztuje mniej niż jeden bit na teksel. Basis Universal idzie inną drogą: dostarcza jeden kompaktowy plik i transkoduje go na urządzeniu do formatu obsługiwanego przez dany GPU.

Popularne formaty tekstur GPU
FormatBity na tekselAlfaTypowe platformyNajlepszy do
BC141 bitDesktop, konsoleNieprzezroczysty kolor przy małej ilości pamięci
BC38TakDesktop, konsoleKolor z łagodną alfą w starszych materiałach
BC44Kanały danychDesktop, konsoleJeden kanał: maski, chropowatość, wysokość
BC58Kanały danychDesktop, konsoleMapy normalnych (X i Y)
BC6H8NieDesktop, konsoleKolor HDR, np. skyboxy i lightmapy
BC78TakDesktop, konsoleKolor wysokiej jakości, z alfą lub bez
ETC14NiePrawie każdy AndroidNieprzezroczysty kolor na bardzo starych urządzeniach
ETC24–8TakAndroid, iOSSzeroko obsługiwany zapasowy format mobilny
ASTC0.89–8TakNowsze Androidy i iOS, Apple SiliconRegulowana jakość na urządzeniach mobilnych
PVRTC2–4TakStarsze iPhone’y i iPadyTylko starsze urządzenia Apple
Basis ETC1SZależy od formatu docelowegoTakDowolny GPU, przez KTX2Małe pobieranie, działa na każdym GPU
Basis UASTCZależy od formatu docelowegoTakDowolny GPU, przez KTX2Wysoka jakość, działa na każdym GPU
WypróbujUruchom prawdziwe koderySkompresuj próbkę 512×512 tymi samymi koderami WebAssembly, których używają nasze narzędzia, i porównaj powiększony fragment.
Działa w przeglądarce. Nic nie jest wysyłane.
Powiększany obszar
Oryginał
RGBA8
1 MiB w pamięci GPU
BC1
BC1
4 bitów na teksel
128 KiB w pamięci GPU
BC7
BC7
8 bitów na teksel
256 KiB w pamięci GPU
ASTC 6×6
ASTC 6×6
3,56 bitów na teksel
116 KiB w pamięci GPU
ASTC 12×12
ASTC 12×12
0,89 bitów na teksel
29 KiB w pamięci GPU

Kliknij „Uruchom kodery”, aby skompresować próbkę. Przy pierwszym uruchomieniu kodery zostaną pobrane.

Rozdział 5

Jak wybrać format

Dwa pytania szybko zawężają wybór: które GPU muszą wczytać teksturę i jakie dane ona zawiera?

Tekstury kolorów, mapy normalnych i jednokanałowe maski różnie reagują na kompresję, a platformy desktopowe, mobilne i webowe obsługują różne rodziny formatów. Wybierz swój przypadek, aby dostać rozsądny punkt wyjścia, a potem sprawdź wynik na własnych teksturach.

WypróbujWybór formatuWybierz, gdzie działa tekstura i co zawiera.
Gdzie będzie działać?
Co zawiera tekstura?

Zacznij od

ASTC 6×6

Rozważ też: ASTC 4×4 · ETC2 RGB

ASTC działa na nowszych GPU z Androidem i iOS. 6×6 to dobry kompromis; użyj 4×4 dla kluczowych zasobów i ETC2 dla starszych urządzeń.

Otwórz koder ASTC

Rozdział 6

Praktyczne wskazówki

Kilka nawyków zapobiega większości problemów z kompresją tekstur.

  1. 01

    Oznaczaj kolor jako sRGB, a dane jako liniowe

    Tekstury albedo i UI są w sRGB. Mapy normalnych, chropowatości i inne dane muszą pozostać liniowe, inaczej oświetlenie będzie błędne.

  2. 02

    Daj mapom normalnych osobny format

    Używaj formatów dwukanałowych, takich jak BC5 lub EAC RG11, i odtwarzaj Z w shaderze. Formaty kolorów marnują bity i dodają widoczne nierówności.

  3. 03

    Generuj mipmapy

    Zwiększają zużycie pamięci o około 33%, ale zapobiegają migotaniu odległych powierzchni i przyspieszają próbkowanie.

  4. 04

    Dobieraj wymiary pod bloki

    Większość formatów działa na blokach 4×4, więc rozmiary podzielne przez 4 nie wymagają dopełniania. Starsze formaty, takie jak PVRTC, wymagają też kwadratowych rozmiarów będących potęgą dwójki.

  5. 05

    Sprawdzaj prawdziwe materiały na prawdziwych urządzeniach

    Porównaj zdekodowany wynik z oryginałem w pełnym powiększeniu i upewnij się, że docelowe GPU obsługują dany format.

Najczęstsze pytania

Czy kompresja tekstur GPU jest bezstratna?

Nie. BC, ETC, ASTC i PVRTC to formaty stratne ze stałym rozmiarem bloku. Ile jakości się traci, zależy od formatu, rozmiaru bloku i obrazu.

Dlaczego nie używać bezpośrednio tekstur PNG lub JPEG?

Szybciej się pobierają, ale GPU nie potrafi ich próbkować, więc są dekodowane do surowych tekseli i zajmują pełną pamięć. Formaty GPU pozostają małe także w pamięci.

Który format tekstur jest najlepszy?

BC7 to dobry domyślny wybór na desktopie, ASTC na nowszych urządzeniach mobilnych, a KTX2 z Basis Universal, gdy jeden plik musi działać na wielu GPU, np. w sieci.

Co oznacza liczba bitów na teksel?

To średni koszt zapisu jednego teksela. Surowe RGBA8 używa 32 bitów, BC1 4, BC7 8, a ASTC od 8 do około 0,89 w zależności od rozmiaru bloku.

Wypróbuj na własnych teksturach

Wszystkie kodery działają lokalnie w przeglądarce. Prześlij PNG lub JPEG, wybierz format i porównaj wynik.