8 kB ile yapılmış animasyon filmi
(ctrl-alt-test.fr)- Ctrl-Alt-Test ekibi, Kasım 2022’den itibaren kısa animasyon gibi görünen gerçek zamanlı bir demoyu 8 kB içine sığdırma denemesine başladı ve Nisan 2023’te The Sheep and the Flower’ı yayımladı
- Ortaya çıkan çalışma, kaynak dosyası veya dış bağımlılık olmadan tek bir
.exedosyasının grafik ve müziği üretmesiyle çalışıyor; sahneler GLSL shader’ları ve raymarching ile GPU’da gerçek zamanlı hesaplanıyor - Koyun, tabela, kamera ve timeline; saklanmış model ya da texture’lardan değil, SDF, prosedürel 3D texture’lar ve hardcode edilmiş zaman parametrelerinden oluşuyor; yaklaşık 25 kamera çekimi elle ayarlandı
- Müzik OpenMPT ve 4klang ile yapıldı; sıkıştırma verimliliğini artırmak için enstrüman sayısı 16’dan 13’e düşürüldü ve tekrarlar artırıldı
- Nihai 8 kB, Crinkler sıkıştırması ve Shader Minifier iyileştirmeleriyle mümkün oldu; 42 kB’lık shader kodu küçültme ve sıkıştırmadan sonra yaklaşık 5 kB’a sığdı, müzik ve C++ kodu için yer bıraktı
8 kB içine sığan tek yürütülebilir dosya
- The Sheep and the Flower, Nisan 2023’te yayımlanan, Windows yürütülebilir dosyası biçiminde gerçek zamanlı bir animasyondur
- Tek bir
.exedosyası her şeyi üretir; ayrı kaynak dosyası veya dış bağımlılık yoktur- Çalıştırmak için Windows ve güncel sürücüler gerekir
- Hedef, grafik, animasyon, yönetmenlik, kamera kullanımı ve müziğin tamamını 8 kB içine koymaktı
- Kaynak kod GitHub’da yayımlandı: ctrl-alt-test/mouton
Grafik, müzik ve sıkıştırmada kullanılan araçlar
- Tüm görsel öğeler GPU’da gerçek zamanlı hesaplanır
- GLSL shader’ı timeline bilgilerini, kamera ayarlarını ve sahne temsilini bile içerir
- Render işlemi raymarching ile yapılır
- Shader, Shader Minifier ile küçültülür
- Müzik, OpenMPT ve 4klang synthesizer ile üretildi
- Enstrümanlar prosedürel olarak tanımlanır
- Nota listesi sıkıştırılır
- Kod, Visual Studio 2022’de C++ ile yazıldı
- Derleyici bayrakları ve başlatma için Leviathan framework’ü temel alınarak başlandı
- Nihai yürütülebilir dosya Crinkler ile sıkıştırıldı
Neden 8 kB?
- Demoscene’de 4 kB ve 64 kB gibi boyut sınırlı kategoriler yaygındır
- Önceki çalışmalar çoğunlukla 64 kB’ı hedefliyordu, ancak 8 kB bambaşka kısıtlar ve kurallar sunuyordu
- 4 kB intro teknikleri ilginç olsa da, düzgün bir hikâye anlatımı için fazla sınırlı görüldü
- Revision demoparty birkaç yıl önce 8 kB yarışma kategorisi eklemişti; bu da deney yapmak için iyi bir fırsat olarak görüldü
İki üçgenle çizilen dünya
- Demoscene’de 2008’den beri standart olarak kullanılan yaklaşıma benzer şekilde, ekranın tamamını kaplayan dikdörtgen iki üçgen olarak çizilir
- Bu dikdörtgen üzerinde GLSL shader’ı her pikselin ve her frame’in rengini hesaplar
- Shader fonksiyonu koordinatları ve zamanı girdi olarak alıp renk döndürür
- Temel zorluk, koyunu ve tüm sahneyi bu fonksiyonun içinde nasıl temsil edecekti
SDF ile sahneyi kurmak
- Signed distance field (SDF), uzaydaki bir noktadan en yakın nesneye olan mesafeyi hesaplayan bir fonksiyondur
- Yüzey üzerinde 0 döndürür
- Nesnenin içinde negatif değer döndürür
- Küre veya kutu gibi temel şekiller basit formüllerle ifade edilebilir
- Birden fazla distance field birleştirilerek sahne oluşturulur
- İki nesnenin birleşimi, mesafelerin minimum değeriyle yapılabilir
- Kesişim, maksimum değerle yapılabilir
- Smooth union kullanıldığında daha organik biçimler elde edilebilir
- Koyun, koni ve küre gibi basit şekillerin birleştirilip kaynaştırılmasıyla yapıldı; gövde ve yün 3D noise fonksiyonu ile oluşturuldu
Raymarching ile pikselleri belirleme yöntemi
- Raymarching, SDF kullanarak bir 3D sahne içinde ışını adım adım ilerleten bir render tekniğidir
- Geleneksel ray tracing’deki gibi kesişim noktası matematiksel olarak doğrudan hesaplanmaz
- SDF, çarpışma olmadan gidilebilecek mesafeyi bildirir; ışının bu kadar ilerletilmesi süreci tekrarlanır
- Mesafe 0’a veya 0’a yakın bir değere düştüğünde kesişim bulunmuş kabul edilir
- Kesişim oluştuğunda mevcut pikselin koyun, gökyüzü veya başka bir nesneden hangisine karşılık geldiği anlaşılır
- Aydınlatma için yüzey normali gerekir; çevredeki eğim hesaplanarak normal tahmin edilir
- Gölgeler, kesişim noktasından güneş yönüne başka bir ışın gönderilip arada nesne olup olmadığı kontrol edilerek hesaplanır
Küçük bir ifade gücüyle hikâye anlatmak
- Demoda seslendirme veya yazı yoktur, karakter de yalnızca birdir
- Koyun yalnızca yürüyebilir, başını ve gözlerini hareket ettirebilir; hatta dönemaz
- Bu kısıtlar içinde duygu aktarabilmek için hikâyeyle ilgisiz öğeler çıkarıldı
- Başta çöl, kum tepeleri ve gökyüzü düşünülmüştü; ancak hikâye için gerekli olmadığına karar verildi
- Arka plan saf beyaz tutuldu
- Anlamı ileten tabela ve gözler dışında texture’lar azaltıldı
- Küçük bir kapsam korunarak detay, cilalama, kamera çalışması, kurgu ve müzik senkronizasyonuna odaklanıldı
- Her çekim elle kurgulandı ve animasyonun akışı doğal hissettirsin diye tekrar tekrar ayarlandı
Kamera ve yönetmenlik
- Kamera, hikâye anlatma aracı olarak kullanıldı
- Koyunun uzun süre dolaştığı sahnelerde yalnızlık hissi yaratmak için geniş planlar kullanıldı
- Tabelayı fark ettiği anda gözlerin extreme close-up çekimi kullanıldı
- Koyun tabelaya bakarken odağı artırmak için başa doğru yavaş zoom yapıldı
- Koyunun heyecanı birkaç ifade katmanıyla aktarıldı
- Çizgi film tarzı 2D efektler
- Hızlanan yürüyüş
- Vurgulanan kuyruk hareketi
- Abartılı baş sallama
- Müziğin dramatik değişimi
Hızlı iterasyon için geliştirme yöntemi
- Kaynak kodda çok sayıda hardcode edilmiş sabit bulunur
- Koyunun göz boyutu
- Kamera hareket hızı
- Her çekimin süresi
- Çiçeğin rengi gibi değerler tekrar tekrar ayarlandı
- Hızlı geri bildirim için shader runtime’da yeniden derlenerek grafikler 1 saniyeden kısa sürede güncellendi
- Animasyon ve kamera ayarı için bir player gerekiyordu
- Duraklatma
- Oynatma
- Zaman kontrolü
- Shader live reload sonrası anında kontrol
- Müzik ve animasyonu doğru senkronize etmek için müzik desteği de şarttı
- İlk prototip Shadertoy üzerinde yapıldı; ardından KodeLife üzerinden C++ projesine taşındı
4klang ile yapılan müzik
- Müzik, hikâye anlatımı için önemli bir öğeydi; farklı atmosferlere ve belirli anlardaki geçişlere ihtiyaç vardı
- 4 kB intro’larda kullanılan araç aynen kullanıldı, ancak daha karmaşık bir yapı için daha fazla alan ayrıldı
- 4klang synthesizer, müzik yazılımlarında kullanılabilecek bir eklenti sağlar ve assembly dosyası dışa aktarır
- Bu assembly dosyası demo ile birlikte derlenip link edilir
- Demo çalışırken synth ayrı bir thread’de dalga biçimli sesi prosedürel olarak üretip ses kartına gönderir
- İlk yapılan müzik beklenenden büyüktü; boyutu azaltmak için çeşitli ayarlamalar yapıldı
- Enstrüman sayısı 16’dan 13’e düşürüldü
- Bitiş teması, tüm müziğin temposuna uyacak şekilde yeniden bestelendi
- Daha iyi sıkıştırılsın diye tekrarlar artırıldı
- Arka plan seslerinin nota uzunluğu gibi kulakla neredeyse fark edilmeyen değişikliklerle sıkıştırma oranı iyileştirildi
- Müziğin genel yapısı korunurken kalite kaybı en aza indirildi ve yer tasarrufu sağlandı
Animasyon ve zaman senkronizasyonu
- Demo, ön hesaplama veya cache olmadan her frame’de her şeyi yeniden değerlendirir
- Bu performans açısından dezavantajlıdır, ancak herhangi bir öğe zamana bağlı olarak değişebildiği için animasyon açısından avantajlıdır
- Tüm demo yaklaşık 25 elle yapılmış kamera çekiminden oluşur
- Her çekim, 18 parametrenin zaman içinde nasıl değiştiğini tanımlar
- Her nesnenin konumu
- Koyunun durumu
- Kamera konumu
- Odak
- Kameranın baktığı hedef vb.
- Örnek olarak
camPos = vec3(22., 2., time*0.6-10.);tek satırı bile çekimde kameranın doğrusal hareketini ifade eder time, demonun başlangıcından itibaren mutlak zamanı değil, çekimin başlangıcından itibaren geçen zamanı ifade eder- Çekim ekleme, silme veya ayarlama işlemleri geri kalan demoyu daha az etkiler
- Basit doğrusal interpolasyon mekanik görünebildiğinden birçok durumda smoothstep kullanıldı
- Timeline kodu vertex shader’ın içindedir
- Çekim tanımlarında çok fazla tekrar eden kod vardır, ancak tekrar sıkıştırma açısından avantaj sağlar
Texture ve malzemeler
- Geleneksel renderer’larda 2D texture’lar 3D model yüzeylerine uygulanır
- Raymarching yönteminde texture koordinatlarını kolayca hesaplamak zor olduğundan, bunun yerine 3D texture’lar anında hesaplanır
- Raymarcher render edilecek 3D konumu bulduğunda, ilgili 3D koordinatları texture fonksiyonuna aktarır
- Trafik tabelası, matematikle üçgen veya dikdörtgen kenarlıklar oluşturarak yapılır; iç içerik ise birden fazla fonksiyonun birleştirilmesiyle çizilir
- Restoran simgesi, 4 siyah oval şekil ve oyuk oluşturan 2 beyaz şekilden oluşur
- Görsel çeşitlilik için yalnızca texture’lar değil, malzemeler de farklı ayarlandı
- Örneğin koyunun toynakları, Fresnel katsayısı kullanılarak farklı yansımaya sahip olacak şekilde işlendi
Gözleri canlandıran sahte yansıma
- Geliştirme sırasında uzun süre gözler cansız ve düz görünüyordu
- Gözler, karakter tasarımı ve hikâye anlatımı için önemli bir öğeydi
- Çizgi film karakter referanslarında irislerin sık görüldüğü, ancak şart olmadığı; göz bebeklerinin ise genellikle büyük çizildiği görüldü
- Parlayan gözler yapmak için göz içinde ışık yansıması gerekiyordu
- Mevcut aydınlatma denklemleriyle, yalnızca güneş ve kamera belirli konumlardayken yansıma oluşuyordu
- Bunu telafi etmek için yüzey normal vektörü değiştirilerek güneş yansıması oluşma olasılığı artırıldı
- Ek olarak environment mapping kullanıldı
- Oyunlarda genellikle gerçek ortam yansımalarını basitleştirip optimize etmek için kullanılır
- Burada gerçek dünya neredeyse tamamen beyaza yakın olsa da, texture ile sahte detay eklendi
- Göz akı ve göz bebeğinde, boş dünyadan çok daha karmaşık yansımalar bulunur
- Birden çok sahte ışık kaynağı
- Koyu zemin ve mavi gökyüzünü taklit eden gradyan
Post-processing ve görsel stil
- Nihai atmosfer ve görüntü kalitesi post-processing ile rafine edildi
- Kullanılan post-processing işlemleri şunlardı
- Color grading
- Gamma correction
- Hafif vignette
- Aliasing’i azaltmak için 2-pass FXAA filtresi
- Gözlerdeki yıldız efekti veya final ekranı efekti gibi bazı efektler de post-processing aşamasında uygulandı
- Bu efektler saf 2D’dir ve 3D dünyada mevcut değildir
- Bir ara eski çizgi film tarzı da denendi
- El çizimi gibi görünmesini sağlayan kontur algılama
- Siyah-beyaz render
- Grain ve noise
- Tartışmaların ardından bu denemeden vazgeçilip daha temiz ve modern bir görünüme odaklanıldı
Crinkler sıkıştırması
- Temel fikir, veriyi saklamak yerine veriyi üreten kodu saklamaktır
- Müzik, çalınacak nota listesini ve her enstrümanın komut listesini saklar
- Crinkler, demoscene ve 1 kB~8 kB intro’lar için tasarlanmış bir sıkıştırma aracıdır
- Yürütülebilir dosyanın kendi kendini açabilmesi gerektiğinden, Crinkler geri kalan yürütülebilir dosyayı açabilecek küçük assembly kodu içerir
- Crinkler boyut optimizasyonunu önceliklendirir
- Sıkıştırma algoritması zaman alır
- Açma işlemi nispeten yavaştır
- Yüzlerce MB RAM kullanır
- Ancak Crinkler tek başına yeterli değildi; 42 kB’lık shader kaynak kodunu yürütülebilir dosyaya koymak için ek küçültme gerekiyordu
Shader Minifier iyileştirmeleri
- Shader kaynak kodu nihai binary’ye dahil edildiğinden olabildiğince küçük olmalıydı
- Elle küçültmek de mümkündü, ancak bakım ve hızlı iterasyon açısından sorun yaratırdı
- Shader Minifier, 2011’den beri geliştirilen bir shader küçültme aracıdır
- Boşlukları ve yorumları kaldırır, değişken adlarını kısaltır ve daha fazla dönüşüm uygular
- 8 kB intro, 4 kB’a kıyasla çok daha fazla kod içerdiği için yeni sorunlar ortaya çıktı; gerekli işlevleri eklemek üzere demo çalışması bir ay durduruldu
- İyi küçültme için basit bir minifier değil, Closure Compiler’a benzer bir source-to-source compiler gerekiyordu
- Shader Minifier’ın yaptığı dönüşümler şunları içerir
- Değişken ve fonksiyon adlarını değiştirme
- Değişken inline etme
- Sabit aritmetik ifadeleri değerlendirme
- Fonksiyon inline etme
- Dead code elimination
- Bildirimleri birleştirme
- Yalnızca kodun kendi boyutunu küçültmek yeterli değildir; sıkıştırma dostu çıktı gerekir
- Bazı dönüşümler kod boyutunu küçültse de sıkıştırma sonrası boyutu artırabilir
- Demo tekrar tekrar geliştirilirken sıkıştırma sonrası boyut sürekli kontrol edilmeliydi
- Yeni Shader Minifier iyileştirmeleriyle sıkıştırılmış binary’de yaklaşık 600 bayt tasarruf edildi
- Sonuçta 42 kB’lık shader kodu küçültme ve sıkıştırmadan sonra yaklaşık 5 kB içine sığdı
- Kalan alana müzik ve C++ kodu girdi
Başka çalışmaların üzerine inşa edilen sonuç
- Bu demo; raymarching teknikleri, müzik üretim yazılımları ve sıkıştırma algoritmaları gibi başkalarının yaptığı çalışmaların üzerine inşa edildi
- Shader Minifier’a eklenen yeni özelliklerin gelecekte daha iyi demolar yapmaya yardımcı olması umuluyor
- 8 kB kategorisinin 4 kB’tan daha fazla olanak sunduğu ve daha popüler hâle gelmesinin umulduğu belirtiliyor
- Karşılaştırma için, özgün metin yaklaşık 21.000 karakter uzunluğunda; aynen konulsa 21 kB gerekirdi
1 yorum
Hacker News yorumları
Bu filme ilham veren özgün filmin yapımcısıyım: https://www.youtube.com/watch?v=khWXdkryBE4
Özgün yapımda yalnızca Blender, SVG ve ses dosyaları bile MB düzeyindeyken, yeniden yapımın 8kB içine sığması gerçekten etkileyici
Creative Commons lisansının gerçekten işe yaradığını görmek sevindirici; ama aynı kirpi karakterini ve ses melodisini kullansaydı daha da iyi olurdu diye düşünüyorum
Sloot geri döndü!!!
https://en.m.wikipedia.org/wiki/Sloot_Digital_Coding_System
Bir sürü demoscene insanını topla, filmi göster ve bilgisayarların olduğu bir odaya bir süre kilitle
Büyük ekran, büyük ses sistemi, bira ve abur cubur olursa daha iyi çalışır; sonra sonuçtaki çalıştırılabilir dosyayı alırsın
aPerformans için Rust ile yazılmış yorumlayıcı,
akomutunu değerlendirirken çalışma zamanına gömülü belirli bir payload’u STDOUT’a basıyorHerkes için gerçekten berbat bir talihsizlikti
Muhtemelen o kişiler a) bunun tek yönlü bir fonksiyon olduğunu ve b) tek yönlü olmasa bile birden fazla girdinin aynı hash’e eşlenebileceğini anlamamıştı
Demoscene videoları epey eğlenceli ama saçma derecede az biliniyor
https://www.youtube.com/playlist?list=PLRQwR4-_0PR9HBI_GZs1nTn7q5LTkGeCN
retro game mechanics gibi, iç işleyişi iyi görsellerle anlatan bir kanal olsa güzel olurdu
Video olmadığı zamanlarda, hayran kalmak ya da hayal kırıklığına uğramak için önce açma ve işleme sürecinin epey beklenmesi gerekiyordu
Eskiden molalarda çok demo izlerdim; o zamanki ruh hâlime mükemmel bir arka plandı
https://en.wikipedia.org/wiki/.kkrieger
Daha da ileri gidersek, birbirleriyle zeki ajanlardan oluşan bir dünyayı ne kadar küçük yapabiliriz?
Ek: Eksileyenler, hiç hayal kurmuyor musunuz? Önümüzde gerçekten çılgınca fantastik çok şey var
Arkasındaki tekniğin epey farklı olduğunu biliyorum ama eski .kkrieger aklıma geldi. Tüm bir 3D FPS’i 96k’ya sıkıştırmıştı; gerçekten çok havalıydı
https://en.m.wikipedia.org/wiki/.kkrieger
Demoscene’i çok izleyip üretim yöntemlerini okudukça sınırları anlamaya başlıyorsun; koyun gibi unsurların, özellikle de bacaklardaki konik kesitlerin çok sıkıştırılmış denklemlerle ifade edilip benzer şekilde animasyonlanabileceği açık hâle geliyor
Ama bildiğim kadarıyla demoların çoğu GPU’ya ve güçlü 3D hızlandırma yeteneklerine dayanırken, 2D Japon anime tarzı demolar küçük boyutlarda nadir ya da neredeyse yok gibi görünüyor
Gerçekten 3D animasyon daha mı kolay?
Bu arada “mouton” Fransızcada “koyun” demek; “mutton” da buradan geliyor
Buna karşılık 2D tarzı animasyonu depolamanın ‘matematiksel’ yolu, konturları SVG eğrileri olarak saklamak ve alan boyama için alan doldurma algoritmaları kullanmakla sınırlı
Kabaca hesaplayınca, tek bir eğri yayı ya da çizgi bile tüm bir geometrik hacim açıklaması kadar depolama alanı yiyebilir; bu eğrilerin animasyonunu da saklamak istersen, 3D hacmin küçük dönüşüm matrislerine kıyasla çok daha fazla alan gerekir
Render algoritmasının karmaşıklığı da hem gerçek algoritma karmaşıklığı hem de alan karmaşıklığı açısından artacak gibi
Not: Birden fazla bitmap’i saklayıp flipbook gibi oynatmanın da, değişimlerden tam kare üreten prosedürel bir açma algoritması kullanılıyorsa ‘matematiksel’ olduğu iddia edilebilir
Ama böyle bir yöntemin var olduğunu sanmıyorum ve 3D hacim açıklamasına kıyasla alan gereksinimi muazzam olurdu
8kB’den biraz büyük ama koyunlarla ilgili beklenmedik derecede karanlık animasyonları seviyorsanız Blender Foundation’ın açık filmi Cosmos Laundromat’ı öneririm
Bu vakfın filmleri teknik demo olmalarına rağmen her zaman tuhaf biçimde karanlık oluyor; bu yapımın özellikle iyi çıktığını düşünmüştüm
[0] https://www.youtube.com/watch?v=Y-rmzh0PI3c
Önceden uyarayım: film “to be continued” diye bitiyor ve Wikipedia sayfasında şöyle yazıyor:
“Bu film başlangıçta uzun metrajlı bir filmin başlangıç noktası olarak tasarlanmıştı. Kısa bir devam filmi için senaryo ve tasarımlar vardı, ancak prodüksiyona geçemedi. 2020’de [yaratıcı], projenin tamamının bu tek filmden ibaret olacağını duyurdu”
İlginç bir konseptin sonunu asla görememenin hayal kırıklığını yaşamak istemiyorsanız, es geçmek daha iyi olabilir
DaVinci Resolve’da HDR denemeleri yaparken işe yaramıştı
[1] https://opencontent.netflix.com/#h.uyzoa2bivz2j
8KB, demoscene’in bir kategorisi. Pouet’te bu tür işleri iyi derleyen bir indeks var
0. https://www.pouet.net/prodlist.php?type%5B%5D=8k&page=1
Razor 1911. Saf nostalji
On yıllar öncesinden çok güzel anıları akla getiriyor :-)
Gerçekten şaşırtıcı; kısıtlı koşullar altında bile hikâyenin bu kadar komik ve yaratıcı olmasını sevdim. Gerçekten etkileyici
Baytları azaltmak için ne tür hileler ve tasarruflar yaptıklarına dair daha fazla teknik ayrıntı duymak isterim
Bu commit’te (https://github.com/ctrl-alt-test/mouton/commit/79d2d1eab7a222b434b7041d8fc9bce4e60524f8) performans optimizasyonu kaldırılarak çok sayıda bayt tasarrufu sağlanmış
Aslında bunu korumak istiyorlardı ama baytları yetmiyordu; ayrıca nispeten yeni GPU’larda o optimizasyona gerek olmadığını fark etmişler
Komik olduğu kadar bütünüyle şaşırtıcı. Sonunda sonunu tahmin edemediğim bir film izledim