BLOCK · 4×4 pixels, fixed bitrateBLOK · 4×4 piksele, stały bitrateMIP · variance lost, roughness unchangedMIP · wariancja gubiona, roughness bez zmianBUDGET · MB per asset, not per shotBUDŻET · MB na asset, nie na ujęcie
Chapter 27 / Realtime lookdevRozdział 27 / Lookdev realtime

Texture and shader budget on the GPUBudżet tekstur i shaderów pod GPU

Chapter 12 asked how many bits a value needs. This chapter asks the harder version of the same question: how many bits it gets, once someone else has already spent them. Rozdział 12 pytał, ile bitów potrzebuje wartość. Ten rozdział zadaje trudniejszą wersję tego samego pytania: ile bitów dostanie, kiedy ktoś inny już je wydał.

TL;DR
Stage: Block compressionEtap: Kompresja blokowa

Two endpoints per sixteen pixelsDwa punkty końcowe na szesnaście pikseli

All the BC (block compression) formats share one idea: split the image into 4×4 blocks and store, per block, a small number of endpoint values plus a per-pixel index selecting a point interpolated between them. BC1 stores two RGB endpoints and two bits per pixel — four distinct colours for the whole block, at half a byte per pixel. The gradient inside a block is therefore quantised to those four steps, and the endpoints are chosen per block, which is why compression artefacts follow the 4×4 grid rather than the image content. Wszystkie formaty BC (block compression) dzielą jedną ideę: podziel obraz na bloki 4×4 i zapisz w każdym bloku niewielką liczbę wartości końcowych plus indeks per piksel wybierający punkt interpolowany między nimi. BC1 przechowuje dwa punkty końcowe RGB i dwa bity na piksel — cztery różne kolory na cały blok, przy pół bajta na piksel. Gradient wewnątrz bloku jest więc skwantowany do tych czterech kroków, a punkty końcowe dobierane są per blok — dlatego artefakty kompresji podążają za siatką 4×4, a nie za treścią obrazu.

M ≈ w · h · bpp · 4/3M — texture memory including the full mip chain; w, h — dimensions; bpp — bytes per pixel of the format (BC1 = 0,5; BC7 / BC3 = 1). The 4/3 is the mip chain's geometric series: 1 + 1/4 + 1/16 + … A 4096² BC1 texture ≈ 11 MB with mips; the same map as BC7 ≈ 22 MB.M — pamięć tekstury razem z pełnym łańcuchem mipów; w, h — wymiary; bpp — bajty na piksel formatu (BC1 = 0,5; BC7 / BC3 = 1). Współczynnik 4/3 to szereg geometryczny łańcucha mipów: 1 + 1/4 + 1/16 + … Tekstura 4096² w BC1 to ≈ 11 MB z mipami; ta sama mapa w BC7 to ≈ 22 MB.
FormatBytes/pxChannelsUse in lookdev
BC10,5RGB (+1-bit alpha)Albedo where quality allows; the cheapest and the most visibly blocky
BC31,0RGB + 8-bit alphaAlbedo with a real alpha; alpha is compressed separately and survives better than RGB
BC40,51 channelA single grey map — roughness, a mask, height. The best quality per bit for one channel
BC51,02 channelsTangent-space normals: store X and Y, reconstruct Z in the shader
BC6H1,0RGB, half-floatHDR — the HDRI environment of Chapter 21, cubemaps, captured lighting
BC71,0RGBAHigh-quality albedo and packed masks; multiple block modes, far fewer artefacts than BC1
Uncompressed 8-bit RGBA is 4 bytes per pixel — every row above is a four- to eight-fold saving, paid for in a specific artefact.
FormatBajty/pxKanałyZastosowanie w lookdevie
BC10,5RGB (+alfa 1-bit)Albedo tam, gdzie jakość pozwala; najtańszy i najbardziej widocznie blokowy
BC31,0RGB + alfa 8-bitAlbedo z prawdziwą alfą; alfa kompresowana osobno i znosi to lepiej niż RGB
BC40,51 kanałPojedyncza mapa szarości — roughness, maska, wysokość. Najlepsza jakość na bit dla jednego kanału
BC51,02 kanałyNormalne w przestrzeni stycznej: zapisz X i Y, odtwórz Z w shaderze
BC6H1,0RGB, half-floatHDR — środowisko HDRI z Rozdziału 21, cubemapy, przechwycone oświetlenie
BC71,0RGBAAlbedo wysokiej jakości i spakowane maski; wiele trybów bloku, dużo mniej artefaktów niż BC1
Nieskompresowane 8-bitowe RGBA to 4 bajty na piksel — każdy wiersz powyżej to oszczędność cztero- do ośmiokrotnej, opłacona konkretnym artefaktem.

