Video oyunlarında LUT (arama tablosu) kullanımı
(blog.frost.kiwi)- LUT (arama tablosu), önceden hesaplanmış değerleri tablo gibi başvurarak kullanma yöntemidir; siyah-beyaz termal görüntülerin renklendirilmesinden oyun nesnesi varyasyonlarına ve video renk düzeltmeye kadar geniş bir alanda kullanılır
- WebGL örneği, video karelerini GPU’ya 2D doku olarak yükledikten sonra piksel bazında rengi belirleyen Fragment Shader’da tinting, 1D LUT ve 3D LUT uygulama akışını gösterir
- 1D LUT, parlaklık değerini
[0.0 - 1.0]renk dizisi koordinatı olarak kullanarak siyah-beyaz girdiyi RGB’ye dönüştürür; GPU’nun çift doğrusal filtrelemesi sayesinde küçük LUT’lar bile ara değerleri doğal biçimde enterpole eder - Valve’in Left 4 Dead örneğinde olduğu gibi tinting ve LUT, sınırlı doku belleği içinde araba, zombi derisi ve kıyafet renk varyasyonları üretmek için kullanılır
- LUT ek doku okuma maliyeti getirir; ancak gamma düzeltme gibi pahalı hesaplamaları önceden saklamak veya harici renk düzeltme iş akışlarını gerçek zamanlı grafiklere taşımak için pratik bir araçtır
LUT grafik programlamada ne işe yarar
- Arama tablosu (LUT), değerleri önceden hesaplayıp satır ya da tablo içinde sakladıktan sonra gerektiğinde başvurma yöntemidir
- Grafik programlamada bu basit yapı çeşitli görsel efektlere dönüşür
- Siyah-beyaz görüntüyü renkliye çevirir
- Renk düzeltme ve stil uygulaması yapar
- Video oyunlarında nesne varyasyonlarını verimli biçimde üretir
- Örnek WebGL kullanıyor; ancak aynı teknik DirectX, OpenGL, Vulkan, Unity ve bilimsel veri görselleştirmede de uygulanabilir
- Demo videosu Panasonic GH6 ve TESTO 890 termal kamera çekimleridir; işleme süreci cihaz dışına çıkmadan GPU üzerinde yerel olarak yapılır
WebGL işlem hattı ve tinting
- Termal kamera çıktısı siyah-beyaz videodur ve her kare WebGL üzerinden GPU’ya 2D doku olarak aktarılır
- Fragment Shader, çıktının her fragment’ı için nihai rengi belirleyen koddur
- Örnekte mevcut konumdaki video rengi
texture2D(video, tex).rgbile okunur - WebGL 1.0’da nihai çıktı
gl_FragColoriçine RGBA olarak yazılır
- Örnekte mevcut konumdaki video rengi
- Tinting, doku rengini belirli bir renkle çarparak ona renk tonu verme yöntemidir
- Örnekte
videoColor * vec3(1.0, 0.5, 0.0)ile turuncu renk çarpılır - Beyaz turuncu olur; siyah ise 0 ile çarpıldığı için siyah kalır
- Örnekte
- Bu bağlamda tinting’in çarpma maliyetini ölçmek zor olabilir
- Dokuyu bellekten getirme maliyeti çarpmadan çok daha yüksektir
- Birden çok iş parçacığı paralel çalışırken, bir pikselin doku okuması beklenirken başka piksellerin çarpma işlemi yapılabilir
- Bu, tinting’in yarattığı farkı açıklamak içindir; tüm performans optimizasyonunun bittiği anlamına gelmez
Valve’in tinting kullanımı
- Valve Software yapımı Left 4 Dead, araba varyasyonları oluşturmak için tinting’den yararlanır
- Her araba türü ve rengi için ayrı doku kullanma yöntemi doku belleği bütçesini aşabilir
- Valve, ek bir mask dokusu kullanarak arabanın boyalı bölgelerini örnek başına farklı renkte tinting uygular
- Tek bir renk dokusu 3 araba modeli arasında paylaşılır
- İki doku maliyetiyle 4 araba modeli ve fiilen sınırsız renk varyasyonu üretilebilir
- Source Engine’de yalnızca arabalar değil, özünde her şey tinting uygulanabilir
1D LUT ile siyah-beyaz değerleri renge dönüştürmek
- 1D LUT bir sayı dizisidir; RGB görüntü söz konusuysa renklerin tek boyutlu dizisidir
- Siyah-beyaz görüntünün parlaklık değeri LUT’un X ekseni koordinatı olarak kullanılıp renk alınır
- Video parlaklık değeri
[0.0 - 1.0]aralığındadır 0.0siyah LUT’un solundaki renge,1.0beyaz LUT’un sağındaki renge eşlenir- Ara değerler karşılık gelen konumdaki renge eşlenir
- Video parlaklık değeri
- WebGL 1.0’da 1D doku olmadığı için yüksekliği 1px olan 2D doku kullanılır
- Örnek kod
texture2D(lut, vec2(videoColor, 0.5))biçimindedir - Girdi 1D değer, çıktı RGB olduğundan “1D vector in, 3D vector out” yapısındadır
- Örnek kod
- GPU’nun çift doğrusal filtrelemesi, doku okuması sırasında ara değerleri otomatik enterpole eder
- 8 bit siyah-beyaz video 256 parlaklık kademesine sahiptir
- 1D LUT 32 piksel genişliğinde olsa bile pikseller arası erişim doğrusal enterpolasyonla yapılır
- Yalnızca 8 piksellik bilgiyle bile 256 piksel genişliğinde renkli bir gradyana yakın sonuç üretilebilir
Renk haritası seçimi ve algısal tekdüzelik
- Örnekte matplotlib tarafından desteklenen renk haritalarının 1D LUT olarak dışa aktarılmış listesi yer alır
- Veride belirli bir yapı yoksa algısal olarak tekdüze renk haritaları kullanmak veya renkleri buna göre ayarlamak uygundur
- viridis ailesi bunun tipik örneğidir
- Algısal olarak tekdüze renk haritaları siyah-beyaz çıktı alındığında da soğuk bölgelerin koyu, sıcak bölgelerin açık kalmasını sağlar
- jet gibi çoğunlukla yalnızca renk tonunu (hue) değiştirip algısal parlaklığı yok sayan renk haritaları bu özelliği garanti etmez
- Renk görme bozukluğu olan kişilerin de veriyi doğru yorumlayabilmesi, renk haritası seçimi için önemli bir ölçüttür
1D LUT performansı ve polinom yaklaşımı
- Küçük bir 1D LUT’un maliyeti genel olarak düşük olabilir; ancak tinting’e göre dikkate alınacak daha fazla nokta vardır
- Başlıca performans endişesi bağımlı doku okumasıdır
- İlk doku okumasının sonucu ikinci doku okumasının koordinatını belirler
- Grafik programlamada, optimize edilebilir yolların bir kısmını ortadan kaldırabilen bir desendir
- GPU’da doku önbelleği bulunur; küçük LUT önbelleğe sığabileceğinden LUT okuma maliyeti çok düşük olabilir
- İnce performans değerlendirmesi için platforma özel analiz araçları gerekir
- Nvidia NSight shader aşamalarına göre performans analizi sağlar, ancak OpenGL’i desteklemez
- Renk haritasını polinom yaklaşımı olarak uygulamak, LUT dokusuyla uğraşmayı gerektirmez
- Matt Zucker’ın ShaderToy viridis yaklaşımı Horner’s method biçiminde yazılmıştır
- Renk
c0+t*(c1+t*(c2+t*(c3+t*(c4+t*(c5+t*c6)))))biçimindeki multiply-add işlemleriyle hesaplanır - Gerçekten LUT’tan hızlı olup olmadığı, platforma özel analiz olmadan değerlendirilmesi zor bir konudur
Left 4 Dead 2’de zombi varyasyonları
- Left 4 Dead 2, basit tinting’in yeterli olmadığı deri ve kıyafet renk varyasyonları için LUT kullanır
- Basit tinting renklerin luma çeşitliliğini yeterince sağlayamayabilir
- Deri ve kıyafetler için birkaç LUT rastgele seçilerek çeşitli renk varyasyonları üretilir
- Sanatçılar uygun color ramp’leri seçip nihai oyuna dahil eder
- Tek bir dokudan hem açık renkli takım elbise hem de koyu takım elbise varyasyonları üretilebilir
- İlgili tam sunum GDC’deki Shading a Bigger Better Sequel oturumunda görülebilir
- “Exclusive Masking”, iki doku aralığını tek kanal içine koyma yöntemidir
- Texture 1, 0-128 aralığıdır
- Texture 2, 128-256 aralığıdır
- Maliyeti renk hassasiyetinin azalmasıdır
Hesaplamaları önceden saklayan 1D LUT
- 1D LUT, grafik programlamada pahalı hesaplama önbelleği olarak da kullanılabilir
- Gamma correction bunun tipik örneğidir
- Yaklaşım kullanılmıyorsa
pow()fonksiyonu gerekir - Özellikle eski GPU’larda
pow()pahalı bir komut olabilir - Standart sRGB parçalı eğrisi kullanılırsa dallanma yolları da eklenir
- Yaklaşım kullanılmıyorsa
- Gamma dönüşümünü 1D LUT olarak önceden hesaplamak, piksel başına hesaplamayı atlamayı sağlar
- Bu durumda yapı “1D vector in, 1D vector out” şeklindedir
- 1D LUT en fazla 4 renk kanalına kadar çıktı verebilir
- Redshift, geceleri monitörü turuncuya tinting uygulayarak göz yorgunluğunu azaltan bir yazılım örneğidir
- Monitörün Red, Green, Blue kanallarına ait Gamma Ramp’leri değiştirir
- Kelvin Warmth → RGB ve ek Gamma hesaplamalarını 3 adet 1D LUT olarak önceden hesaplar
- İlgili uygulama Redshift kaynak kodunda yer alır
- Bu yöntemde yeniden eşleme grafik kartında değil monitörde gerçekleştiği için performans etkisi yoktur; ancak donanım arayüzü desteği günümüzde çoğu durumda sallantılı ya da bozuk durumdadır
- Raspberry Pi grafik yığını, yeni bir güncellemede ilgili desteği kaybetmiş bir örneğe sahiptir
- Microsoft, SetDeviceGammaRamp kullanımına karşı uyarır
3D LUT: RGB uzayının tamamını yeniden eşlemek
- 3D LUT, tüm RGB uzayını tek bir küp olarak temsil eder ve olası tüm renkleri yeniden eşler
- Girdi RGB üç boyutlu vektörünü çıktı RGB üç boyutlu vektörüne dönüştürdüğü için “3D vector in, 3D vector out” yapısındadır
- Red, Green ve Blue’nun her birine 1D LUT uygulamak renk dengesini değiştirebilir
- 3D LUT, girdi RGB kombinasyonu gerektiren dönüşümler için gereklidir
- Doygunluk değişikliği
- Renk tonu (hue) değişikliği
- Belirli renk ayarlamaları
- Renk ayrıştırma
- 3D LUT genellikle küp biçimindedir; oyunlarda strip veya square biçiminde saklanır, video düzenleme araçlarında ise “Iridas/Adobe”
.cubedosyası olarak kullanılır
WebGL 1.0’da 3D LUT uygulamak
- Örnekteki video Panasonic GH6 ile çekilmiş Panasonic V-Log renk profili videosudur
- V-Log, daha fazla dinamik aralığı koruyan ve Gamut ile Gamma tanımları net olan log profildir
- WebGL 1.0, 3D dokuları desteklemediği için 3D doku okuması iki 2D doku okuması ve enterpolasyonla uygulanır
- Bu yaklaşım Gregg Tavares’in Google I/O 2011 sunumuna ve webglfundamentals.org açıklamasına dayanır
- Mevcut örnek kodda küpün Z ekseni hesaplamasıyla ilgili bir sorun nedeniyle renklerin maviye kaydığı bir hata vardı ve bu hata 2019’da düzeltildi
- WebGL 1.0, OpenGLES 2 ve OpenGL 2.1’de
OES_texture_3Dolmadan uyumluluğu korumak için 3D doku örnekleme kodunun güncel sürümü kullanılmalıdır
3D LUT ile renk düzeltme iş akışını taşımak
- 3D LUT’a uygulanan düzeltme, bu LUT’tan geçen video veya grafik sahnesine aynen uygulanır
- Örnekte V-Log video ve LUT DaVinci Resolve içine aktarılıp işlenir
- Panasonic’in V-Log to V-709 3D-LUT dosyası uygulanır
- Kontrast ve white point düzeltilerek beyazın full-bright olması sağlanır
- Düzeltilmiş LUT yeniden dışa aktarılır
- Gerçek video orijinal haliyle kalır; renk düzeltme WebGL’de LUT üzerinden gerçek zamanlı uygulanır
- Yüklenen LUT aynı boyutu korumalıdır
- Örnek kısıt 1024px × 32px
- 32³px küp biçimi korunmalıdır
Oyun sektöründe 3D LUT kullanımı
- Oyun renklerini harici araçlarda 3D LUT ile stillendirme yöntemi, video oyun sektöründe iyi bilinen standart bir iş akışıdır
- Genel prosedür şöyledir
- Renk düzeltmesi yapılacak sahnenin ekran görüntüsü alınır
- Ekran görüntüsü ve başlatılmış 3D LUT, Photoshop gibi bir araçta birlikte açılır
- Ekran görüntüsüne ve LUT’a aynı renk düzeltmesi uygulanır
- 3D LUT bölümü kesilip dışa aktarılır
- Left 4 Dead de aynı yöntemi kullanır
- Photoshop’un renk düzeltme araçları serbestçe kullanılabilir; ancak birden fazla piksel arasındaki ilişkiyi değiştiren filtreler kullanılamaz
- blur, sharpen, emboss gibi convolution türleri remapped color’ı bulanıklaştırarak beklenmeyen sonuçlar doğurabilir
Karmaşık renk düzeltmeyi tek bir LUT’a gömmek
- DaVinci Resolve gibi renk düzeltme araçları karmaşık renk dönüşümleri ve color grade’ler oluşturup bunları 3D LUT olarak dışa aktarabilir
- Örnek, film baskı görünümünü hedefleyen Kodak 2383 LUT’u uygular
- V-Log gamma videosunu Cineon Film Log’a dönüştürür
- Renk uzayını Rec.709 olarak dönüştürür
- Film emülasyonu uygular ve gamma’yı tekrar Rec.709’a dönüştürür
- Son olarak white point’i ayarlar
- Karmaşık ayrıntı dönüşümlerini doğrudan uygulamak yerine tek bir LUT’a gömüp grafik uygulamasına taşımak mümkündür
- Örnek video, yazıyla uyumluluk için 8 bit yüksek sıkıştırmalı formattadır; ancak bu işlem genellikle 10 bit footage üzerinde yapılır
- LUT boyutu sanılandan daha küçük kullanılır
- Panasonic’in resmi V-Log to V-709 3D-LUT’u 33³px boyutundadır
- Panasonic’in kamera içi izleme LUT’u 17³px kullanır
- Panasonic’in beş haneli dolar fiyat aralığındaki sinema kameralarında bile 17³px kullanılır
Grafik dışındaki LUT örnekleri
- LUT, grafik programlama dışında da kullanılır
- Tomb Raider’ın Game Boy Advance portunda da LUT’tan yararlanılmıştır
- Açık kaynak OpenLara motor portu, Game Boy Advance’te 3D özellikleri olmadığı için birçok bölümü yazılımla işler
- Bunlardan biri tamsayı bölmeyi uygulayan LUT’tur
- Bu LUT, load instruction’ı atlamak için ROM adres uzayının başlangıcına yerleştirilir
1 yorum
Hacker News yorumları
Look-up table olmasaydı bu efekti hiç uygulayamazdık sanırım: https://twitter.com/zeta0134/status/1756988843851383181
Asıl nokta iki look-up table kullanılması. Büyük tablo, oyuncunun etrafındaki ayarlanabilir bir yarıçap içinde dairesel aydınlatma bilgisini saklıyor; her yarıçap için başlı başına bir tablo var. İkinci tablo ise arka plan satırlarının sözde rastgele sırasını içeriyor. Meşale aydınlatma rutini her çağrıldığında ekranın yalnızca 1/20’sini güncelleyecek kadar zaman var; ama sırayı biraz rastgeleleştirince kenarlar yumuşak görünüyor ve normalde görülecek raster taraması gizlenebiliyor. Bu sıra, satırların güncellemede aç kalmamasını sağlayan bir grab bag; gerçek zamanlı hesaplama fazla yavaş olduğundan tablo kullanılıyor
Beni ilk gerçekten etkileyen look-up table efekti, texture tunnel yapmak için kullanılan yöntemdi
Ekrandaki her piksel için ekran merkezinden açıyı ve uzaklığı veren bir look-up table tutuluyor; bununla her piksel konumuna hangi texel’in konulacağı seçiliyor. 3B geometri tünelinin içinde hareket ediyormuşsunuz gibi görünüyor ama maliyeti çok düşük olduğundan pico’da bile mümkün: https://www.lexaloffle.com/bbs/?pid=63818
Başta Stardust’ın bu efekti kullandığını sanmıştım, ama az önce bakınca aslında arka planda tekrarlanan 6 karelik bir animasyon oynattığını gördüm: https://codetapper.com/amiga/sprite-tricks/stardust/
https://web.engr.oregonstate.edu/~mjb/cs557/Projects/Papers/Parallax_Occlusion_Mapping.pdf
Wind Waker’ın kendine özgü görünümünü oluşturmak için birden çok LUT’u nasıl kullandığına dair bir video var. BoTW ve ToTK da aynı tekniği kullanıyor
https://www.youtube.com/watch?v=mnxs6CR6Zrk
Yazının yazarıyım. Sorular varsa yanıtlayabilirim
Ancak LUT ile renk düzeltmeyi tanıtma biçimi biraz şaşırttı. Yazıda L4D2’nin kullandığı havalı, niş bir çözüm gibi görünüyor; oysa gerçekte uzun zamandır sektör standardıydı ve çalıştığım tüm oyunlarda kullanıldı. AAA oyun NFS (2015)’ten Lost in Random gibi büyük indie oyunlara kadar hepsinde böyleydi
[1] https://www.copetti.org/writings/consoles/game-boy-advance/#operating-system
“Here is every single colormap that matlibplot supports,...”
Sıkıcı iş süreçleri alanında bile bu şaşırtıcı derecede kullanışlı
Koşullu ifadelerle dolu bir kod tabanını temiz bir look-up table ile basitleştirebildiğiniz çok durum var. Basit görünen şeyler bile 50 bin satırlık bir look-up table’a dönüşebildiği için insanın aklına her zaman gelmiyor sanırım. Son kullanıcıya çok görünebilir ama bilgisayar pek umursamaz. Üstelik look-up table’lar tekrarlı olduğundan genelde yönetmesi kolaydır; kolay olmadığında bile yine de değerlidir. Kod değişikliği olmadan son kullanıcı tarafından da ayarlanabilir. Genel olarak iş mantığını kodlarken sürekli karşınıza çıkan çeşitli senaryolar için özellikle yararlı bir kavram
Retro oyunlar tabloları gerçekten çok kullanırdı. O dönemde bellek hızı çok yüksekti, işlemciler ise yavaştı; bu yüzden mümkün olduğunca çok hesaplamayı tablolara taşımak mantıklıydı. Bunu ne kadar akıllıca yaparsanız o kadar gösterişli oyunlar üretebilirdiniz
O kanalı seviyorum. Kendi modunun daha hızlı çalışması için Mario 64 kodunun tamamını elden geçirip sabit 60FPS’e getirmişti [0]
[0] https://www.youtube.com/watch?v=t_rzYnXEQlE
LUT’lerle çok uğraşıyorsanız, gelişmiş renk bilimi ve dönüşüm işlerini yöneten bir Mac uygulaması geliştiriyorum: https://videovillage.com/lattice
Eskiden NES homebrew sahnesini biraz kurcalamıştım; Bobl adlı bir oyunda sistemin hesaplayabileceğinin çok ötesinde görünen şaşırtıcı fizik efektleri görmüştüm. Meğer lookup table’mış; basit bir araçla çok karmaşık bir süreç gibi görünen şeyler yapılabileceğini o zaman fark ettim
https://morphcatgames.itch.io/bobl
A Podcast Of Unnecessary Detail, SNES Doom portu ve LUT’lerin trigonometrik fonksiyonlarda nasıl kullanıldığı üzerine bir bölüm yayımladı. Bağlam, SNES’te grafik işlemci olmadığı iddiası
https://festivalofthespokennerd.com/podcast/series-3-episode-4/
https://github.com/RandalLinden/DOOM-FX
Arka plan döndürme ve ölçekleme de yapabiliyordu. Mario Kart’ı düşünün; bu Mode 7’dir. Ayrıca birçok oyunda görebileceğiniz donanımsal saydamlığı da destekliyordu. Üstelik Doom ve Starfox gibi oyunlarda kartuşun içinde 3D hesaplamaları yapan Super FX çipi vardı. Yani o belirli oyunlarda fiilen iki grafik işlemciyle uğraşıyorlardı
SNES donanımını harika ve acı verici derecede ayrıntılı anlatan Retro Game Mechanics Explained serisi var:
https://www.youtube.com/watch?v=57ibhDU2SAI&list=PLHQ0utQyFw5KCcj1ljIhExH_lvGwfn6GV&index=1
Aklıma gelen kendi LUT kullanım alanlarım şunlardı: atmosferik saçılma, sprite renklendirme, gece görüş dürbünü, FLIR dürbünü, siyah-beyaz “video feed” efekti, glitch efekti, yükseklik haritası gölgelendirmesi, uzay gemisi egzoz plümündeki alfa nokta katsayısı, web sitesi ziyaretçilerinin fare bekleme ısı haritası, kristalimsi efektler ve son olarak ham renk uzayında post-processing renklendirme
LUT, zaten bildiğiniz değerlerden oluşan bir dizinin görselleştirilmiş hâlidir ve şaşırtıcı derecede kullanışlıdır
http://www.effectgames.com/demos/canvascycle/
İlk Xbox bunu pek iyi yapamıyordu, Photoshop da desteklemiyordu; bu yüzden popülerliği azaldı. Ama modern donanımlar AESprite’ta oluşturulan palette swap’leri rahatlıkla işleyebilir