1 puan yazan GN⁺ 4 시간 전 | 1 yorum | WhatsApp'ta paylaş
  • Catlantean 3D, 1990'ların başındaki PC oyun tarzı kısıtlarla tam teşekküllü bir birinci şahıs nişancı yapmayı amaçlayan bir yan proje ve 320x240 çözünürlük ile 256 renk paleti tabanlı renderlemeyi hedefliyor
  • Renderleyici yalnızca palet indeksleriyle çalıştığı için, mesafeye bağlı kararma efekti vermek amacıyla 32 kademeli bir colormap önceden hesaplanıyor ve çalışma sırasında O(1) erişimle daha koyu renk seçiliyor
  • Varlık üretimi; Blender tabanlı önceden renderlenmiş sprite'lar, elle çizilmiş sprite ve dokular, Python betikleriyle üretilen prosedürel dokular olarak üçe ayrılıyor
  • Elle çizilmiş HUD ve piksel düzeyinde ölçek kuralları, düşük çözünürlükte netlik ve okunabilirliği korumak için temel kısıtlar; dünya içindeki 1 birim 64 piksele göre ayarlanıyor
  • Tiled yerine kendi harita düzenleyicisini geliştiriyor ve çıkıştan sonra oyunculara da aynı düzenleyiciyi sunmayı planlıyor; oyunun kaynak kodu da GitHub'da açık kaynak olarak yayımlanacak

Projenin hedefleri ve kısıtları

  • Catlantean 3D, bir yılı aşkın süredir boş zamanlarda yavaş yavaş geliştirilen bir yan proje ve hedef gelecek yıl Steam'de çıkmak
  • Amaç, 1990'ların başında yaygın olan tekniklerle tamamlanıp yayımlanabilecek bir birinci şahıs nişancı yapmak
  • Modern derleyicilere ve platform soyutlama katmanlarına izin veriliyor, ancak bu katman; pikseller yazılan bir framebuffer, klavye ve fare girdisi, örnekler yazılan bir ses tamponu ve dosya sistemi I/O'su ile sınırlı tutuluyor
  • Oyun, varlıklar dahil her şeyin sıfırdan yapılmasını gerektiriyor; renderleme ve ses miksajı da tamamen elle uygulanıyor
  • Hedef çözünürlük 320x240 ve ekrandaki her piksel yalnızca 256 renkten birini kullanabiliyor
  • Oyun mantığı, deterministik davranışı garanti etmek için fixed-point kullanıyor; renderleme ise determinizm daha az önemli olduğu için floating-point kullanıyor
  • Ortaya çıkacak şey bir teknik demo değil, keyifle oynanabilecek tamamlanmış bir oyun olmalı ve yapay zeka çıktıları kullanılmıyor
  • Gösterilen tüm çalışmalar devam eden işler ve büyük ölçüde değişebilir

Palet renderleme

  • VGA grafikleri

    • VGA donanımındaki Mode 13h, 320x200 çözünürlükte 256 renkli bir grafik moduydu ve bir nesil PC oyununu tanımlayan ünlü bir moddu
    • Programcı açısından Mode 13h, her pikselin 256 renkli paletten bir indeks olduğu 1 baytlık doğrusal bir framebuffer sunuyordu
    • Piksel çizmek için belirli bir adrese 1 bayt yazmak yeterliydi; shader ya da VRAM gibi kavramlarla uğraşmak gerekmiyordu
    • Modern oyun varlıkları görsellerde milyonlarca renk kullanabiliyor, ancak 256 renk sınırında her renk seçimi dikkatli ve bilinçli olmak zorunda
    • Doom ve Duke Nukem gibi oyunlar, teknik sınırlamaların grafikleri keskin ve net kıldığı örnekler olarak veriliyor
    • Catlantean 3D bu hissi yeniden üretmeye çalışıyor, ancak 320x200 yerine VGA Mode-X'e daha yakın olan 320x240'ı seçiyor
    • 320x200'ü 4:3 ekranda göstermek kare olmayan pikseller oluşturuyor; bu yaklaşım daha otantik olsa da kişisel tercih nedeniyle kaçınılıyor
  • Palet

    • Palet 768 bayttan başlıyor ve pek çok deneme-yanılma ile yineleme sonunda seçiliyor
    • Palette şeffaf renk için parlak pembe, saf beyaz ve saf siyah için birer renk ayrılmış durumda
    • Kan efekti için çok sayıda kırmızı tonuna ihtiyaç duyulmuş; ayrıca kırmızı, yeşil ve mavi anahtarlar ile renk ayrımlı kapılar için yeşil ve mavi tonları da gerekiyor
    • Arka plan, kedi tapınması nedeniyle antik Mısır'ı andıran parodi bir diyar olan Catlantis'te geçtiği için bol miktarda sarı ve kahverengi çöl tonu gerekiyor
    • Catlantis'in sibernetik köpek insanlar tarafından işgal edilmiş olması nedeniyle, teknolojik tesisleri göstermek için de çok sayıda gri tona ihtiyaç var
    • Grinin tekdüzeliğini kırmak ve karardığında sıcak alternatif tonlar sağlamak için bej tonları da ekleniyor
    • Kalan renkler, doku üretim sürecinde ihtiyaç oldukça doldurulmuş ve “göze doğru görünmesi” gibi öznel bir ölçüte göre seçilmiş
    • Palet tek seferde tamamlanmamış; varlık üretimi, test ve yineleme boyunca sürekli ayarlanmış

