Panduan pemula

Apa yang terjadi pada tekstur di dalam GPU

PNG berukuran 300 KB bisa diam-diam memakan 5 MB memori grafis. Panduan ini menjelaskan alasannya, bagaimana GPU memperkecil tekstur dengan kompresi blok, dan cara memilih format. Setiap konsep dilengkapi sesuatu yang bisa langsung Anda coba.

Sekitar 10 menit5 demo interaktif
Mulai membaca

Bab 1

Ukuran file bukan ukuran memori

PNG dan JPEG dibuat untuk menyimpan dan mengirim gambar. Sebelum GPU dapat menggambar tekstur, gambar dibongkar menjadi texel mentah, biasanya 4 byte per texel.

GPU mengambil sampel texel tersebut jutaan kali per frame, jadi texel harus selalu siap dibaca. Karena itu penggunaan memori hanya bergantung pada resolusi dan format piksel, bukan seberapa baik file dikompresi. Mipmap, salinan yang diperkecil untuk permukaan jauh, menambah sekitar sepertiga.

Coba sendiriKalkulator memori grafisUbah resolusi dan jumlah tekstur untuk melihat berapa memori GPU yang dibutuhkan tekstur yang sama di setiap format.
Resolusi
  • RGBA8
    32 bit per texel
    213 MiB
    Acuan
    21,3 MiB per tekstur
  • BC7 · ASTC 4×4
    8 bit per texel
    53,3 MiB
    4× lebih kecil
    5,3 MiB per tekstur
  • BC1 · ETC2 RGB
    4 bit per texel
    26,7 MiB
    8× lebih kecil
    2,7 MiB per tekstur
  • ASTC 6×6
    3,56 bit per texel
    23,8 MiB
    9× lebih kecil
    2,4 MiB per tekstur
  • ASTC 8×8
    2 bit per texel
    13,3 MiB
    16× lebih kecil
    1,3 MiB per tekstur
  • ASTC 12×12
    0,89 bit per texel
    6 MiB
    35,7× lebih kecil
    612 KiB per tekstur

Format blok dibulatkan ke atas menjadi blok utuh di setiap level mip, jadi angkanya sama dengan yang dialokasikan GPU.

Bab 2

Mengapa GPU tidak bisa menyimpan PNG

Saat shader mengambil sampel tekstur, ia bisa meminta texel mana pun dalam urutan apa pun. Perangkat keras harus menemukannya seketika.

PNG dan JPEG memakai pengodean dengan panjang variabel: untuk mencapai piksel di tengah, semua data sebelumnya harus didekode lebih dulu. Format GPU memakai laju tetap: setiap blok 4×4 memakai jumlah byte yang persis sama, sehingga alamat texel mana pun cukup dihitung dengan satu perkalian. Tekstur tetap terkompresi di memori, dan unit tekstur mendekode blok saat membacanya.

Coba sendiriTemukan texelKlik texel mana pun pada tekstur 32×32 ini. Format blok dapat menghitung lokasi penyimpanannya; PNG tidak bisa.

Gunakan tombol panah untuk memindahkan pilihan.

Texel terpilih
x 13, y 18
Bloknya
kolom 3, baris 4
Alamat di BC1
(4 × 8 + 3) × 8 byte = byte ke-280

64 blok sebagaimana tersusun di memori

0511

Texel yang sama di PNG

Harus mendekompresi baris 0 sampai 18 dulu (19 dari 32)

Bab 3

Di dalam blok 4×4

BC1, format tertua yang banyak dipakai, menunjukkan idenya paling jelas. Format ini menyimpan blok berisi 16 texel hanya dalam 8 byte.

Encoder memilih dua warna titik ujung. Decoder mencampurnya menjadi empat warna pada satu garis lurus, dan setiap texel menyimpan angka 2 bit yang menunjuk warna terdekat. Blok dengan perubahan warna yang halus tetap terjaga; blok yang mencampur beberapa warna tak berkaitan tidak.

Coba sendiriPenjelajah blok BC1Pilih blok 4×4 pada tekstur contoh dan lihat bagaimana tepatnya BC1 menyimpannya.
Blok 12, 4

Bab 4

Banyak format, kompromi berbeda

Format yang lebih baru memakai bitnya lebih cerdas daripada BC1: lebih banyak titik ujung, beberapa garis warna dalam satu blok, alpha yang lebih baik, atau pilihan ukuran blok.

BC7 dan ASTC 4×4 memakai 8 bit per texel dan terlihat sangat mirip dengan aslinya. ASTC menukar kualitas dengan ukuran lewat ukuran bloknya: satu blok selalu 128 bit, sehingga blok 12×12 memakai kurang dari satu bit per texel. Basis Universal menempuh jalan lain: ia mengirim satu file ringkas lalu mentranskodenya di perangkat ke format yang didukung GPU tersebut.

