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ł.
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.
| Format | Bytes/px | Channels | Use in lookdev |
|---|---|---|---|
| BC1 | 0,5 | RGB (+1-bit alpha) | Albedo where quality allows; the cheapest and the most visibly blocky |
| BC3 | 1,0 | RGB + 8-bit alpha | Albedo with a real alpha; alpha is compressed separately and survives better than RGB |
| BC4 | 0,5 | 1 channel | A single grey map — roughness, a mask, height. The best quality per bit for one channel |
| BC5 | 1,0 | 2 channels | Tangent-space normals: store X and Y, reconstruct Z in the shader |
| BC6H | 1,0 | RGB, half-float | HDR — the HDRI environment of Chapter 21, cubemaps, captured lighting |
| BC7 | 1,0 | RGBA | High-quality albedo and packed masks; multiple block modes, far fewer artefacts than BC1 |
| Format | Bajty/px | Kanały | Zastosowanie w lookdevie |
|---|---|---|---|
| BC1 | 0,5 | RGB (+alfa 1-bit) | Albedo tam, gdzie jakość pozwala; najtańszy i najbardziej widocznie blokowy |
| BC3 | 1,0 | RGB + alfa 8-bit | Albedo z prawdziwą alfą; alfa kompresowana osobno i znosi to lepiej niż RGB |
| BC4 | 0,5 | 1 kanał | Pojedyncza mapa szarości — roughness, maska, wysokość. Najlepsza jakość na bit dla jednego kanału |
| BC5 | 1,0 | 2 kanały | Normalne w przestrzeni stycznej: zapisz X i Y, odtwórz Z w shaderze |
| BC6H | 1,0 | RGB, half-float | HDR — środowisko HDRI z Rozdziału 21, cubemapy, przechwycone oświetlenie |
| BC7 | 1,0 | RGBA | Albedo wysokiej jakości i spakowane maski; wiele trybów bloku, dużo mniej artefaktów niż BC1 |
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.
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 takChapter 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.
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 rendererCompression 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.
Three chapters of constraints and one engine's answers to them. Chapter 28 looks at a different kind of answer: a proprietary in-house engine, REDengine, built for one studio's games — what its material system did, what its path-traced mode changed, and what a lookdev artist should take from a technology that is now being retired in favour of the engine of Chapter 25. Trzy rozdziały ograniczeń i odpowiedzi jednego silnika na nie. Rozdział 28 przygląda się odpowiedzi innego rodzaju: autorskiemu silnikowi jednego studia, REDengine, zbudowanemu pod jego własne gry — co robił jego system materiałów, co zmienił tryb path tracingu i co lookdev artysta powinien wziąć z technologii, która jest właśnie wygaszana na rzecz silnika z Rozdziału 25.