colormap ve ışıklandırma

  • Raycaster yapısı

    • Catlantean 3D geleneksel bir raycaster; harita tamamen aynı boyuttaki karolardan oluşuyor
    • Bazı karolar duvar, diğerleri ise yalnızca zemin ve tavana sahip boş alanlar
    • Renderleyici, ekranın her sütunu için DDA algoritmasını kullanarak karo haritasında ilerliyor ve harita geometrisine çarptığı noktayı buluyor
    • Çarpışma konumuna göre uygun doku koordinatından örneklenen duvar sütununu ekrana çiziyor
    • Zemin ve tavan daha sonra yatay scanline'larla renderlenerek ekranın kalanını dolduruyor
    • Oyun dünyasını yalnızca paletle renderlemek görüntüyü düz ve etkisiz bırakıyor
    • Oyuncudan uzaklaştıkça ışığın azalması ve bir karo yüzünün diğerinden biraz daha koyu olması derinlik hissi yaratıyor
  • Palet tabanlı karartma

    • Modern donanım hızlandırmalı renderleyicilerde, vertex mesafesine göre renk vektörüne floating-point katsayı çarparak shader içinde kolayca karartma yapılabiliyor
    • Palet renderleyici renk kavramıyla değil, yalnızca palet indeksleriyle çalıştığından belirli bir rengin daha koyu versiyonunu bulmak için tüm paleti taramak gerekiyor
    • Her renderlenen piksel için 256 renkli paleti taramak çok yavaş olacağı için, çalışma öncesinde önceden hesaplama ile hızlı renk erişimi hazırlanıyor
    • Palet tek bir satır gibi düşünülüp 32 parlaklık seviyesi seçildiğinde, her renk için orijinal hariç 31 daha koyu varyant gerekiyor
    • Her rengin RGB değeri ve parlaklık indeksiyle hedef koyu renk hesaplanıyor, ancak bu renk gerçek palette bulunmayabiliyor
    • Hedef renge en yakın palet rengini bulmak için palet taranarak colormap oluşturuluyor
    • İlk başta Öklid mesafesi kullanılmış, ancak birçok renk griye kayma eğilimi göstermiş ve koyu tonlar soğuk, cansız görünmüş
    • Sonrasında renkler Oklab renk uzayına dönüştürülmüş ve insanın renk farkını algılayışına daha yakın bir algısal mesafe formülü kullanılmış
    • Ayrıca renkler koyulaştıkça biraz daha sıcak tonlara kaydıran, piksel sanatta kullanılan hue shifting yaklaşımı da uygulanmış
    • colormap, her rengin parlaklık durumunu gösteren palet indekslerinden oluşan iki boyutlu bir matris; yine de yalnızca palet renkleri kullanılabildiğinden geçişler kusursuz değil
  • Çalışma maliyetini azaltma

    • Mesafeye bağlı colormap satır indeksi belirlendiğinde, ilgili parlaklık seviyesi satırındaki N'inci öğe seçilerek kararmış N renginin palet indeksi elde ediliyor
    • Bu yöntem, çalışma sırasında daha koyu renk seçimini O(1) erişimle yapıyor
    • Duvar renderlemesinde, duvar sütunu tamamen dikey olduğundan ve sütundaki tüm pikseller kameraya aynı uzaklıkta bulunduğundan ekran sütunu başına yalnızca bir kez colormap satır indeksi hesaplanıyor
    • Zemin renderlemesinde, yatay satırdaki tüm pikseller aynı uzaklığa sahip olduğundan ekran satırı başına bir kez hesap yapmak yeterli
    • Sprite'lar, tüm pikselleri kameraya aynı uzaklıkta olan düz billboard'lar olduğu için görünen her sprite için yalnızca bir kez hesap yapılıyor
    • Duvarlar için 320 kez, zemin için en fazla 240 kez ve görünen sprite'ların her biri için birer kez hesaplama yetiyor; raycasting ayrıca görünmeyen nesneleri ayıklamayı ücretsiz sağlıyor
    • Doom ve başka birçok oyun da benzer bir yaklaşım kullanıyordu