Two consequences matter for authoring. A normal map must never go through an RGB format that compresses the channels jointly — that is what BC5 exists for, and a normal map in BC1 produces the characteristic blotchy shading that no amount of roughness tuning will fix. And unrelated data packed into the RGB of a jointly-compressed format bleeds between channels: if roughness and metallic share BC1's endpoints, a metal edge will contaminate roughness. Pack into BC7, or keep single-channel maps in BC4. Dwie konsekwencje mają znaczenie przy autorowaniu. Mapa normalnych nie może przechodzić przez format RGB kompresujący kanały wspólnie — po to jest BC5, a normalna w BC1 daje charakterystyczne plamiaste cieniowanie, którego nie naprawi żadne strojenie roughness. I dane niezwiązane ze sobą, spakowane w RGB formatu kompresowanego wspólnie, przeciekają między kanałami: jeśli roughness i metallic dzielą punkty końcowe BC1, krawędź metalu zanieczyści roughness. Pakuj do BC7 albo trzymaj mapy jednokanałowe w BC4.

BC1.block4×4 pixels, two endpoints, four available values4×4 piksele, dwa punkty końcowe, cztery dostępne wartości
source gradient (16 distinct values)gradient źródłowy (16 różnych wartości) after BC1 (4 values, per block)po BC1 (4 wartości, per blok) endpoint 0 — stored exactlypunkt końcowy 0 — zapisany dokładnie two interpolated stepsdwa kroki interpolowane endpoint 1 — stored exactlypunkt końcowy 1 — zapisany dokładnie 2 bits per pixel choose one of the four2 bity na piksel wybierają jedną z czterech → a smooth gradient bands along block edges→ gładki gradient pasmuje na krawędziach bloków Same mechanism as Chapter 12's banding — but quantised per block, not per image.Ten sam mechanizm co pasmowanie z Rozdziału 12 — tylko kwantyzowany per blok, nie per obraz.
A block whose sixteen pixels span a wide value range gets four steps to describe them all. Detail that crosses a block boundary — a mask edge, a scratch, a seam — is where the artefact becomes visible.Blok, którego szesnaście pikseli obejmuje szeroki zakres wartości, dostaje cztery kroki na opisanie ich wszystkich. Detal przechodzący przez granicę bloku — krawędź maski, rysa, szew — to miejsce, w którym artefakt staje się widoczny.
Stage: MipsEtap: Mipy

Why a rough surface sparkles at distanceDlaczego szorstka powierzchnia iskrzy z odległości

A mip chain is a set of pre-filtered downsamples the GPU picks between by screen-space texel density. Two things go wrong in it, and both are lookdev problems rather than technical-artist trivia. Łańcuch mipów to zestaw wstępnie przefiltrowanych pomniejszeń, między którymi GPU wybiera na podstawie ekranowej gęstości tekseli. Dwie rzeczy idą w nim źle i obie są problemami lookdevu, a nie ciekawostkami dla technicznego artysty.

The first is the Chapter 3 mistake in a new place: mips must be filtered in linear space. Averaging sRGB-encoded values directly darkens the result, so a texture whose mips were generated without decoding first will drift in brightness with distance — visible as an asset that gets subtly darker as the camera pulls back. Pierwsza to błąd z Rozdziału 3 w nowym miejscu: mipy muszą być filtrowane w przestrzeni liniowej. Uśrednianie wartości zakodowanych w sRGB wprost przyciemnia wynik, więc tekstura, której mipy wygenerowano bez wcześniejszego dekodowania, będzie dryfować w jasności wraz z odległością — widać to jako asset subtelnie ciemniejący, gdy kamera się oddala.

The second is deeper and comes straight from Chapter 13's microfacet model. Roughness is a statistical description of normal variation below the pixel; a normal map is the same variation stored explicitly. When a normal map is downsampled, opposing normals average out and the resulting vector shortens — the variation is lost from the normal map, but it was never transferred into the roughness map, which was mipped independently. The surface therefore becomes smoother than it should be at distance, and a smoother surface concentrates its specular into a smaller, brighter lobe: the sparkle and shimmer you see on distant metal, wet asphalt or fine fabric. Druga jest głębsza i wynika wprost z modelu mikrofasetkowego z Rozdziału 13. Roughness to statystyczny opis zmienności normalnych poniżej piksela; mapa normalnych to ta sama zmienność zapisana wprost. Kiedy mapa normalnych jest pomniejszana, przeciwstawne normalne uśredniają się, a wynikowy wektor skraca się — zmienność ginie z mapy normalnych, ale nigdy nie została przeniesiona do mapy roughness, mipowanej niezależnie. Powierzchnia staje się więc z odległości gładsza, niż powinna, a gładsza powierzchnia skupia specular w mniejszym, jaśniejszym lobie: to iskrzenie i migotanie, które widzisz na odległym metalu, mokrym asfalcie czy drobnej tkaninie.

