- Game Boy Color üzerinde gerçek zamanlı 3D gölgelendirme uygulayan bir proje; oyuncu ışığın yörüngesini kontrol ederken nesneyi döndürebiliyor
- Normalize vektörler ve Lambert gölgelendirmesi (
dot product) hesabını temel alıyor; işlemleri basitleştirmek için küresel koordinat sistemi kullanılıyor
- Çarpma komutu olmayan SM83 CPU kısıtlarını aşmak için log dönüşümü ve lookup table'lar kullanılarak işlemler 8 bit hassasiyetle yürütülüyor
- Kendi kendini değiştiren kod (self-modifying code) ile yaklaşık %10 performans artışı sağlanıyor ve kare başına 15 tile render ediliyor
- Yapay zeka ile kod üretme denemeleri büyük ölçüde başarısız olmuş; çekirdek algoritma ve shader'lar elle yazılmış kodla tamamlanmış
Proje özeti
- Game Boy Color'da gerçek zamanlı görüntü render eden bir oyun geliştirildi
- Oyuncu, yörünge biçimindeki bir ışığı kontrol ederken nesneyi döndürüyor
- Tüm kod GitHub deposunda (nukep/gbshader) açık olarak yayımlandı
3D üretim süreci
- Başlangıçtaki lookdev çalışması için Blender kullanıldı; görsel sonuç tatmin edici bulununca projeye devam edildi
- Cryptomatte ve özel shader'larla normal map üretildi
- Teapot modeli için kamera döndürülerek PNG dizisi halinde normal map çıktı alındı
- Game Boy Color modelinin ekran bölümü ayrı bir sahnede render edilip sonradan birleştirildi
Matematiksel temel
- Normal map, her pikselin normal vektörünü kodlayan bir vektör alanı olarak kullanılıyor
- Lambert gölgelendirmesi,
v = N·L biçimindeki bir iç çarpımla (dot product) hesaplanıyor
- Küresel koordinatlara dönüştürülerek
v = sinNθ sinLθ cos(Nφ−Lφ) + cosNθ cosLθ biçiminde sadeleştiriliyor
- Tüm vektörlerde yarıçap
r=1 varsayılarak işlem yükü azaltılıyor
Game Boy üzerindeki uygulama
- Lθ (ışığın dikey açısı) sabit tutuluyor, yalnızca Lφ (ışığın dönme açısı) oyuncu tarafından kontrol ediliyor
- ROM'da her piksel
(Nφ, log(m), b) biçiminde saklanıyor
- Çarpma komutunun olmaması sorununu çözmek için log dönüşümü ve lookup table'lar (
log, pow) kullanılıyor
- Negatif işlemleri desteklemek için işaret (
sign) biti üst bitlerde saklanıyor
- Tüm skaler değerler -1.0 ile +1.0 aralığında 8 bit kesirler olarak ifade ediliyor
- Toplama lineer uzayda, çarpma ise log uzayında yapılıyor
- Payda olarak 127 kullanılarak hem +1 hem -1 temsil edilebiliyor
cos_log ve temel işlemler
cos_log, log(cos x) biçiminde birleşik bir lookup olup çarpma işlemini logaritmik toplamaya dönüştürüyor
- Piksel başına işlem miktarı
- 1 çıkarma, 1
cos_log erişimi, 1 toplama, 1 pow erişimi, 1 toplama
- Toplamda 3 toplama/çıkarma ve 2 lookup yapılıyor
Performans
- Kare başına 15 tile işleniyor; bazı boş satırlar daha hızlı hesaplanabiliyor
- Piksel başına yaklaşık 130 cycle, boş satırlarda ise 3 cycle gerekiyor
- CPU'nun yaklaşık %89'u shader hesaplamaları için, kalanı giriş ve I/O işlemleri için kullanılıyor
Kendi kendini değiştiren kod (Self-Modifying Code)
- Kare başına yaklaşık 960 piksel işleyen çekirdek döngüyü optimize etmek için komutların kendisi değiştiriliyor
- Değişken yüklemek yerine sabitler doğrudan koda gömülerek daha hızlı işlem yapılıyor
- Örnek:
sub a, 8, sub a, variable'dan 12 cycle daha hızlı
- Toplamda yaklaşık 11.520 cycle (%10) tasarruf sağlanıyor
Yapay zeka kullanım denemeleri
- Tüm projenin %95'i elle yazıldı
- Yapay zeka, Game Boy assembly'si (SM83) yazmakta zorlandı
- Yapay zekanın kullanıldığı alanlar
- Python: OpenEXR katmanlarını okuma
- Blender: sahne otomasyon betikleri
- SM83: bazı işlev parçacıkları (ör. VRAM DMA)
- Başarısız denemeler
- Yapay zekayla shader assembly kodu üretme girişimi → verimsiz ve çok hatalı sonuçlar
- Claude Sonnet 4 modeliyle sözde koddan assembly üretme denemesi
- Kısmen çalıştı ancak yavaştı; ayrıca Z80 ile SM83'ü karıştırma gibi hatalar yaptı
- Nihai kod sonunda tamamen elle yeniden yazıldı
Sonuç ve çıkarımlar
- Yapay zeka basit betiklerde yararlı olsa da, doğruluk ve doğrulama şart
- OpenEXR işleme kodunda yapay zeka kanal sıralama hatası (BGR vs RGB) oluşturarak haftalar süren bir bug'a yol açtı
- Deneyim, “yapay zeka kullanırken en önemli şey doğrulamadır” dersini öne çıkarıyor
- Proje, eski donanımın sınırlarını aşan deneysel bir shader uygulaması örneği olarak değerlendiriliyor
1 yorum
Hacker News yorumları
HN'de gerçekten hacker ruhu taşıyan bir yazı görmek sevindirici.
Ortaya çıkan sonuç gerçekten harika. Benim anladığım kadarıyla bu, “3D gibi görünen ama aslında 2D normal map önceden render edilip üzerine ışıklandırma efektleri uygulanmış bir shader”
Kareler bu GitHub bağlantısında yer alıyor
3D üçgen işleme kısmı basit tutulur ve maliyetli ışıklandırma shader'ları 2D görüntü üzerinde yalnızca bir kez çalıştırıldığı için verimlidir
Shader açısından bakıldığında girdi 3D vektörse bu bir 3D shader'dır. 3D rasterizer olup olmaması ayrı bir konudur
Modern 3D oyunlar da bu yöntemi çeşitli şekillerde kullanır. Farklı açılardan önceden render edilmiş modellerin kullanıldığı imposter tekniği de gerçek 3D motorlarda kullanılan resmi bir tekniktir
Ancak bu kez bunun Game Boy Color'da çalışıyor olması şaşırtıcı
Merhaba, yazının yazarı benim. Bunun burada paylaşıldığını duydum ve hesap açtım. Paylaştığınız için teşekkürler
Environment map kullanarak daha da basitleştiren denemeler de yapıyorum; Bsky'de paylaştığım bağlantıdan görebilirsiniz
Gerçekten ilginç bir proje. Eskiden C64 assembly kodlama yaptığım günleri hatırlattı.
O zaman da çarpma komutu olmadığı için donanım kısıtlarını aşmanın yaratıcı yollarını bulmak gerekiyordu
AI kullanmayı deneme girişimiydi ama sonuçta başarısız bir deney oldu.
Sektör AI konuşmalarıyla çalkalanırken bunu bizzat deneyimlemek istedim ve generative AI kullanılıp kullanılmadığını şeffaf biçimde açıklamanın önemli olduğunu düşünüyorum.
Gizlemek güveni zedeler; açıklamak ise farklı düşünen insanlarla da açık bir diyalog kurmayı mümkün kılar
Sadece bu süreci kayda geçirmek istemiştim
Bu GBC shader'ı, “bütün hesaplamalar kısıtlar altında yapılan birer yaklaştırmadır” gerçeğini gösteriyor.
Çarpma işlemi tablo bakışı ve toplamayla değiştirilmiş, hassasiyet ise gözle görülen sonuca göre ayarlanmış
Gerçekten etkileyici. Özellikle bunun gerçek Game Boy Color donanımında çalışıyor olması şaşırtıcı.
Bazen karta güçlü bir işlemci koyup GBC'yi yalnızca basit bir terminal gibi kullananlar oluyor, ama bu öyle bir hack değil
Açıkçası Nintendo'nun GBC ya da GBA'yı yeniden piyasaya sürmesini isterdim.
İçinde birkaç oyun bulunan kartuş biçiminde satsalar hemen alırdım
Ama bugünlerde aynı form faktördeki Android el konsolları daha pratik.
Bende de bir Game Boy koleksiyonu var ama artık emülatörler çok daha kullanışlı geliyor
Nintendo yeniden yapsa bile bunun kadar iyi olacağını sanmıyorum
İşte HN'in var olma nedeni tam da böyle yazılar.
Eski teknoloji dergilerini karıştırdığım günlerdeki keyfi yeniden hissettiriyor
Bu yazar iyi anlamda çılgın bir dahi