Varlık üretim yöntemi

  • Üç varlık kategorisi

    • Catlantean 3D'nin dokuları ve sprite'ları üç kategoriye ayrılıyor
    • Birinci kategori, Blender'da yapılmış 3D modellerin doku olarak renderlenmesiyle elde edilen önceden renderlenmiş sprite'lar
    • İkinci kategori, elle çizilmiş sprite'lar ve dokular
    • Üçüncü kategori ise elle çizilmiş sanatı birleştiren özel Python betikleriyle oluşturulan prosedürel dokular
  • Önceden renderlenmiş sprite'lar

    • Karmaşık animasyonlu sprite'larda birçok kareyi düzenlemek gerektiği için yineleme zor ve zaman alıcı oluyor
    • Daha verimli yöntem, Blender'da 3D model oluşturup rig ve animasyonu yapmak, ardından Blender Python API kullanan bir betikle çok sayıda doku renderlemek
    • Değişiklikler model üzerinde yapılıyor ve gerisini renderleme betiği hallettiği için yineleme süresi ciddi biçimde kısalıyor
    • Başlıca zorluk, renderlenen sprite'ların çok bulanık ve soluk görünmesiydi
    • Yüksek çözünürlükte renderleyip filtreleme ile küçültmek bazı durumlarda ayrıntının filtrede kaybolmasına ve kenar netliğinin bozulmasına yol açtığı için sonuçlar karışıktı
    • En etkili ve yeniden kullanılabilir yöntem, Blender'ın compositing araçlarıyla uygun kontrast ve keskinliği elde etmek oldu
    • Görsel hazır olduğunda özel bir Python betiği palet kuantizasyonu yaparak motorun kullandığı 1 bayt piksel görsellerini üretiyor
    • Betik, kaynak görseldeki her piksel için Oklab ölçütüne göre algısal olarak en yakın palet rengini buluyor ve o rengin indeksini piksel değeri olarak kullanıyor
    • İndeks dizisi ve boyut bilgisi, oyunda kullanılan basit TEX biçimine paketleniyor
    • Düşman sprite'ları birden fazla animasyona sahip olabiliyor ve her animasyon, sprite'ın bakabileceği 8 yön için kareler içermeli
    • Python betiği her animasyon için sprite'ı döndürüp tüm kareleri renderliyor, ardından tekrar döndürerek süreci sürdürüyor
    • Sprite dosya adları, sprite adı, hareket adı, yön ve kare indeksini gösteren bir kurala göre kaydediliyor
    • Renderlenmiş sprite'lar depoda tutulmuyor, .gitignore ile hariç bırakılıyor; başka bir bilgisayarda derleme betiği tüm modelleri renderleyip sprite'ları üretiyor
    • RTX 3070 üzerinde yaklaşık 15 modelin işlenmesi yaklaşık 10 saniye sürüyor
  • Elle çizilmiş sprite'lar ve dokular

    • Geliştirmenin başlarında durum çubuğundaki yüz için, kedi Vilko'nun dokusunu taşıyan kedi biçimli bir kafa Blender'da yapılmış
    • Bu sonuç tembelce ve düşük emekli görünmüş, duyguyu iyi aktaramamış ve atmosfer geri bildirimlerinde insanların ilk dikkat çektiği nokta olmuş
    • Bazı öğelerin mutlaka elle çizilmesi gerekiyor ve animasyonlu elle çizilmiş sürümün çok daha iyi olduğuna karar verilmiş
    • Sprite boyutu nedeniyle her pikselin kasıtlı olması gerekiyor; bunu Blender renderleyicisine bırakamazsınız
    • Aynı mantık çoğu pickup öğesi için de geçerli olmuş; önceki önceden renderlenmiş sonuçlar küçük ölçekte Blender compositing aracının istikrarlı biçimde iyi sonuç vermemesi nedeniyle yetersiz kalmış
    • İnsan eli değdikten sonra pickup öğelerinin netliği ve okunabilirliği büyük ölçüde artmış
    • Sprite çözünürlüğünü basitçe artırmak, oyun rasterizer'ı bunu ölçekleyebilse de piksel ölçeği tutarsız olacağı için iyi sonuç vermiyor
    • Aynı ekran satırında ya da sütununda ileri geri hareket ederken piksel boyutunun aynı kalmasını bilinçsizce beklersiniz; bu yüzden sprite'lar arasında piksel ölçeği değişince görüntü tuhaflaşıyor
    • Catlantean 3D dünyasında 1 birim 64 piksele karşılık geliyor ve tüm sprite'lar bu ölçeğe göre hazırlanıyor
    • Dünya biriminin dörtte biri yüksekliğindeki bir sprite'ın yüksekliği 64/4=16 piksel olmalı

