UPROSZCZONA GAMMA · x^(1/2,2)PRAWDZIWE sRGB · liniowy odcinek + x^(1/2,4)LOG · stały krok na stop
Rozdział 5 / Kolor i linearność

Krzywe transferu: gamma i log

Gamma 2,2 to uproszczenie, którym posługuje się cała branża — prawdziwe sRGB, LogC czy ACEScct mają dodatkowe segmenty, o których żaden slider Ci nie powie.

TL;DR
Etap: Prosta gamma

Gamma jako funkcja potęgowa — i skąd się w ogóle wzięła

Rozdział 2 pokazał, dlaczego percepcja jasności jest w przybliżeniu logarytmiczna. Najprostszy sposób, żeby to przybliżyć jedną funkcją, to potęga:

V_encoded = V_linear^(1/γ)V_linear — wartość liniowa (proporcjonalna do fizycznego światła); γ (gamma) — wykładnik, zwykle 2,2 lub 2,4; V_encoded — wartość zapisana w pliku lub wysłana do ekranu

Gamma nie jest wynalazkiem branży efektów specjalnych — to spadek po kineskopach (CRT). Działo elektronowe starego telewizora czy monitora fizycznie reagowało na napięcie sterujące z wykładnikiem bliskim 2,4–2,5: podwojenie napięcia nie dawało podwojenia jasności plamki, tylko jasność w przybliżeniu proporcjonalną do napięcia podniesionego do tej potęgi. Żeby obraz wyglądał poprawnie, sygnał trzeba było więc wcześniej zakodować odwrotną potęgą (1/γ) — i ten krok, historycznie czysto elektroniczna konieczność, przypadkiem zadziałał też jako niezłe przybliżenie krzywej percepcji z Rozdziału 2. Nowoczesne ekrany (LCD, OLED) nie mają już fizycznego działa elektronowego, ale zachowały ten sam standard kodowania cyfrowo — dekodują go programowo, nie dzięki fizyce lampy.

Etap: Prawdziwe sRGB

Dlaczego prawdziwe sRGB to nie jest goła potęga

Czysta funkcja potęgowa ma jedną niewygodną własność blisko zera: jej pochodna przy V=0 dąży do nieskończoności (dla wykładnika mniejszego niż 1, jak 1/2,4). W praktyce oznacza to, że najmniejsze różnice w wartości liniowej blisko czerni zostałyby wzmocnione do bardzo dużych skoków w wartości zakodowanej — każdy szum czy błąd zaokrąglenia w cieniach eksplodowałby na widoczne artefakty. Standard sRGB (IEC 61966-2-1) rozwiązuje to, zastępując sam dół krzywej krótkim odcinkiem liniowym:

V_sRGB = 12,92 · V_linear, dla V_linear ≤ 0,0031308
V_sRGB = 1,055 · V_linear^(1/2,4) − 0,055, dla V_linear > 0,0031308Kodowanie (encode): z wartości liniowej do pliku/ekranu. Zwróć uwagę na wykładnik 1/2,4, nie 1/2,2 — i na przesunięcie −0,055, które sprawia, że funkcja potęgowa łączy się z odcinkiem liniowym bez skoku
V_linear = V_sRGB / 12,92, dla V_sRGB ≤ 0,04045
V_linear = ((V_sRGB + 0,055) / 1,055)^2,4, dla V_sRGB > 0,04045Dekodowanie (decode): z pliku/ekranu z powrotem do wartości liniowej — dokładnie ten krok, który Rozdział 3 nazwał warunkiem koniecznym przed wejściem do jakiegokolwiek wzoru na shading

Progi 0,0031308 (w linear) i 0,04045 (w sRGB) to dokładnie ten sam punkt na krzywej, wyrażony w dwóch różnych jednostkach — miejsce, w którym odcinek liniowy przechodzi w odcinek potęgowy tak, żeby wartość i nachylenie funkcji zgadzały się po obu stronach (bez tego przejście byłoby widoczne jako subtelny załamek na krzywej). Dokładne wyprowadzenie tych stałych — skąd się bierze akurat 1,055 i 0,055 — jest w Dodatku C; tutaj wystarczy wiedzieć, że różnica między tą pełną formułą a uproszczoną gołą potęgą 1/2,2 jest w praktyce niewielka.

Policzone: uproszczona gamma 2,2 kontra prawdziwe sRGB, dla V = 0,5
Uproszczona (^2,2): 0,5^2,2 ≈ 0,218 (linear)
Prawdziwe sRGB: ((0,5 + 0,055) / 1,055)^2,4 = 0,5261^2,4 ≈ 0,214 (linear)
Różnica: ok. 2% — realna, ale dużo mniejsza niż błąd z Rozdziału 3 (16%) wynikający z całkowitego pominięcia dekodowania
Wniosek: to, czy dekodujesz teksturę, ma dużo większe znaczenie niż to, którą dokładnie krzywą (uproszczoną czy pełną) do tego użyjesz — ale przy pracach porównawczych (Dodatek C, Pomocnik Tom 1) różnica 2% bywa dokładnie tym, co odróżnia zgodność z Nuke/OCIO od przybliżenia.
Etap: Po co log

Gamma zawodzi tam, gdzie zaczyna się materiał z kamery