The fix is to convert the lost normal length into extra roughness at each mip level — the classic Toksvig-style variance-to-roughness mapping. In Unreal it is a texture setting: point a roughness texture at its normal map as a composite texture, and each roughness mip is generated with that correction applied. Turning it on for every roughness map that has a matching normal map is close to free and removes a whole class of "it shimmers in motion" notes. Lekarstwem jest zamiana utraconej długości normalnej na dodatkowy roughness na każdym poziomie mipa — klasyczne odwzorowanie wariancji na roughness w stylu Toksviga. W Unrealu to ustawienie tekstury: wskaż teksturze roughness jej mapę normalnych jako composite texture, a każdy mip roughness powstanie z nałożoną korektą. Włączenie tego dla każdej mapy roughness mającej odpowiadającą mapę normalnych jest niemal darmowe i usuwa całą klasę uwag „migocze w ruchu”.

↓ raytracing-book, Appendix G — mipmapping and texture filtering: why the level is chosen the way it is↓ raytracing-book, Dodatek G — mipmapping i filtrowanie tekstur: dlaczego poziom wybierany jest właśnie tak
Stage: PackingEtap: Pakowanie

Three maps in one textureTrzy mapy w jednej teksturze

Chapter 25 named the wall: a material has a small fixed number of texture samplers, and a graph that samples one texture per channel hits it before the material is finished. Channel packing is the answer — most commonly ORM: ambient occlusion in R, roughness in G, metallic in B, one sample instead of three. Conventions differ per project and per engine, which is exactly why the convention must be written down somewhere a texture artist reads, not inferred from an existing file. Rozdział 25 nazwał ścianę: materiał ma małą, stałą liczbę samplerów tekstur, a graf próbkujący jedną teksturę na kanał uderza w nią, zanim materiał będzie skończony. Channel packing to odpowiedź — najczęściej ORM: ambient occlusion w R, roughness w G, metallic w B, jedno próbkowanie zamiast trzech. Konwencje różnią się między projektami i silnikami i właśnie dlatego konwencję trzeba spisać tam, gdzie czyta ją artysta teksturujący, a nie wywnioskować z istniejącego pliku.

Three rules keep packing from causing more problems than it solves. A packed texture is data, never colour — sRGB stays off, per Chapter 11. Channels with hard edges (masks) and channels with smooth gradients (AO) fight each other inside a jointly-compressed block, so packed maps want BC7 rather than BC1. And the channel that carries the most perceptually important signal — usually roughness, because Chapter 13 showed how strongly a small roughness change moves a highlight — should get the format's best-preserved channel, which for BC3 is alpha. Trzy zasady sprawiają, że pakowanie nie tworzy więcej problemów, niż rozwiązuje. Tekstura spakowana to dane, nigdy kolor — sRGB zostaje wyłączony, zgodnie z Rozdziałem 11. Kanały z twardymi krawędziami (maski) i kanały z gładkimi gradientami (AO) walczą ze sobą wewnątrz wspólnie kompresowanego bloku, więc mapy spakowane wolą BC7 niż BC1. A kanał niosący percepcyjnie najważniejszy sygnał — zwykle roughness, bo Rozdział 13 pokazał, jak mocno mała zmiana roughness rusza rozbłyskiem — powinien dostać najlepiej zachowany kanał formatu, którym w BC3 jest alfa.

Stage: The budgetEtap: Budżet

Texel density, streaming, and what "4K textures" costsGęstość tekseli, streaming i ile kosztują „tekstury 4K”

In VFX, UDIM tiles let an asset carry as much texture as it needs, and Appendix T's budget is about disk and load time. In a game the same asset shares a fixed pool of video memory with everything else on screen, so texture resolution is expressed as texel density — texels per centimetre of surface — and agreed project-wide, so that a wall and a prop next to it resolve to the same detail rather than one looking soft beside the other. W VFX kafle UDIM pozwalają assetowi nieść tyle tekstur, ile potrzebuje, a budżet z Dodatku T dotyczy dysku i czasu wczytywania. W grze ten sam asset dzieli stałą pulę pamięci wideo ze wszystkim innym na ekranie, więc rozdzielczość tekstur wyraża się jako gęstość tekseli — teksele na centymetr powierzchni — i uzgadnia w skali projektu, żeby ściana i stojący obok niej rekwizyt rozdzielały się do tego samego detalu, zamiast żeby jedno wyglądało miękko obok drugiego.