HUD ve prosedürel üretim hattı

  • HUD

    • HUD ve bileşenlerinin neredeyse tamamı elle yerleştiriliyor ve çiziliyor
    • Ekranın altındaki durum çubuğu, çeşitli geçiş panelleri ve ekranlar ile yazı tipleri, elle çizilmiş HUD kategorisine giriyor
    • Tüm öğeleri doğrudan boyamak yerine Affinity Photo'nun katman efektleri ve compositing özelliklerinden yoğun biçimde yararlanılıyor
    • Kullanılan efektler arasında düz yüzeylere 3D hissi veren emboss, kirli doku için noise üretimi ve overlay, renk kaplaması, blending modları ve glow efektleri bulunuyor
    • HUD öğeleri sık sık tekrar düzenlendiği için, katman tabanlı yeniden yerleştirme kolaylığı da önemli
    • Genel olarak önce Affinity Photo'da truecolor olarak çalışılıyor; birçok öğe, tek renkli dikdörtgenlere özel efektler ve blending uygulanmasından oluşuyor
    • Affinity Photo'dan dışa aktarılan görseller, muhtemelen anti-aliasing ile ilgili garip artefaktlar içeriyordu ve bunları güvenilir biçimde kapatmak mümkün olmadı
    • Bu nedenle piksel hassasiyetli işler için uygun değildi; Aseprite'te piksel mükemmelliğinde metin, görsel parçalama ve daha keskin kenarların elle rötuşlanması gibi ek işlemler yapıldı
  • Prosedürel üretilen dokular

    • Bazı dokular doğrudan çizilecek kadar basit ya da belirgin, ancak birçok doku temel malzeme üzerinde ortak aşınma, kir ve yüzey ayrıntısı varyasyonlarını paylaşıyor
    • Her varyasyonu elle çizmek sıkıcı ve tutarsız olduğundan Python betikleriyle üretiliyor
    • Üretim hattı; yüzey relief'ini tanımlayan bir heightmap, varyasyon için bir noise map, kir ve aşınma için bir grime map, iki temel renk ve bir brightmap'i girdi olarak alıyor
    • Heightmap aslında bir normal map üretmek için kullanılıyor ve normal map basit ışık ve gölgeyi bake etmekte kullanılıyor
    • Brightmap, diğer parametrelerden bağımsız olarak rengini koruyacak bölgeleri belirliyor
    • Betik son dokuyu oluşturuyor ve palet kuantizasyonunu da yaparak onu doğrudan motorda kullanılabilir hale getiriyor
    • Böylece doku düzenlemek, pikselleri yeniden çizmekten çok parametreleri ayarlama işine dönüşüyor; bu da tek başına çalışırken ciddi zaman kazandırıyor

Gibs ve önceden renderlenmiş efektler

  • Gibs

    • Düşmana point-blank shotgun blast ya da explosion gibi aşırı hasar uygulandığında genellikle gibbing gerçekleşiyor
    • Büyük hasarın etkisini hissettirmek için düşmanın kanlı parçalara ayrılarak patladığı animasyonlar kullanılıyor
    • Bu hat Python betikleri tarafından yürütülüyor; sprite, palet ve parametre kümesi alıp oyun verisine girecek animasyon karelerini üretiyor
    • İlk aşama olan Voronoi decomposition'da, sprite'ın opak gövdesinden rastgele K adet seed piksel seçiliyor ve tüm pikseller en yakın seed'e atanıyor
    • Ortaya çıkan her cell, uçuşan bir parçaya dönüşüyor
    • İkinci aşama olan wound bleeding'de, farklı parçalara komşu sınır pikseller derinliği 0 olan yara olarak işaretleniyor ve BFS içeri doğru yayılıp derinlik değerleri atıyor
    • Renderleme sırasında sınır yakınındaki pikseller, oyun paletinden türetilen bir ramp üzerinden kan rengine doğru karıştırılıyor; parçanın içine gidildikçe özgün sprite rengi daha çok korunuyor
    • Palet ramp seçimi parametreleştirilmiş durumda; böylece belirli düşmanlar için yeşil ya da mavi “kan” da kullanılabiliyor
    • Üçüncü aşama olan physics'te, her parçaya bir merkez noktası, sprite merkezinden dışa doğru rastgele saçılma hızı, dönme hızı, yerçekimi ve drag atanıyor
    • Çarpışma algılama yok, ancak parçalar zemine çarpınca duruyor; kaba ama yeterli bir sonuç veriyor
    • Parça sayısı, patlama kuvveti, yerçekimi, drag, saçılma ve yara derinliği parametrelerle ayarlanabiliyor
    • Göze hoş gelen seed'leri bulmak biraz deneme gerektiriyor ama animasyonu elle çizmekten daha hızlı
    • Aynı teknik, saksı, varil ve kasa gibi parçalanabilir çevre nesnelerinde de kullanılıyor
    • Önceden renderlenmiş animasyonlarda olduğu gibi gibs çıktıları da depoda tutulmuyor; checkout sonrası yeniden üretiliyor ve çalışma süresi ihmal edilebilir düzeyde
  • Önceden renderlenmiş parçacık sistemi

    • Parçacık efektlerinin çoğu Aseprite'te elle çiziliyor, ancak bazıları gibs ile aynı şekilde üretilip bake ediliyor
    • Python betiği simülasyonu çalıştırıp PNG kare dizileri oluşturuyor, ardından bunlar TEX'e kuantize ediliyor
    • Çalışma zamanında bir particle system yok; tüm efektler önceden bake edilerek yazılım rasterizer'ının olabildiğince hızlı renderlemesi sağlanıyor
    • Buradaki “particle” kelimesi biraz yanıltıcı; aslında gerçek parçacık simülasyonu yapılmıyor
    • Her kare, piksel başına bir radial energy field hesaplanıp birden fazla bağımsız katman toplanarak oluşturuluyor
    • Core, animasyon boyunca dışa doğru genişleyen yumuşak bir disk
    • Rays, core çevresindeki sivri ışık huzmeleri; sharpness ve length ayarlanabiliyor ve her ray'e RNG tabanlı uzunluk dalgalanması eklenerek düzensiz bir görünüm veriliyor
    • Ring, isteğe bağlı genişleyen bir shockwave; noise ise toplam enerjiye value noise çarparak temiz şekli daha pürüzlü ve düzensiz hale getiriyor
    • Birikmiş piksel başına enerji, betik parametrelerinde belirtilen palet ramp'ine göre kuantize ediliyor
    • Palet tasarımı gereği her satır açık tondan koyu tona giden bir gradyan gibi ele alındığından, blending ya da alpha hesabı olmadan yalnızca palet indeksi aritmetiğiyle pikseller karartılıyor
    • Belirli bir eşik üzerinde pikseller beyaza doğru itiliyor ve böylece white-hot core etkisi veriliyor
    • İsteğe bağlı olarak üzerine küçük sparkle'lar serpilebiliyor; bu haç biçimli parıltılar dışa doğru hareket ediyor ve kendi ömürleri boyunca sönüyor
    • Animasyonlar, explosion ya da teleport flash gibi büyüyüp kaybolan one-shot modunu ve ilk kareyle son karenin eşleştiği kesintisiz loop modunu destekliyor
    • Loop modu, plasma bolts ve energy projectiles gibi sürekli tekrar eden efektler için yararlı