Ekran SDR ma zakres rzędu 7–10 stopów (Rozdział 2) — i krzywa gamma jest dobrana pod dokładnie taki zakres: rozkłada dostępne kody (8 czy 10 bitów) tak, żeby wystarczyło ich na cienie i światła w tych granicach, bez widocznego bandingu. Nowoczesna matryca kamery filmowej rejestruje jednak 12–16 stopów i więcej. Gdyby zapisać taki materiał wprost krzywą gamma zaprojektowaną pod ekran, coś musi ucierpieć: albo górne stopy się przepalą (zabraknie kodów, żeby je odróżnić od bieli), albo cienie stracą precyzję, bo gamma i tak większość dostępnych kodów kieruje w stronę czerni, zostawiając mało miejsca dla rozciągniętego w górę zakresu jasnych partii.

Log encoding rozwiązuje to inaczej niż gamma: zamiast krzywej potęgowej używa logarytmu, którego kluczowa własność to stały krok kodu na każdy stop (podwojenie jasności), niezależnie od tego, czy ten stop leży blisko czerni czy blisko granicy zakresu matrycy. Gamma tej własności nie ma — jej „gęstość kodów na stop” zmienia się wzdłuż krzywej. To dlatego materiał z kamery filmowej bywa nagrywany w formie „płaskiej”, mało kontrastowej — log nie jest formatem do oglądania, tylko gęstym, równomiernym zapisem surowego zakresu, przeznaczonym do gradingu (Część III) już po zdjęciach.

Etap: Konkretna krzywa

ACEScct jako w pełni jawny przykład

Krzywe log kamer (ARRI LogC, Sony S-Log3) mają stałe dobrane przez producenta pod konkretną matrycę — publikowane w białych księgach danego producenta, sprawdzane per projekt, nie warte zapamiętywania na pamięć. ACEScct, log encoding samego ACES używany jako working space pod grading (Rozdział 6, Dodatek G), ma stałe w pełni jawne i publiczne — dobry, konkretny przykład tej samej idei:

ACEScct = 10,5402377416545 · lin_AP1 + 0,0729055341958355, dla lin_AP1 ≤ 0,0078125
ACEScct = (log₂(lin_AP1) + 9,72) / 17,52, dla lin_AP1 > 0,0078125lin_AP1 — wartość liniowa w przestrzeni ACEScg (Rozdział 4); log₂ — logarytm o podstawie 2, naturalny wybór, skoro jeden stop to dokładnie podwojenie; stałe 9,72 i 17,52 przesuwają i skalują wynik tak, żeby zmieścił się w wygodnym zakresie 0–1
Policzone: kod ACEScct dla 18% szarości (środek ekspozycji fotograficznej)
lin_AP1 = 0,18
log₂(0,18) ≈ −2,474
ACEScct = (−2,474 + 9,72) / 17,52 ≈ 0,4136
18% szarości ląduje w kodzie ≈ 0,414 — nieprzypadkowo blisko środka zakresu 0–1
Sprawdzenie stałego kroku na stop: pochodna funkcji log względem log₂(lin) to 1/17,52 ≈ 0,0571 — każdy kolejny stop ekspozycji, od najciemniejszego do najjaśniejszego końca zakresu, przesuwa kod ACEScct o dokładnie tę samą wartość. To jest właściwość, której gamma nie ma, i właśnie dla niej istnieje log.

ARRI LogC (obecnie w wersji Wide Gamut / LogC4), Sony S-Log3 i historyczny Cineon (log encoding zaprojektowany jeszcze pod skan negatywu filmowego, prekursor całej tej rodziny krzywych) mają dokładnie tę samą architekturę — krótki liniowy odcinek blisko czerni plus segment logarytmiczny — różniącą się stałymi dobranymi pod konkretną matrycę czy skaner. Rozdział 6 pokazuje, gdzie w praktyce Arnold i RenderMan aplikują te krzywe automatycznie, zamiast liczyć je ręcznie w node'ach.

Curve.shapeslinear → gamma → log, ten sam zakres wejścia
0 wartość liniowa (0–1, przycięta) 1,0 liniowe (bez kodowania) gamma — mniej kodów przy bieli log — kod równy na każdy stop
Gamma i log obie „unoszą” ciemne wartości wyżej niż linia prosta — ale log robi to z myślą o równych krokach na stop w szerokim zakresie, gamma z myślą o zakresie ekranu.
Słowniczek
Gamma
Kodowanie percepcyjne w formie funkcji potęgowej V^(1/γ); γ zwykle 2,2 lub 2,4.
EOTF / OETF
Electro-Optical / Opto-Electrical Transfer Function — formalne nazwy funkcji dekodującej (EOTF, kod → światło z ekranu) i kodującej (OETF, światło → kod).
Log encoding
Kodowanie logarytmiczne dające stały krok kodu na jeden stop ekspozycji, niezależnie od miejsca w zakresie — używane do przechwytywania szerokiego zakresu kamer.
Middle grey (18% szarości)
Umowny punkt odniesienia ekspozycji fotograficznej, w przybliżeniu środek subiektywnego zakresu tonalnego — realizowany w ACEScct jako kod ≈ 0,414.
Code value
Konkretna liczba zapisana w pliku lub buforze — odróżniana celowo od „jasności”, bo związek między nimi zależy od krzywej transferu.