Czerwony w sRGB i czerwony w ACEScg to dwie różne liczby dla tego samego koloru — macierz 3×3, która tłumaczy między nimi, jest fundamentem każdego pipeline'u kolorystycznego.
Prymarne danej przestrzeni RGB to trzy konkretne, ustalone kolory — czerwony, zielony, niebieski — które w dowolnych nieujemnych proporcjach mieszasz addytywnie, żeby otrzymać każdy inny kolor, jaki ta przestrzeń potrafi zapisać. „Nieujemnych” jest tu kluczowe: trójka (R,G,B) = (0,8; 0,3; 0,1) to zawsze konkretna mieszanka światła czerwonego, zielonego i niebieskiego w tych proporcjach — nigdy odejmowanie. To właśnie dlatego żadna przestrzeń RGB o skończonym, realnym zestawie prymarnych nie obejmuje wszystkich kolorów widzialnych dla człowieka: pewne bardzo nasycone kolory (zwłaszcza w okolicach turkusu i czystej zieleni) wymagałyby ujemnego udziału jednego z prymarnych, żeby je odtworzyć — czyli leżą poza gamutem.
Prymarne opisuje się jako punkty na diagramie chromatyczności CIE 1931 — dwuwymiarowej mapie wszystkich kolorów, jakie rozróżnia ludzki wzrok, niezależnie od jasności (pełne wyprowadzenie tego diagramu, wraz z przestrzenią XYZ, na której stoi, jest w Dodatku B; tutaj wystarczy traktować go jako mapę, na której każdy punkt to jeden konkretny odcień). Do tego dochodzi biały punkt — chromatyczność koloru, który przestrzeń definiuje jako neutralną biel, czyli równe (R,G,B) = (1,1,1). Bez białego punktu prymarne same w sobie nie wystarczą: mówią, które trzy światła mieszasz, ale nie mówią, w jakich proporcjach dają biel.
Cztery przestrzenie, z którymi ta książka pracuje najczęściej, różnią się dokładnie w tym: gdzie leżą ich prymarne i jaki mają biały punkt.
| Przestrzeń | R (x, y) | G (x, y) | B (x, y) | Biały punkt |
|---|---|---|---|---|
| sRGB / Rec.709 | 0,6400 · 0,3300 | 0,3000 · 0,6000 | 0,1500 · 0,0600 | D65 (0,3127 · 0,3290) |
| DCI-P3 (D65) | 0,6800 · 0,3200 | 0,2650 · 0,6900 | 0,1500 · 0,0600 | D65 (0,3127 · 0,3290) |
| ACEScg (AP1) | 0,7130 · 0,2930 | 0,1650 · 0,8300 | 0,1280 · 0,0440 | ~D60 (0,32168 · 0,33767) |
| ACES2065-1 (AP0) | 0,7347 · 0,2653 | 0,0000 · 1,0000 | 0,0001 · −0,0770 | ~D60 (0,32168 · 0,33767) |
Chromatyczności CIE xy. sRGB i Rec.709 mają identyczne prymarne — to ten sam trójkąt pod dwiema nazwami. „~D60” bo biały punkt ACES nie jest dosłownie D60 (Rozdział 6 wraca do tej niuansy).
Zauważ trzy rzeczy w tej tabeli. Po pierwsze, niebieski prymarny sRGB i DCI-P3 to dokładnie ten sam punkt — te przestrzenie różnią się tylko czerwonym i zielonym. Po drugie, zielony prymarny ACEScg (0,165; 0,830) leży bardzo blisko granicy tego, co w ogóle widzialne — stąd nazwa AP1 (ACES Primaries, wariant 1) bywa opisywana jako „szeroki, ale wciąż realistyczny” gamut, dobrany tak, żeby mieścił praktycznie każdy kolor, jaki realna kamera może zarejestrować. Po trzecie, zielony prymarny ACES2065-1 (AP0) to (0; 1) — punkt, którego żadne realne źródło światła nie potrafi wyemitować; a niebieski, (0,0001; −0,0770), ma ujemne y, czyli leży całkowicie poza obszarem kolorów widzialnych. AP0 został tak zaprojektowany celowo: to przestrzeń archiwalna, mająca matematycznie pomieścić kompletnie każdy kolor widzialny plus margines bezpieczeństwa, kosztem posiadania prymarnych, które same w sobie nie są realnymi kolorami.
Skoro dwie przestrzenie mają różne prymarne, ta sama trójka (R,G,B) opisuje w nich różne fizyczne kolory — i odwrotnie, ten sam fizyczny kolor ma różne współrzędne w każdej z nich. Żeby przejść z jednej przestrzeni do drugiej bez zmiany faktycznego koloru, potrzebna jest macierz zmiany bazy. Ogólny schemat (pełne wyprowadzenie w Dodatku A) prowadzi przez CIE XYZ jako wspólny, pośredni układ odniesienia — każda przestrzeń RGB ma swoją macierz do XYZ, zbudowaną wprost z jej prymarnych i białego punktu:
Złożenie tych dwóch macierzy w jedną daje pojedynczą macierz 3×3, która tłumaczy bezpośrednio z A do B — to właśnie tę gotową, złożoną macierz najczęściej widzisz w configu OCIO (Rozdział 6) czy w dokumentacji renderera, bez śladu przejścia przez XYZ. Jeśli białe punkty A i B się różnią (jak D65 w sRGB kontra ~D60 w ACEScg), do złożenia dochodzi dodatkowo adaptacja chromatyczna (transformacja Bradforda) — pełny wywód w Dodatku E; tutaj wystarczy wiedzieć, że jest częścią gotowej macierzy, nie osobnym krokiem, o którym trzeba pamiętać ręcznie.
W praktyce nie liczysz tych macierzy ręcznie za każdym razem — robi to config OCIO (Rozdział 6) przy każdym odczycie tekstury i każdym wyświetleniu na ekranie. Ale sama decyzja, w jakiej przestrzeni renderer wykonuje shading — czyli working space — nie jest formalnością. ACEScg (AP1) stał się w produkcji standardowym working space właśnie dlatego, że jest wystarczająco szeroki, by pomieścić realne kolory kamer i materiałów, a jednocześnie wystarczająco „ciasny” (w porównaniu z AP0), żeby operacje takie jak mnożenie w shaderze czy mieszanie w warstwach (Rozdział 15) nie generowały artefaktów przy bardzo nasyconych kolorach blisko granic gamutu. Ta sama macierz, która w tym rozdziale tłumaczyła jeden czerwony piksel, w praktyce działa na każdym pikselu każdej tekstury wchodzącej do sceny — Rozdział 6 pokazuje, gdzie dokładnie w pipeline'ie Arnolda i RenderMana ten krok się odbywa.
Ten rozdział zakładał, że wiesz, jak przejść z liczby zapisanej w pliku (percepcyjnej) na liczbę liniową, zanim w ogóle zaczniesz mnożyć przez macierze. Rozdział 5 domyka tę lukę: pokazuje dokładny kształt krzywych transferu — gamma, prawdziwe sRGB, log encodingi — stojących za tym pierwszym, wcześniej pominiętym krokiem.