Harita düzenleyici ve araç ekosistemi

  • Harita düzenleme ilk başta Tiled ile başlamış; genel olarak makul bir araç olsa da oyunun ihtiyaç duyduğu belirli özelliklerden yoksun kalmış
  • Tiled'da hücre bazında light level boyama, cell flags ve oyuna özgü property kavramı olmadığından, başlangıçta object properties aşırı kullanılarak bunun etrafından dolaşılmış
  • Tiled'ın JSON çıktısını motorun kullandığı ikili biçime dönüştüren bir Python betiği de gerekmiş; bu da aracın oyun gereksinimleriyle uyuşmazlığını telafi eden ek bir parça olmuş
  • Oyuncuların harita yapmak için Tiled kurması, arayüzünü öğrenmesi ve dönüştürme betiğini ayarlaması gerekiyorsa, bu yük düzenleyicinin fiilen kullanılma ihtimalini neredeyse ortadan kaldıracak kadar büyük
  • Kendi düzenleyicisi; light level boyamayı, cell flags'i ve oyunun bildiği tüm entity ile property türlerini yerel olarak destekliyor
  • Oyun çıktığında, oyuncular da geliştirme sırasında kullanılan aynı düzenleyiciyi alacak
  • Düzenleyici plug-and-play çalışıyor ve seviye doğrudan düzenleyiciden başlatılabiliyor
  • Araç çubuğu ikonlarının korkunç göründüğünün farkında ve tam da bu yüzden öyle bırakılıyor
  • Düzenleyici wxPython ile yapılmış; widget, event handling ve layout açısından tkinter'dan daha uygun bulunmuş
  • wxPython ile ortaya çıkan sonuç daha yerel görünüyor ve yineleme süreci hızlı ilerlemiş
  • MVP desenine dayalı yapı, UI mantığı ile harita verisini temiz biçimde ayırıyor; bu da harita formatı henüz stabil değilken ve iki taraf da sık sık değişirken önemli
  • Düzenleyicinin her parçası Python ile yazılmış değil; modelin büyük bölümü pybast kütüphanesine dayanıyor
  • pybast, pybind aracılığıyla motordaki iç Python binding'leri; oyun veri arşivini okuma, oyun dokularını okuma, entity koordinatları için fixed-point sınıfı ve serialization sağlıyor
  • Bu tercih, zaten C++ ile uygulanmış işlevleri Python'da yeniden yazmamak için yapılmış; motor ve araçlar küçük ama sıkı bağlı bir ekosistem oluşturuyor

Çıkış planı ve yayımlama biçimi

  • Catlantean 3D'nin 2027'nin ilk çeyreğinde yayımlanması bekleniyor
  • Şu anki odak; seviye tasarımı, düşman ve silah ekleme ile devam eden polish çalışmaları
  • Hedef fiyat aralığı 5 ila 8 dolar
  • Oyunun kaynak kodu GitHub'da açık kaynak olarak yayımlanacak
  • Grafikler, seviyeler, sesler ve müzik gibi gerçek veri arşivi ise oyunu satın alanlara verilecek
  • Süreçte şeffaflık, kalıcı güven inşa eden az sayıdaki unsurlardan biri olarak görülüyor
  • Bağımsız oyunlar AAA yapımların aksine daha küçük bir kitleye dayanıyor, ancak bu kitle projeyi takip etmeye, desteklemeye ve başkalarına anlatmaya daha istekli oluyor
  • Yapım sürecini göstermek, ortaya konan işe gerçekten önem verildiğini göstermenin en dürüst yollarından biri olarak sunuluyor

