Film animasi yang dibuat dalam 8kB
(ctrl-alt-test.fr)- Tim Ctrl-Alt-Test memulai eksperimen pada November 2022 untuk memuat demo real-time yang tampak seperti film animasi pendek ke dalam 8kB, lalu merilis The Sheep and the Flower pada April 2023
- Hasilnya adalah satu file
.exeyang menghasilkan grafis dan musik tanpa file resource atau dependensi eksternal, sementara adegan dihitung secara real-time di GPU dengan shader GLSL dan raymarching - Domba, rambu, kamera, dan timeline tidak dibuat dari model atau tekstur yang disimpan, melainkan dari SDF, tekstur 3D prosedural, dan parameter waktu yang di-hardcode, dengan sekitar 25 shot kamera yang disetel manual
- Musik dibuat dengan OpenMPT dan 4klang, sambil mengurangi jumlah instrumen dari 16 menjadi 13 dan menambah pengulangan untuk meningkatkan efisiensi kompresi
- Ukuran akhir 8kB dimungkinkan berkat kompresi Crinkler dan peningkatan Shader Minifier; kode shader 42kB masuk ke sekitar 5kB setelah minimisasi dan kompresi, menyisakan ruang untuk musik dan kode C++
Satu file executable dalam 8kB
- The Sheep and the Flower adalah animasi real-time dalam bentuk file executable Windows yang dirilis pada April 2023
- Satu file
.exemenghasilkan semuanya, tanpa file resource terpisah atau dependensi eksternal- Untuk menjalankannya dibutuhkan Windows dan driver terbaru
- Tujuannya adalah memasukkan grafis, animasi, penyutradaraan, pergerakan kamera, dan musik ke dalam 8kB
- Kode sumber dipublikasikan di GitHub: ctrl-alt-test/mouton
Alat yang dipakai untuk grafis, musik, dan kompresi
- Semua elemen visual dihitung secara real-time di GPU
- Shader GLSL mencakup informasi timeline, pengaturan kamera, hingga representasi adegan
- Rendering dilakukan dengan raymarching
- Shader diperkecil dengan Shader Minifier
- Musik dibuat dengan OpenMPT dan synthesizer 4klang
- Instrumen dideskripsikan secara prosedural
- Daftar not dikompresi
- Kode ditulis dalam C++ di Visual Studio 2022
- Flag compiler dan inisialisasi dimulai dari framework Leviathan
- File executable akhir dikompresi dengan Crinkler
Mengapa 8kB
- Di demoscene, kategori dengan batas ukuran seperti 4kB dan 64kB sudah umum
- Karya sebelumnya terutama menargetkan 64kB, tetapi 8kB memberi batasan dan aturan yang sepenuhnya berbeda
- Teknik intro 4kB menarik, tetapi dianggap terlalu terbatas untuk storytelling yang layak
- Demoparty Revision menambahkan kategori kompetisi 8kB beberapa tahun lalu, dan itu dijadikan kesempatan bagus untuk bereksperimen
Dunia yang digambar dengan dua segitiga
- Seperti pendekatan yang menjadi standar di demoscene sejak 2008, sebuah persegi panjang yang menutupi seluruh layar digambar dengan dua segitiga
- Di atas persegi panjang ini, shader GLSL menghitung warna tiap piksel dan tiap frame
- Fungsi shader menerima koordinat dan waktu sebagai input lalu mengembalikan warna
- Tantangan utamanya adalah bagaimana merepresentasikan domba dan seluruh adegan di dalam fungsi itu
Menyusun adegan dengan SDF
- Signed Distance Field (SDF) adalah fungsi yang menghitung jarak dari satu titik di ruang ke objek terdekat
- Di permukaan, nilainya 0
- Di dalam objek, nilainya negatif
- Bentuk dasar seperti bola atau kotak bisa direpresentasikan dengan rumus sederhana
- Beberapa distance field digabungkan untuk membentuk adegan
- Gabungan dua objek bisa dibuat dengan nilai minimum jaraknya
- Irisan bisa dibuat dengan nilai maksimumnya
- Smooth union memungkinkan bentuk yang lebih organik
- Domba dibuat dengan merakit dan menggabungkan bentuk sederhana seperti kerucut dan bola, sementara badan dan bulunya dibentuk dengan fungsi noise 3D
Cara raymarching menentukan piksel
- Raymarching adalah teknik rendering yang menggunakan SDF untuk memajukan sinar sedikit demi sedikit di dalam adegan 3D
- Berbeda dari ray tracing tradisional, titik perpotongan tidak dihitung langsung secara matematis
- SDF memberi tahu seberapa jauh sinar bisa bergerak tanpa bertabrakan, lalu proses itu diulang
- Saat jaraknya menjadi 0 atau mendekati 0, titik perpotongan dianggap telah ditemukan
- Ketika ada titik perpotongan, bisa ditentukan apakah piksel saat ini milik domba, langit, atau objek lain
- Pencahayaan membutuhkan normal permukaan, yang diperkirakan dengan menghitung gradien di sekitar titik tersebut
- Bayangan dihitung dengan mengirim sinar lain dari titik perpotongan ke arah matahari untuk memeriksa apakah ada objek di tengahnya
Menyampaikan cerita dengan daya ekspresi yang kecil
- Demo ini tidak memiliki suara atau teks, dan karakternya hanya satu
- Domba hanya bisa berjalan, menggerakkan kepala dan mata, dan bahkan tidak bisa berputar
- Untuk menyampaikan emosi dalam keterbatasan ini, elemen yang tidak terkait cerita disingkirkan
- Awalnya mereka membayangkan gurun, bukit pasir, dan langit, tetapi menilai itu tidak diperlukan untuk cerita
- Latar belakang dipertahankan putih polos
- Tekstur dikurangi kecuali pada rambu dan mata yang membawa makna
- Dengan menjaga cakupan tetap kecil, mereka bisa fokus pada detail, polishing, camera work, editing, dan sinkronisasi musik
- Tiap shot disusun manual, dan animasinya disetel berulang kali agar alurnya terasa alami
Kamera dan penyutradaraan
- Kamera dipakai sebagai alat untuk menyampaikan cerita
- Shot lebar digunakan saat domba mengembara lama untuk menciptakan rasa kesepian
- Extreme close-up pada mata dipakai saat domba menyadari rambu itu
- Ketika domba menatap rambu, kamera melakukan zoom-in perlahan ke arah kepala untuk meningkatkan fokus
- Kegembiraan domba disampaikan dengan menumpuk beberapa ekspresi
- Efek 2D bergaya kartun
- Langkah yang dipercepat
- Gerakan ekor yang ditegaskan
- Goyangan kepala yang dilebih-lebihkan
- Perubahan dramatis pada musik
Cara pengembangan untuk iterasi cepat
- Kode sumber berisi banyak konstanta yang di-hardcode
- Ukuran mata domba
- Kecepatan pergerakan kamera
- Durasi tiap shot
- Nilai seperti warna bunga disetel berulang kali
- Demi umpan balik cepat, shader dikompilasi ulang saat runtime sehingga grafis bisa diperbarui dalam waktu kurang dari 1 detik
- Sebuah player diperlukan untuk menyesuaikan animasi dan kamera
- Pause
- Play
- Kontrol waktu
- Langsung memeriksa hasil setelah live reload shader
- Dukungan musik juga wajib agar musik dan animasi bisa sinkron dengan akurat
- Prototipe awal dibuat di Shadertoy, lalu dipindahkan melalui KodeLife ke proyek C++
Musik yang dibuat dengan 4klang
- Musik adalah elemen penting untuk menyampaikan cerita, dan dibutuhkan beberapa suasana serta transisi pada momen tertentu
- Alat yang dipakai di intro 4kB tetap digunakan, tetapi diberi lebih banyak ruang untuk komposisi yang lebih kompleks
- 4klang synthesizer menyediakan plugin yang bisa dipakai di software musik, lalu mengekspor file assembly
- File assembly ini dikompilasi dan di-link bersama demo
- Saat demo berjalan, synth secara prosedural menghasilkan suara waveform di thread terpisah lalu mengirimkannya ke sound card
- Musik pertama yang dibuat ternyata lebih besar dari perkiraan, sehingga dilakukan berbagai penyesuaian untuk mengecilkannya
- Jumlah instrumen dikurangi dari 16 menjadi 13
- Tema ending dikomposisi ulang agar sesuai dengan tempo keseluruhan musik
- Pengulangan ditambah agar lebih mudah dikompresi
- Perubahan yang hampir tak terdengar, seperti panjang not pada suara latar, dipakai untuk meningkatkan rasio kompresi
- Struktur keseluruhan musik dipertahankan sambil meminimalkan penurunan kualitas dan menghemat ruang
Animasi dan sinkronisasi waktu
- Demo ini mengevaluasi ulang semuanya di setiap frame tanpa pra-perhitungan atau cache
- Ini buruk untuk performa, tetapi menguntungkan untuk animasi karena elemen apa pun bisa berubah berdasarkan waktu
- Keseluruhan demo terdiri dari sekitar 25 shot kamera yang disusun manual
- Tiap shot mendeskripsikan bagaimana 18 parameter berubah seiring waktu
- Posisi tiap objek
- Status domba
- Posisi kamera
- Fokus
- Target yang dilihat kamera
- Sebagai contoh,
camPos = vec3(22., 2., time*0.6-10.);saja sudah cukup untuk merepresentasikan gerakan linear kamera dalam satu shot timebukan berarti waktu absolut sejak demo dimulai, melainkan waktu sejak shot itu dimulai- Ini mengurangi dampak pada sisa demo ketika shot disisipkan, dihapus, atau diubah
- Interpolasi linear sederhana bisa terlihat mekanis, sehingga dalam banyak kasus digunakan smoothstep
- Kode timeline berada di dalam vertex shader
- Definisi shot memang berisi banyak kode berulang, tetapi pengulangan justru menguntungkan untuk kompresi
Tekstur dan material
- Dalam renderer tradisional, tekstur 2D ditempelkan ke permukaan model 3D
- Dalam pendekatan raymarching, koordinat tekstur sulit dihitung dengan mudah, sehingga tekstur 3D dihitung saat itu juga
- Ketika raymarcher menemukan posisi 3D yang akan dirender, koordinat 3D itu diteruskan ke fungsi tekstur
- Rambu lalu lintas dibuat secara matematis dengan membentuk bingkai segitiga atau persegi panjang, lalu isi di dalamnya digambar dengan kombinasi beberapa fungsi
- Simbol restoran terdiri dari empat bentuk oval hitam dan dua bentuk putih yang membentuk lekukan
- Untuk variasi visual, bukan hanya tekstur yang dibedakan, tetapi juga materialnya
- Misalnya, kuku domba diberi pantulan berbeda dengan memanfaatkan koefisien Fresnel
Pantulan palsu untuk menghidupkan mata
- Selama pengembangan, mata lama terlihat datar dan tidak hidup
- Mata merupakan elemen penting dalam desain karakter dan penyampaian cerita
- Dari gambar referensi karakter kartun, mereka melihat bahwa iris sering ada tetapi tidak wajib, sedangkan pupil hampir selalu digambar besar
- Untuk membuat mata tampak berkilau, diperlukan pantulan cahaya di dalam mata
- Dengan persamaan pencahayaan yang ada, pantulan hanya muncul ketika matahari dan kamera berada di posisi tertentu
- Untuk mengatasinya, vektor normal permukaan dimodifikasi agar peluang munculnya pantulan matahari lebih tinggi
- Selain itu, environment mapping juga digunakan
- Dalam game, teknik ini biasanya dipakai untuk menyederhanakan pantulan lingkungan nyata demi optimasi
- Di sini, dunia sebenarnya nyaris sepenuhnya putih, tetapi tekstur dipakai untuk menambahkan detail palsu
- Bagian putih mata dan pupil diberi pantulan yang jauh lebih kompleks daripada dunia kosong di sekitarnya
- Beberapa sumber cahaya palsu
- Gradien yang meniru tanah gelap dan langit biru
Post-processing dan gaya visual
- Nuansa akhir dan kualitas gambar dipoles lewat post-processing
- Post-processing yang digunakan adalah sebagai berikut
- Color grading
- Koreksi gamma
- Vignette ringan
- Filter FXAA 2-pass untuk mengurangi aliasing
- Beberapa efek seperti efek bintang di mata atau efek layar ending juga diimplementasikan pada tahap post-processing
- Efek-efek ini murni 2D dan tidak ada di dunia 3D
- Mereka sempat bereksperimen dengan gaya kartun lama
- Deteksi outline agar terlihat seperti gambar tangan
- Rendering hitam-putih
- Grain dan noise
- Setelah diskusi, eksperimen ini ditinggalkan dan fokus dialihkan ke tampilan yang lebih bersih dan modern
Kompresi Crinkler
- Ide intinya adalah bukan menyimpan data, melainkan menyimpan kode yang menghasilkan data itu
- Musik menyimpan daftar not yang harus dimainkan dan daftar instruksi untuk tiap instrumen
- Crinkler adalah alat kompresi yang dirancang untuk demoscene dan intro 1kB~8kB
- Karena file executable harus bisa mengekstrak dirinya sendiri, Crinkler menyertakan sedikit kode assembly yang dapat membuka sisa file executable
- Crinkler memprioritaskan optimasi ukuran
- Algoritme kompresinya memakan waktu
- Proses dekompresinya relatif lambat
- Menggunakan ratusan MB RAM
- Namun Crinkler saja tidak cukup, dan diperlukan minimisasi tambahan agar kode sumber shader 42kB bisa dimasukkan ke dalam file executable
Peningkatan Shader Minifier
- Karena kode sumber shader dimasukkan ke dalam biner akhir, ukurannya harus dibuat sekecil mungkin
- Minimisasi manual memang mungkin, tetapi akan menimbulkan masalah pemeliharaan dan iterasi cepat
- Shader Minifier adalah alat minimisasi shader yang dikembangkan sejak 2011
- Alat ini menghapus spasi dan komentar, memendekkan nama variabel, serta melakukan lebih banyak transformasi
- Intro 8kB memuat jauh lebih banyak kode daripada 4kB, sehingga muncul masalah baru, dan pekerjaan demo sempat dihentikan selama sebulan untuk menambahkan fitur yang dibutuhkan
- Untuk minimisasi yang baik, yang dibutuhkan bukan sekadar minifier sederhana, tetapi source-to-source compiler mirip Closure Compiler
- Transformasi yang dilakukan Shader Minifier meliputi
- Mengganti nama variabel dan fungsi
- Inlining variabel
- Evaluasi ekspresi aritmetika konstan
- Inlining fungsi
- Menghapus dead code
- Menggabungkan deklarasi
- Mengurangi ukuran kode saja tidak cukup; output juga harus ramah kompresi
- Beberapa transformasi memang mengecilkan kode, tetapi justru bisa memperbesar ukuran setelah dikompresi
- Selama pengembangan demo yang berulang, ukuran setelah kompresi harus terus dicek
- Peningkatan baru pada Shader Minifier menghemat sekitar 600 byte dalam biner terkompresi
- Pada akhirnya, kode shader 42kB masuk ke sekitar 5kB setelah diminimalkan dan dikompresi
- Ruang sisanya dipakai untuk musik dan kode C++
Hasil yang dibangun di atas karya orang lain
- Demo ini dibuat di atas karya orang lain seperti teknik raymarching, software pembuat musik, dan algoritme kompresi
- Mereka berharap fitur baru yang ditambahkan ke Shader Minifier akan membantu membuat demo yang lebih baik di masa depan
- Kategori 8kB menawarkan lebih banyak kemungkinan dibanding 4kB, dan ada harapan agar kategori ini menjadi lebih populer
- Sebagai perbandingan, teks aslinya sendiri berukuran sekitar 21.000 karakter, yang berarti akan membutuhkan 21kB jika disimpan apa adanya
1 komentar
Opini Hacker News
Saya pembuat film asli yang menjadi inspirasi film ini: https://www.youtube.com/watch?v=khWXdkryBE4
Versi aslinya saja, hanya file Blender, SVG, dan audio, sudah berukuran MB, jadi sangat mengesankan bahwa remake-nya bisa muat dalam 8kB
Senang melihat lisensi Creative Commons ternyata benar-benar berguna, hanya saja akan lebih bagus kalau mereka memakai karakter landak dan melodi audio yang sama
Sloot hidup kembali!!!
https://en.m.wikipedia.org/wiki/Sloot_Digital_Coding_System
Kumpulkan banyak demoscener, tunjukkan filmnya, lalu kurung mereka beberapa waktu di ruangan yang ada komputernya
Ini bekerja lebih baik kalau ada layar besar, sistem suara besar, bir, dan junk food; setelah itu tinggal ambil file executable hasilnya
aInterpreter yang ditulis dengan Rust demi performa akan mengevaluasi perintah
adan mencetak payload tertentu yang disertakan saat runtime ke STDOUTBenar-benar nasib sial yang kejam bagi semua orang
Mereka mungkin tidak memahami bahwa a) itu fungsi satu arah dan b) sekalipun bukan satu arah, banyak input bisa dipetakan ke hash yang sama
Video demoscene cukup menarik, tetapi sangat kurang dikenal
https://www.youtube.com/playlist?list=PLRQwR4-_0PR9HBI_GZs1nTn7q5LTkGeCN
Akan bagus kalau ada kanal yang menguraikan bagian dalamnya dengan visual yang bagus, seperti retro game mechanics
Pada masa belum ada video, kita harus menunggu cukup lama proses dekompresi dan pemrosesan sebelum akhirnya bisa terkesan atau kecewa
Dulu saya sering menonton demo saat istirahat, dan itu menjadi latar yang sempurna untuk kondisi mental saya waktu itu
https://en.wikipedia.org/wiki/.kkrieger
Lebih jauh lagi, seberapa kecil kita bisa membuat dunia yang terdiri dari agen-agen yang saling cerdas?
Tambahan: untuk yang memberi downvote, kalian tidak bermimpi? Di depan ada banyak hal yang benar-benar gila dan fantastis menanti
Saya tahu teknologi di baliknya cukup berbeda, tetapi ini mengingatkan saya pada .kkrieger dulu. Seluruh 3D FPS dikompresi menjadi 96k, dan itu benar-benar keren
https://en.m.wikipedia.org/wiki/.kkrieger
Setelah banyak menonton demoscene dan membaca cara pembuatannya, kita mulai memahami batasannya, dan menjadi jelas bahwa unsur seperti domba, terutama penampang kerucut pada kakinya, bisa diekspresikan dengan persamaan yang sangat terkompresi dan dianimasikan dengan cara serupa
Namun setahu saya kebanyakan demo mengandalkan GPU dan kemampuan akselerasi 3D yang kuat, sedangkan demo 2D bergaya anime Jepang tampaknya jarang atau hampir tidak ada dalam ukuran kecil
Apakah animasi 3D memang lebih mudah dalam praktiknya?
Sebagai tambahan, “mouton” berarti “domba” dalam bahasa Prancis, dan dari situlah “mutton” berasal
Sebaliknya, cara ‘matematis’ untuk menyimpan animasi bergaya 2D kurang lebih hanya menyimpan kontur sebagai kurva SVG, lalu memakai algoritma pengisian ruang untuk pewarnaan area
Dengan perhitungan kasar saja, satu busur kurva atau satu garis bisa memakan ruang penyimpanan sebanyak deskripsi seluruh volume geometri, dan untuk menyimpan animasi kurva-kurva itu dibutuhkan jauh lebih banyak ruang dibanding matriks transformasi kecil untuk volume 3D
Kompleksitas algoritma rendering juga tampaknya akan meningkat, baik dalam kompleksitas algoritme aktual maupun kompleksitas ruang
Catatan: menyimpan banyak bitmap lalu memutarnya seperti flipbook pun bisa diklaim ‘matematis’ jika memakai algoritma dekompresi prosedural yang menghasilkan frame penuh dari delta
Namun saya tidak melihat pendekatan seperti itu ada, dan kebutuhan ruangnya akan sangat besar dibanding deskripsi volume 3D
Ini sedikit lebih besar dari 8kB, tetapi jika Anda suka animasi tentang domba yang secara tak terduga gelap, saya merekomendasikan open movie Cosmos Laundromat dari Blender Foundation
Film-film yayasan ini selalu terasa anehnya gelap untuk ukuran demo teknologi, dan menurut saya karya ini khususnya sangat berhasil
[0] https://www.youtube.com/watch?v=Y-rmzh0PI3c
Sebagai peringatan dulu, filmnya berakhir dengan “to be continued”, dan halaman Wikipedia menuliskan seperti ini:
“Film ini awalnya dimaksudkan sebagai titik awal untuk sebuah film panjang. Sekuel pendeknya sudah memiliki naskah dan desain, tetapi tidak pernah masuk produksi. Pada 2020, [pembuatnya] mengumumkan bahwa satu film ini akan menjadi keseluruhan proyek tersebut”
Kalau tidak ingin kecewa karena tidak akan pernah melihat akhir dari konsep yang menarik ini, mungkin lebih baik dilewati
Ini berguna saat bereksperimen dengan HDR di DaVinci Resolve
[1] https://opencontent.netflix.com/#h.uyzoa2bivz2j
8KB adalah salah satu kategori di demoscene. Di Pouet ada indeks yang merapikan karya-karya seperti ini dengan baik
0. https://www.pouet.net/prodlist.php?type%5B%5D=8k&page=1
Razor 1911. Nostalgia murni
Banyak kenangan indah dari puluhan tahun lalu muncul kembali :-)
Benar-benar menakjubkan, dan saya suka bagaimana dalam kondisi penuh batasan pun ceritanya bisa selucu dan sekreatif ini. Sungguh mengesankan
Ingin mendengar lebih banyak detail teknis tentang trik dan penghematan seperti apa yang mereka lakukan untuk memangkas byte
Dalam commit ini (https://github.com/ctrl-alt-test/mouton/commit/79d2d1eab7a222b434b7041d8fc9bce4e60524f8), mereka menghapus optimasi performa dan menghemat banyak byte
Awalnya mereka ingin mempertahankannya, tetapi byte-nya tidak cukup, dan mereka menyadari bahwa optimasi itu tidak diperlukan pada GPU yang relatif modern
Lucu sekaligus benar-benar mencengangkan. Akhirnya saya menonton film yang ending-nya tidak bisa saya tebak