Format tekstur GPU yang umum
FormatBit per texelAlphaPlatform umumCocok untuk
BC141 bitDesktop, konsolWarna buram saat memori terbatas
BC38YaDesktop, konsolWarna dengan alpha halus pada konten lama
BC44Kanal dataDesktop, konsolSatu kanal: mask, kekasaran, tinggi
BC58Kanal dataDesktop, konsolNormal map (X dan Y)
BC6H8TidakDesktop, konsolWarna HDR seperti skybox dan lightmap
BC78YaDesktop, konsolWarna berkualitas tinggi, dengan atau tanpa alpha
ETC14TidakHampir semua AndroidWarna buram di perangkat yang sangat lama
ETC24–8YaAndroid, iOSCadangan mobile dengan dukungan luas
ASTC0.89–8YaAndroid dan iOS terbaru, Apple SiliconKualitas yang dapat diatur di mobile
PVRTC2–4YaiPhone dan iPad lamaHanya perangkat Apple lama
Basis ETC1STergantung targetYaGPU apa pun, melalui KTX2Unduhan kecil yang berjalan di GPU apa pun
Basis UASTCTergantung targetYaGPU apa pun, melalui KTX2Kualitas tinggi yang berjalan di GPU apa pun
Coba sendiriJalankan encoder sungguhanKompresi sampel 512×512 dengan encoder WebAssembly yang sama dengan alat kami, lalu bandingkan area yang diperbesar.
Berjalan di browser Anda. Tidak ada yang diunggah.
Area yang diperbesar
Asli
RGBA8
1 MiB di memori GPU
BC1
BC1
4 bit per texel
128 KiB di memori GPU
BC7
BC7
8 bit per texel
256 KiB di memori GPU
ASTC 6×6
ASTC 6×6
3,56 bit per texel
116 KiB di memori GPU
ASTC 12×12
ASTC 12×12
0,89 bit per texel
29 KiB di memori GPU

Tekan “Jalankan encoder” untuk mengompresi sampel. Saat pertama kali, encoder akan diunduh.

Bab 5

Memilih format

Dua pertanyaan cepat mempersempit pilihan: GPU mana yang harus memuat tekstur, dan data apa yang ada di dalamnya?

Tekstur warna, normal map, dan mask satu kanal bereaksi berbeda terhadap kompresi, dan platform desktop, mobile, serta web mendukung keluarga format yang berbeda. Pilih kasus Anda untuk mendapat titik awal yang masuk akal, lalu periksa hasilnya dengan tekstur Anda sendiri.

Coba sendiriPemilih formatPilih tempat tekstur dijalankan dan isinya.
Di mana tekstur akan berjalan?
Apa isi teksturnya?

Mulai dengan

ASTC 6×6

Pertimbangkan juga: ASTC 4×4 · ETC2 RGB

ASTC berjalan di GPU Android dan iOS terbaru. 6×6 adalah titik seimbang yang baik; gunakan 4×4 untuk aset utama dan ETC2 untuk perangkat lama.

Buka encoder ASTC

Bab 6

Tips praktis

Beberapa kebiasaan mencegah sebagian besar masalah kompresi tekstur.

  1. 01

    Tandai warna sebagai sRGB dan data sebagai linear

    Tekstur albedo dan UI adalah sRGB. Normal map, kekasaran, dan peta data lainnya harus tetap linear, atau pencahayaan akan salah.

  2. 02

    Beri normal map format tersendiri

    Gunakan format dua kanal seperti BC5 atau EAC RG11 dan bangun ulang Z di shader. Format warna memboroskan bit dan menimbulkan tonjolan yang terlihat.

  3. 03

    Buat mipmap

    Mipmap menambah sekitar 33% memori, tetapi mencegah permukaan jauh berkedip dan mempercepat pengambilan sampel.

  4. 04

    Gunakan dimensi yang ramah blok

    Sebagian besar format bekerja dalam blok 4×4, jadi ukuran yang habis dibagi 4 tidak memerlukan padding. Format lama seperti PVRTC juga membutuhkan ukuran persegi berpangkat dua.

  5. 05

    Periksa konten nyata di perangkat nyata

    Bandingkan hasil dekode dengan aslinya pada perbesaran penuh, dan pastikan GPU target Anda mendukung format tersebut.

Pertanyaan yang sering diajukan

Apakah kompresi tekstur GPU bersifat lossless?

Tidak. BC, ETC, ASTC, dan PVRTC adalah format lossy dengan ukuran tetap per blok. Seberapa besar penurunan kualitasnya bergantung pada format, ukuran blok, dan gambarnya.

Mengapa tidak langsung memakai tekstur PNG atau JPEG?

Unduhannya lebih cepat, tetapi GPU tidak dapat mengambil sampel darinya, sehingga file didekode menjadi texel mentah dan memakai memori penuh. Format GPU tetap kecil di memori juga.

Format tekstur mana yang terbaik?

BC7 adalah pilihan default yang kuat di desktop, ASTC di perangkat mobile terbaru, dan KTX2 dengan Basis Universal bila satu file harus berjalan di banyak GPU, misalnya di web.

Apa arti bit per texel?

Itu adalah biaya penyimpanan rata-rata satu texel. RGBA8 mentah memakai 32 bit, BC1 memakai 4, BC7 memakai 8, dan ASTC berkisar dari 8 hingga sekitar 0,89 tergantung ukuran bloknya.

Coba dengan tekstur Anda sendiri

Semua encoder berjalan secara lokal di browser Anda. Unggah PNG atau JPEG, pilih format, lalu bandingkan hasilnya.