1 yorum

 
GN⁺ 4 시간 전
Hacker News görüşleri
  • Yazılım renderingi ile oynamak istiyorsanız, SDL2 ve C ile tüm platformlarda ana bellekteki ARGB8888 2D dizisini ekrana verimli şekilde basan, mümkün olan en kısa koda yakın bir örnek var: https://gist.github.com/CoryBloyd/6725bb78323bb1157ff8d4175d...
    320x200x8 bit paletli framebuffer'ı ARGB'ye dönüştürme işini kendiniz yapmanız gerekiyor ;)
    Paletli framebuffer ile neler yapılabileceğine dair ilham almak isterseniz http://www.effectgames.com/demos/canvascycle/ sitesinde Show Options'a tıklayabilir ya da ilgili sanatçının GDC konuşmasını izleyebilirsiniz: https://youtu.be/aMcJ1Jvtef0
    Ardından klasik Deluxe Paint IIe hissi istiyorsanız https://github.com/mriale/PyDPainter'ı, daha modern bir araç istiyorsanız https://www.aseprite.org/'i açabilirsiniz

    • En azından SDL3'te artık renderer veya texture gerekmiyor. SDL_GetWindowSurface ile yüzeyi alıp SDL_UpdateWindowSurface ile gösterebilirsiniz
      Kütüphaneyi anladığım kadarıyla bu, yazılım grafiğine en yakın yöntem ve SDL hâlâ çift tamponlamayı sizin yerinize yapıyor

    • Kesinlikle en temel yöntem bu. İç döngüde küçük bir optimizasyon yapmak istiyorsanız, piksel döngüsüne girmeden önce scanline offset'ini önceden hesaplayabilirsiniz:
      int s = y*screenRect.w;

      for (int x = 0; x < screenRect.w; x++) {
      pixels[s + x] = argb(255, frame>>3, y+frame, x+frame);
      }

    • Paylaşım için teşekkürler. Zaten popüler olan birkaç Quake fork'u var ama Planimeter, değişiklik eklemeyen Quake-VS2026 fork'unu dağıtıyor
      Ekip x64 build üzerinde çalışıyor; bunun için eski SciTech Multi-platform Graphics Library'yi (yalnızca x86) SDL3 ile değiştirmeleri gerekiyor. Alternatif olarak scitech-mgl'i x64'e port etmeleri gerekir ama bu pek olası görünmüyor ve en son bildiğim kadarıyla yazılım renderer'ı da çıkabilir durumdaydı
      Ama belki yazılım renderer'ı ve SDL_Texture ile korunabilir

  • Bu yazı Doom'dan çok ilham almış, ama asıl ray casting engine Doom'dan önceki oyunlara, özellikle de en bilineni Wolfenstein 3D'ye daha yakın
    Dikey duvarlar ve sabit zemin-tavan yükseklikleri kullanıyor. Wolf3D performans nedeniyle dokulu zemin ve tavana sahip değildi ama benzer başka oyunlarda bunlar vardı
    Doom ve yanlış hatırlamıyorsam Duke Nukem de çok daha esnek bir BSP engine kullanıyordu; duvarlar keyfi açılarla kesişebiliyor, zemin ve tavan yükseklikleri değişebiliyordu. Yine de bölümler hâlâ “2.5D” idi; yani tek bir bölüm içinde birden fazla kat yapılamıyor, örneğin hem altından hem üstünden geçilebilen bir köprü tasarlanamıyordu

    • Build engine BSP kullanmıyordu. Sektörler arası bağlantıları portal olarak ele alıyor, bu portallara göre clipping yapıyor ve duvarları 90 derece döndürülmüş yamuklar gibi rasterize ediyordu
      Bu sayede hareket eden trenler ya da dönen ışıklar gibi dinamik duvar geometrileri mümkün oluyordu; ayrıca aynı anda iki oda görünmüyorsa “room over room” düzenleri de yapılabiliyordu
      Blood ve Shadow Warrior'da daha “3D” hissi veren alanlar oluşturmak için, aynı şekilli sektörler yaratıp bir sektörün zeminini diğerinin tavanına bağlanan bir portal gibi kullanan bir workaround uygulanmıştı. Bu engine'in yerleşik özelliği değildi ama kaynak koda erişimi bile olmayan stüdyoların kendi başlarına yapabildiği kadar esnekti
      Duke Nukem 3D'nin ilk bölümü de birkaç Build hilesi kullanır. Örneğin sprite'lar kamerayı takip ederek dönmek yerine eksene hizalı olabilir ve çarpışmaya sahip olabilir; dolayısıyla her sprite'ı eksene hizalı bir dikdörtgen gibi ele alarak basit 3D geometri oluşturabilirsiniz. İlk bölümde bu, çıkış düğmesinden hemen önce iki bina arasındaki köprüyü yapmak için kullanılmıştı

    • Blake Stone ve Rise of the Triad, Wolf3D engine'inin sonraki bir sürümünü kullanıyordu ve dokulu zeminler ile tavanlar vardı
      Duke Nukem'in Build engine'i BSP kullanmıyordu

      https://www.jonof.id.au/forum/topic-137.html#msg1548

    • Sonradan Shadow Warrior'da böyle şeyler mümkün olmuş gibiydi. Portal tabanlı olduğunu hatırlıyorum ve editörde ayarlaması oldukça sancılıydı

    • Zemin konusunda, bildiğim kadarıyla DOOM bile bunu tam doğru yapmıyordu. Dikey duvarlarda belirli bir duvar parçası için her piksel sütununda perspektif bölmesini yalnızca bir kez yapmanız yeterli
      Zeminde ise ne yazık ki böyle bir lüks yok; yanlış hatırlamıyorsam DOOM zemini parçalara ayırıyor, doğru perspektifi yalnızca köşelerde hesaplıyor ve arayı enterpolasyonla dolduruyordu

    • İlk bakışta bunun sadece skin'i değiştirilmiş bir Wolfenstein 3D olduğunu düşünmüştüm. Bu oldukça haksız bir değerlendirmeymiş; burada gerçekten çok emek var

  • Harika bir yazı. Özellikle gib animasyonu oluşturma yaklaşımı ilginçti.
    Bu bir teknik demoydu ama ben de 90'ların ortalarında buna benzer bir şey yapmıştım. Bu yazıda görünmeyen bir nokta olarak, dokularda 8x8 veya 16x16 lightmap kullanarak titreyen meşaleler ya da koridorda uçarken etrafa ışık saçan roketler gibi efektleri kolayca yapabiliyordum. İstenirse ışığı “önceden işlemek” için de lightmap kullanılabiliyordu.
    Lightmap “sadece” 8x8 olduğu için, her luxel yani lightmap'in her birimi için ışık kaynağına olan mesafeyi ve görüş hattını hesaplayıp parlaklık değeri çıkarmak gibi matematiksel işlemleri kaldırabiliyordu. Dokuyu render ederken de luxel, arama tablosuyla birlikte kullanılarak gerçekten çizilecek pikselin rengi belirleniyordu.
    Performans için, hatırladığım kadarıyla lightmap'leri saniyede 15 kez güncelliyordum. DJGPP sayesinde render tarafında inline assembly kullanmıştım ve o dönemde kayan nokta işlemleri yavaş olduğundan, iyi optimize edilen sabit nokta aritmetiğini tercih etmiştim. Dönemin bilgisayarları için render performansı şaşırtıcı derecede iyiydi.

    • Sabit nokta fikrinin çok az kullanıldığını ve hak ettiği değeri görmediğini düşünüyorum. Gerçekten daha iyi bir seçenek olduğu çok alan var ve bazen performansı da daha iyi oluyor.
  • 1990'ların başı ve ortasındaki grafik programlama oldukça eğlenceliydi. Bellek eşlemeli video RAM'e piksel verisi yazdığınızda ekranda anında görünüyordu.
    0xA0000'ı gösteren tek bir işaretçi yeterliydi, API gibi şeylere gerek yoktu. Bahsedilen kare olmayan pikselli 320×200 VGA modunun sebebi, video tamponunun 64000 bayt olması ve böylece 16 bit segment içine sığarak 16 bit kodda ve CPU tarafında adreslemeyi kolaylaştırmasıydı.

    • O dönemde PC'nin, konsollara kıyasla CPU'su canavar gibiyken bile, grafik mimarisi yüzünden 1985 NES'teki Mario tarzı akıcı kaydırmayı gerçekleştirmekte zorlanması bana hep ilginç gelmiştir.
      Ama bu zayıflık sayesinde ekranın her pikseli başına çok daha fazla iş yapılabiliyordu ve bu yüzden böyle ray casting ya da BSP tree sistemleri mümkün oldu.
      Sprite ve arka plan katmanları için özel işlemciler yoktu ama bunun karşılığında PC'nin yapabilecekleri katı, sabit işlevli bir mimariye hapsolmamıştı.
      90'ların ortası ve sonlarında özel 3D işlemciler çıkınca bu artık sorun olmaktan çıktı ama 90'ların başlarında kısa bir süre için benzersiz görsel render teknikleri için bir oyun alanı vardı.
    • 0xA0000 işaretçisi gerçekten yeterliydi ama kullandığınız extender bunu biraz daha uğraştırıcı hale getirebiliyordu :-P
      DJGPP ve Free Pascal, DJ Delorie'nin aynı go32 extender'ını kullanıyor ama tam doğrusal eşleme yapmadığı için ekranda bir şey göstermek adına biraz daha ince ayar yapmak gerekiyordu.
    • VGA çıkmadan önce işler çok daha karmaşıktı.
  • En ilginç kısım iç araçlar. gib animasyonu oluşturan Python betikleri ya da Blender'dan 2D sprite sheet üreten diğer Python betikleri gibi şeyler.
    Orijinal yazının yazarı belli ki iyi görseller de üretebilen 10x bir mühendis ve bana göre böyle insanlar gerçekten nadir. Tutarlı bir sanat yönetiminin olması da oldukça şaşırtıcıydı.

    • 90'larda bu türün bir hayranı olarak baktığımda, büyük hitlerin arkasında hep bu tür Rönesans tipi mühendisler varmış gibi geliyor. Hâlâ birkaç ismi hatırlıyorum; gerçekten sanatçıydılar.
      Son 15 yılda oyun sektöründe CEO ya da baş yönetmen dışında neredeyse kimsenin adını bilmiyorum.
  • Bu oyunun, kadın bir başkahramana sahip nadir shooter'lardan biri olabileceğini az önce fark ettim. Kedi calico desenli ve bu tür kediler neredeyse her zaman dişi olur (https://en.wikipedia.org/wiki/Calico_cat).

    • Kadın başkahramanlı shooter'lar o kadar da nadir mi? Aklıma hemen gelen oldukça ana akım örnekler olarak Perfect Dark, Mirror's Edge, Dishonored 1 mi 2 mi, Metroid gibi yapımların hepsi bir şekilde shooter ve kadın başkahramanlı.
      Tabii Mirror's Edge, %100 kesin konuşacaksak “shooter”dan çok “birinci şahıs” sayılır.
      Ayrıca “RPG + FPS” türünde erkek ya da kadın olarak oynanabilen birçok oyun da var.
      Yazar da desen ve kedinin olası cinsiyeti konusunu biliyor gibi görünüyor:

      After all, I do need to give the protagonist his fair share. [image] (Yes, I know it's a female, but call it convention rooted in dialect.)

    • Bu Perfect Dark oyunu değil.

    • Günümüzde boomer shooter türünde kadın başkahramanlar epey yaygın. Mesela Selaco[0], Supplice[1], The Citadel[2] ve devam oyunu[3], Zortch[4] ve planlanan devam oyunu[5], Nightmare Reaper[6], COVEN[7], Viscerafest[8], Hedon[9] gibi örnekler var.
      Hatta bugünlerde kadın başkahramanlı boomer shooter'ların, olmayanlardan daha fazla olduğunu bile düşünüyorum :-P Steam aramasında “boomer shooter” ve “female protagonist” etiketlerini birleştirince 143 sonuç çıkıyor; buna karakter cinsiyetini seçebildiğiniz ya da çoğunlukla erkek oynayıp bazı bölümlerde kadın oynadığınız oyunlar da dahil gerçi.

      [0] https://store.steampowered.com/app/1592280/Selaco/

      [1] https://store.steampowered.com/app/1693280/Supplice/

      [2] https://store.steampowered.com/app/1378290/The_Citadel/

      [3] https://store.steampowered.com/app/3371240/Beyond_Citadel/

      [4] https://store.steampowered.com/app/2443360/Zortch/

      [5] https://store.steampowered.com/app/3807500/Zortch_2/

[6] https://store.steampowered.com/app/1051690/Nightmare_Reaper/

[7] [https://store.steampowered.com/app/1785940/COVEN/](<https://store.steampowered.com/app/1785940/COVEN/>;)

[8] [https://store.steampowered.com/app/1406780/Viscerafest/](<https://store.steampowered.com/app/1406780/Viscerafest/>;)

[9] [https://store.steampowered.com/app/1072150/Hedon_Bloodrite/](<https://store.steampowered.com/app/1072150/Hedon_Bloodrite/>;)
  • Muhtemelen kasıtlı değildi ama genel olarak bu tür şeylerden pek etkilenmiyorum ve bir değer de görmüyorum. Hollywood'da kadınların kendilerinin iki katı büyüklükteki adamları yere serişinin tasviri de aynı
    Bana göre gerçek dışı, gülünç ve zararlı

  • Gerçekten harika. 90'larda kullanılan bir diğer eğlenceli numara da palette animation idi. Sadece paleti değiştirerek düşük çalışma maliyetiyle inanılmaz havalı efektler üretilebiliyordu

    • Evet. Bu tekniğin harika bir örneğini görmek için bu siteyi şiddetle tavsiye ederim

      http://www.effectgames.com/demos/canvascycle/

    • Kare ortasında palette değiştirmek de eğlenceli. PC'de Amiga'nın copper'ı gibi bir şey olmadığından zamanlamaya çok daha fazla dikkat etmek gerekiyor ama yine de mümkün

    • Diablo 1 ve 2'deki birçok düşmanın aslında aynı sprite'ın farklı paletlerle boyanmış hali olduğunu hatırlıyorum. Aynı numara mı bu?

    • Mavi su, mor plazma, kırmızı/turuncu ise kan ya da lav demek

  • Render edildikten sonra quantized sprite'ların oldukça iyi görünmesine gerçekten şaşırdım. O hızlı dönüşüm sayesinde çok net görünüyorlardı

  • Saçma derecede zorlu kısıtlarla çalışan bir 3D engine yapan bir başka geliştirici olarak, buradaki açıklamanın ayrıntılarını ve geçilen süreci görmek gerçekten hoşuma gidiyor

  • PlayStation homebrew için bir voxel space rendering teknoloji demosuyla uğraşıyorum. Hafta sonu bir iki gün kurcaladıktan sonra bile yaklaşık 10~15 FPS gibi fena olmayan sonuçlar alıyorum ve henüz DMA ya da GTE'yi, hatta polyline temel şekilleri bile kullanmadım
    Trigonometriyi ve eski usul düşük seviye optimizasyon numaralarını yeniden hatırlamak ferahlatıcı. Scratch buffer 1KiB olduğunda ve stack bunun sadece bir kısmını kullanabildiğinde, işte kullandığım mikrodenetleyicilerin ne kadar lüks olduğunu fark ediyorsunuz. Orada her thread'e 8KiB stack ayrılıyor ve 50'den fazla C++ template fonksiyonunun yığıldığı backtrace'ler bile çıkıyor sonuçta