Streaming and virtual texturing soften the limit without removing it: the engine keeps only the mip levels currently needed resident, and virtual textures page in tiles of a much larger texture on demand. Both change when memory is spent, not how much a fully-resolved close-up costs — and both introduce a visible failure mode, the low-resolution mip that hasn't streamed in yet, which is worth checking deliberately by teleporting the camera to an asset rather than walking up to it. Streaming i wirtualne tekstury łagodzą limit, nie usuwając go: silnik trzyma w pamięci tylko aktualnie potrzebne poziomy mipów, a wirtualne tekstury doczytują kafle znacznie większej tekstury na żądanie. Oba zmieniają to, kiedy pamięć jest wydawana, a nie ile kosztuje w pełni rozdzielone zbliżenie — i oba wprowadzają widoczny tryb awarii, czyli niski mip, który jeszcze się nie doczytał; warto sprawdzać go celowo, teleportując kamerę do assetu zamiast do niego podchodzić.

On the shader side the equivalent budget is instructions and samples per pixel. The costs that surprise artists are rarely arithmetic: they are extra texture samples, dependent samples (a texture whose UVs come from another texture read), and shader permutations from static switches nobody uses. A master material with every feature switched on for every asset is the shader-side twin of the 4K-texture-for-a-doorknob problem. Po stronie shadera odpowiednikiem budżetu są instrukcje i próbkowania na piksel. Koszty, które zaskakują artystów, rzadko są arytmetyką: to dodatkowe próbkowania tekstur, próbkowania zależne (tekstura, której UV pochodzą z odczytu innej tekstury) i permutacje shadera z przełączników statycznych, których nikt nie używa. Master material z wszystkimi funkcjami włączonymi dla każdego assetu to shaderowy bliźniak problemu tekstury 4K na klamkę.

↓ raytracing-book, Appendix J — the same question offline: what a shading network’s complexity costs a renderer↓ raytracing-book, Dodatek J — to samo pytanie offline: ile złożoność sieci shaderów kosztuje renderer
From practiceZ praktyki

Compression artefacts are invisible on the texture and obvious on the asset — always judge them in the engine, on the model, at the distance the asset is actually seen, never in the texture viewer at 100 %. The two maps that most often need to escape the cheapest format are a subtle albedo gradient (skin, painted metal) and any mask with a hard edge. Everything else usually survives BC1 better than an artist's instinct expects. Artefakty kompresji są niewidoczne na teksturze i oczywiste na asecie — zawsze oceniaj je w silniku, na modelu, z odległości, z jakiej asset jest naprawdę oglądany, nigdy w podglądzie tekstury przy 100 %. Dwie mapy, które najczęściej muszą uciec z najtańszego formatu, to subtelny gradient albedo (skóra, malowany metal) i każda maska z twardą krawędzią. Cała reszta zwykle znosi BC1 lepiej, niż podpowiada instynkt artysty.

GlossarySłowniczek
Block compression (BC1–BC7)Kompresja blokowa (BC1–BC7)
GPU texture formats storing endpoints plus per-pixel indices for each 4×4 block, decoded in hardware at sample time.Formaty tekstur GPU zapisujące punkty końcowe plus indeksy per piksel dla każdego bloku 4×4, dekodowane sprzętowo przy próbkowaniu.
Mip chainŁańcuch mipów
The pre-filtered downsample pyramid; adds about one third to a texture's memory and must be filtered in linear space.Piramida wstępnie przefiltrowanych pomniejszeń; dokłada około jednej trzeciej do pamięci tekstury i musi być filtrowana liniowo.
Variance-to-roughness (Toksvig)Wariancja na roughness (Toksvig)
Pushing the normal variation lost during mip generation into the roughness map, removing distance sparkle.Przeniesienie zmienności normalnych utraconej przy generowaniu mipów do mapy roughness, co usuwa iskrzenie z odległości.
Channel packing / ORMChannel packing / ORM
Storing several single-channel maps in one texture's channels — commonly occlusion, roughness, metallic — to save samplers.Zapis kilku map jednokanałowych w kanałach jednej tekstury — zwykle occlusion, roughness, metallic — dla oszczędności samplerów.
Texel densityGęstość tekseli
Texels per unit of surface — the project-wide agreement that keeps neighbouring assets resolving to the same detail.Teksele na jednostkę powierzchni — ustalenie w skali projektu, dzięki któremu sąsiadujące assety rozdzielają się do tego samego detalu.
Virtual texturing / streamingWirtualne teksturowanie / streaming
Paging in only the tiles or mip levels currently visible, moving when memory is spent rather than removing the limit.Doczytywanie tylko aktualnie widocznych kafli albo poziomów mipów — przesuwa moment wydania pamięci, nie znosi limitu.