Gönderen Konu: Merhaba retrojen (ve ilk 3D denemelerim)  (Okunma sayısı 1255 defa)

0 Üye ve 1 Ziyaretçi konuyu incelemekte.

Çevrimdışı Alpyre

  • RAAT
  • Retromanik
  • *
  • İleti: 19
Ynt: Merhaba retrojen (ve ilk 3D denemelerim)
« Yanıtla #15 : 10 Temmuz 2017, 11:23:58 »
Bu başlığa güncelleme zamanı! Geç cevaplar için özür. Şehir dışındaydım... :(

Alıntı
fakat uzak duvarlardaki texture'lar sağa sola sallanıyor hatta bazen hepten yok oluyorlar, bu hiç hoş değil:
Bu problemin başka bir bug olmadığından emin misin. mesela precision'ı 6 bit yerine 8 bite veya 16 bite çıkarınca bug ortadan kalkıyor mu?...
Aynen abi. Duvarlara yaklaşınca oluşan bozulma precision’ı 10 bit'e çıkarınca ortadan kalkıyor. 16 bit'e ise hiç çıkarmak istemiyorum. Çünkü bazı hesaplamalarda precision’ı kaybetmemek için sola iki kez bitshift yapıyorum. Bu değişkenlerimi double yapmak zorunda bırakır. Bunu istemiyorum. Önerdiğin gibi 8 bit kullanıp, high word'ü doğrudan okumak süper olur. Yalnız C'de bunun için yazacağım kod ne kadar verimli olur bilemiyorum? Keşke Assembly bilsem. :D

Uzak duvarların kaybolmasının nedeni ise, mapping’de kullandığım bir değişkenin (her satırdaki duvar uzaklığı) de precise olması gerektiğindenmiş. Onu halledince o da düzeldi.

Bu arada görsellerden de anlaşılacağı gibi “perspective correct texture mapping” yapıyorum (her satırda duvar uzaklığı bu yüzden gerekli). Şehirlerarası yolda 90’lı yıllardaki öncü 3D oyunların görsellerini youtube’dan bol bol inceledim. “Legends of Valour” ve “Ultima Underworld” çok dikkatimi çekti. Bu ikisinin de PC versiyonu “perspective correct” kullanmıyor gibi. Affine kullanıyorlar sanki (bazı açılarda perspektif bozulmaları var çünkü texture’larda).

Ben de duvarları daha küçük duvarlara bölüp her duvar için Affine mapping yapmaya karar verdim.



Böylece satır başına birkaç çarpma bölme işleminden daha kurtulmuş oldum. Fakat bu defa da daha fazla vertex transform edilmek zorunda. Parça duvarların ve texture’ın genişliğini, perspektif bozulmasının fazla hissedilmeyeceği kadar büyütüp bir ortalama yakalamaya çalıştım. Hazır elim değmişken texture’ı da tümden değiştirdim. Belirttiğin gibi gradient’li bir şey yapmaya çalıştım. Gerçekten fark yarattı.



NOT: Bu arada Legends of Valour’un Amiga sürümüne de baktım. Zemin döşemesini çıkarmışlar, fakat duvarlar “perspective correct”! Çok ilginç değil mi? :)
Bu haliyle FPS 060 Amiga’mda üst sınır olan 50’ye dayandı. Fakat duvarlara yakın olunduğunda (en az 25’e kadar) düşebiliyor.
Tüm bu optimizasyonlara rağmen, hala stok A1200’de bir Legends of Valour FPS performansını yakalayabilmiş değilim (Affine kullanmama rağmen 7-10 FPS’in üzerine çıkamadım hala). Bir şeyleri doğru yapmıyor olmalıyım.

Tahminimce hesaplamalarda değil de, pikselleri ekrana yazdırırken oluyor ne oluyorsa.
Ya da bu oyunlar Assembly ile yazıldığı için mi daha hızlı, bilemiyorum?
Bir de gcc ile mi derlesem acaba? Bakıcaz… :)

Denemelerim sürecek, bakalım daha neler öğreneceğim.

Çok detaylı yazamıyorum şu aralar. Aslında bu thread bayağı bir güzelleme hakediyor. Kusuruma bakmayın. Ama süper gidiyor.
Yorumların hem fikir, hem gaz veriyor, hem de biraz şımartıyor abi. :)
Yoğun olduğunu biliyorum. Kıp kısa yazsan da hiç sorun değil. Zaten tek satırda bile 40 yıl düşünsem aklıma gelmeyecek fikirler veriyorsun. Çok sağol valla. :)

EDIT: Bir de executable atacaktım. Unutmuşum. Buyrun efendim.

Hareket için: W,A,S,D
Tam ekran  : F
Çıkış : Q

Çevrimdışı Ref

  • Yönetici
  • Özgür Retrocu
  • *
  • İleti: 2030
  • Advanced User Simulator
    • ae unutmadan
Ynt: Merhaba retrojen (ve ilk 3D denemelerim)
« Yanıtla #16 : 11 Temmuz 2017, 01:04:39 »
Legends of Valour seninkinden yavaş çalışıyor gibi geldi bana alpyre.

stok a1200 üzerinde 7-17fps çiziyor.

Çevrimdışı Alpyre

  • RAAT
  • Retromanik
  • *
  • İleti: 19
Ynt: Merhaba retrojen (ve ilk 3D denemelerim)
« Yanıtla #17 : 12 Temmuz 2017, 17:24:48 »
Legends of Valour seninkinden yavaş çalışıyor gibi geldi bana alpyre.

stok a1200 üzerinde 7-17fps çiziyor.

Aaa!? Gerçekten mi? Yani aslında öyle de olması gerek, çok daha sade bizimkisi.
Benim makinede 10'un üzerini göremedim bir türlü.
Ben A1200'ümde custom graphics.library'si olan bir ROM kullanıyorum, sanırım ondan bu farklılık.
İyisi mi yeni bir ROM yapayım şu makineye! :)

17 FPS hiç fena değil. Basit bir labirent oyunu yapabilirim öyleyse. :)

Çevrimdışı nightlord

  • RAAT
  • Tedavideki Retromanik
  • *
  • İleti: 366
    • Night Network
Ynt: Merhaba retrojen (ve ilk 3D denemelerim)
« Yanıtla #18 : 12 Temmuz 2017, 21:14:53 »
Selam Alpyre, hızlı iki sorum var?

Alıntı
mapping’de kullandığım bir değişkenin (her satırdaki duvar uzaklığı)

hemen bir terminoloji senkronizasyonu:

"satır" ile ne kastediyorsun? sanki dikey piksel sütunlarını (yani x=sabit) kastettiğini anlıyorum ama emin olamadım. yatay raster satırı (yani y=sabit) kastetmiyorsun değil mi?

Alıntı
Fakat bu defa da daha fazla vertex transform edilmek zorunda
senin vertexlerin 2d mi (yani üstten görünüş) 3d mi? transform işleminden kastın 3x3 (veya 3x2) bir matrix ile 2d bir vertex'in çarpılması mı? yoksa 4x4 (muhtemelen içine projection da yedirilmiş) bir matrix ile 3d bir vertex mi çarpıyorsun? ya da başka bir metod mu?


Çevrimdışı Alpyre

  • RAAT
  • Retromanik
  • *
  • İleti: 19
Ynt: Merhaba retrojen (ve ilk 3D denemelerim)
« Yanıtla #19 : 13 Temmuz 2017, 09:03:46 »
Hemen hızlı iki yanıt geliyor :)

Alıntı
mapping’de kullandığım bir değişkenin (her satırdaki duvar uzaklığı)
hemen bir terminoloji senkronizasyonu:

"satır" ile ne kastediyorsun? sanki dikey piksel sütunlarını (yani x=sabit) kastettiğini anlıyorum ama emin olamadım. yatay raster satırı (yani y=sabit) kastetmiyorsun değil mi?
Haklısın. 'Satır' hiç doğru bir terminoloji olmadı. "Sütun" demeliydim (x=sabit). Duvarlar sırayla düşey çizgiler halinde çiziliyor.

Alıntı
Fakat bu defa da daha fazla vertex transform edilmek zorunda
senin vertexlerin 2d mi (yani üstten görünüş) 3d mi? transform işleminden kastın 3x3 (veya 3x2) bir matrix ile 2d bir vertex'in çarpılması mı? yoksa 4x4 (muhtemelen içine projection da yedirilmiş) bir matrix ile 3d bir vertex mi çarpıyorsun? ya da başka bir metod mu?
Bak işte bu soru çalıştığım yerden geldi.
Dün şu yazını okumuş bulundum (sörf yaparken şans eseri karşıma çıktı): http://www.plazma-dergi.org/dergi/08/chunk/ch09.html
Okumamış olsaydım şimdi şaşkın şaşkın ekrana bakıyor olacaktım muhtemelen. :) Neyse...

Vertex'lerim tamamen 2D. X ve Y koordinatından ibaret.
'Transform' dediğim ise bu vertex'lerin herbirini oyuncuya rölatif hale getirmek (sanki oyuncu sabit duruyor da tüm duvarlar onun etrafında dönüyor gibi).

Pseudo code olarak yazarsam şöyle bir şey yapıyorum:
pX,PY : Oyuncunun mutlak haritadaki konumu
X,Y :  Vertex'lerin mutlak haritadaki koordinatları.
TX,TY : Oyuncuya göre rölatif hale getirilmiş koordinatlar.
Kod: [Seç]
for each vertex in this sector
  vertex.TX = vertex.X - pX
  tempTY    = vertex.Y - pY
  vertex.TY = vertex.TX * Cos(angle) + tempTY * Sin(angle)
  vertex.TX = vertex.TX * Sin(angle) - tempTY * Cos(angle)

Daha sonra da bu TX,TY koordinatlarından vertex'lerin ekran koordinatlarını hesaplıyorum. TY bir aproksimasyon olarak oyuncuya uzaklık (z) kabul ediliyor (bu bisqwit'in kodunun aşağı yukarı aynısı).

Bu hesaplamalar için matris kullanabileceğimi yeni öğrendim (dün :)).
Hatta bisqwit'in videosundaki gizemli "Vector Cross Product" işleminin olduğunu da sanırım anladım. Vertex'leri vektör olarak alıyor, matris olarak yazıyor ve sonra ardışık matris işlemleri yapıyor. Ama giriş yazımda da dediğim gibi, bu çok daha pahalı. Temel trigonometri ile çok daha ucuz hesaplanabiliyor.

Ancak 'transform' işleminde avantaj sağlayabilir gibi duruyor. Bunun üzerine biraz kafa yorayım.

Çevrimdışı nightlord

  • RAAT
  • Tedavideki Retromanik
  • *
  • İleti: 366
    • Night Network
Ynt: Merhaba retrojen (ve ilk 3D denemelerim)
« Yanıtla #20 : 13 Temmuz 2017, 19:55:05 »
OK bu durumda vertex transform sayısını azaltmanın bir yolu olabilir. Özellikle duvarları küçük küçük bölümlediğin için (hani mesela 8m uzunluğundaki duvarı 8 tane 1m duvar yapıyorsun ya)

Diyelim ki 8 m duvar için 9 vertex'in var.
v1, ... , v9

ve sen bunları transform edip 9 transformed vertex buluyorsun
tv1, ... , tv9

Bu yazdığın işlem ile sadece ilk 2 vertexi döndür.
tv1, tv2 yi bul

sonra bu ikisinin farkı senin o yöndeki duvarlar için birim vektörün

u1 = tv2 - tv1

bundan sonra

tv3 = tv2 + u1
tv4 = tv3 + u1
...
tv9 = tv8 + u1

yani 7 tane vertex'i sadece 2 toplama ile bulabilirsin.

Hatta en başta hatırlarsan bunu sormuştum. Mesela bütün duvarlar kuzey güney ve doğu batı şeklinde olsa işine yarar mı diye. Bunun için sormuştum. Çünkü o durumda sadece 2 tane birim vektör hesaplaman yeterli diğer bütün vertexleri toplamalar/çıkarmalar ile transform edebilirsin.





Çevrimdışı Wisdom

  • RAAT
  • Retroman
  • *
  • İleti: 40
Ynt: Merhaba retrojen (ve ilk 3D denemelerim)
« Yanıtla #21 : 15 Temmuz 2017, 12:44:09 »
Merhaba,

Cok guzel gidiyor, elinize saglik, ben daha yeni gordum bu konuyu. Koda bakmadim ama konunun tamamini okudum, bir yerde sin/cos tablolarini 72 degerden 18'e indirdiginizi yazmistiniz galiba (simdi geri donup bakamadim). Eger programin size'i sorun degilse (ki degil saniyorum), bu tablolari mumkun oldugunca acmanizda ve bir fonksiyon uzerinden erismek yerine inline olarak erismenizde fayda var. Hatta yeriniz varsa mumkun oldugunca her turlu hesaplamayi tablolara donusturmenizi oneririm. Cok genel bir oneri oldu biliyorum, belki zaten yaptiniz, belki de "feasible" degil, ama soylemeden gecemedim.

Tekrar elinize saglik, basarilar!

Çevrimdışı Ref

  • Yönetici
  • Özgür Retrocu
  • *
  • İleti: 2030
  • Advanced User Simulator
    • ae unutmadan
Ynt: Merhaba retrojen (ve ilk 3D denemelerim)
« Yanıtla #22 : 17 Temmuz 2017, 14:32:57 »
Hatta en başta hatırlarsan bunu sormuştum. Mesela bütün duvarlar kuzey güney ve doğu batı şeklinde olsa işine yarar mı diye. Bunun için sormuştum. Çünkü o durumda sadece 2 tane birim vektör hesaplaman yeterli diğer bütün vertexleri toplamalar/çıkarmalar ile transform edebilirsin.

hmm bu durumda wolfenstein topu topu 2 vertex hesabından ibaret miymiş?
e bu güzel bir ip ucu oldu.

Çevrimdışı Alpyre

  • RAAT
  • Retromanik
  • *
  • İleti: 19
Ynt: Merhaba retrojen (ve ilk 3D denemelerim)
« Yanıtla #23 : 17 Temmuz 2017, 17:02:28 »
...bu tablolari mumkun oldugunca acmanizda ve bir fonksiyon uzerinden erismek yerine inline olarak erismenizde fayda var. Hatta yeriniz varsa mumkun oldugunca her turlu hesaplamayi tablolara donusturmenizi oneririm...

Haklısın Wisdom. Öyle yapacağım.
Ancak nightlord'un önerdiğini uygulamanın zarif bir yolunu düşünüyorum kaç gündür. Bu optimizasyon kodumda kesinlikle olsun istiyorum ama haritalarım Wolf3D'deki gibi blok blok olsun da istemiyorum. Pek çok şeyi yeni baştan tasarlayacağım sanırım. :)

Çevrimdışı Ref

  • Yönetici
  • Özgür Retrocu
  • *
  • İleti: 2030
  • Advanced User Simulator
    • ae unutmadan
Ynt: Merhaba retrojen (ve ilk 3D denemelerim)
« Yanıtla #24 : 18 Temmuz 2017, 23:31:15 »
Wolf3D'deki gibi blok blok olsun da istemiyorum. Pek çok şeyi yeni baştan tasarlayacağım sanırım. :)

bu durumda harita detayını limitleyerek çözebilirsin belki de: 90,60,45,30 derecelik duvarlar kullanıp  bunları kendi aralarında  toplam 8 vertex çarpımı ile taban işlemi halledip, diğer tüm duvarları kendi gruplarında toplama yöntemi ile halledebilirsin. Hatta sadece 90 ve 45 derece kullandığında bile birçok harita başarıyla kotarılabilir.

Çevrimdışı Alpyre

  • RAAT
  • Retromanik
  • *
  • İleti: 19
Ynt: Merhaba retrojen (ve ilk 3D denemelerim)
« Yanıtla #25 : 22 Temmuz 2017, 08:46:34 »
Evreka. :)

Günlerce kafamdaki düşünce deneyleri yüzünden evde ve işte hayalet gibi gezinmelerimin sonunda tüm detaylar birbiriyle örtüştü ve neyi nasıl yapacağımı buldum.

Harita biçemimden ana loop'uma kadar pek çok şey baştan yazılacak şimdi. Bakalım artı kaç FPS elde edeceğim. :)

...tüm duvarları kendi gruplarında toplama yöntemi ile halledebilirsin....
Bir ipucu: İlk bunu düşündüm ama sonra daha da iyisini bulup vazgeçtim. Çalışırsa detaylıca açıklayacağım nasıl hallettiğimi. :)

Çevrimdışı Alpyre

  • RAAT
  • Retromanik
  • *
  • İleti: 19
Ynt: Merhaba retrojen (ve ilk 3D denemelerim)
« Yanıtla #26 : 17 Ağustos 2017, 14:58:01 »
Yeniden merhabalar arkadaşlar. Nerede kalmıştık? :)

nightlord'un dediğini (biraz da abartarak) uygulamaya çalıştım.

Haritayı yüklerken her bir duvarın hangi yöne uzandığını tespit edip duvarın bir attribute'si olarak her duvara ekledim (şimdilik sadece DOĞU-BATI-KUZEY-GÜNEY yönleri var, dilersem daha sonra ara yönler de eklemek kolay).

Sonra iki tane birim duvar parçası uzunluğunda vektör oluşturdum. Biri Doğu->Batı diğeri Kuzey->Güney yönünde.

Her karede sadece bu iki vektörü ve içinde bulunulan odanın (sector) ilk duvarının, ilk vertex'ini açıya göre sin(), cos() değerleriyle çarparak dönüştürüyorum.

Harita verisinde her odanın, her bir duvarını saat yönünde ve sırayla tanımlayınca, her duvar parçasının bittiği yerde diğeri başlamış oldu. Böylece tüm duvarların dönüştürülmüş ikinci vertex'ini uzandıkları yönün vektörünü ekleyerek hesaplayabildim.
İlk vertex ise zaten hep bir önceki duvardan miras kalıyor. Yani ilk 3 dönüştürmeden sonra tüm diğer vertex'ler sadece toplama ile hesaplanıyor.

Bir önemli değişiklik de texture bitmap'lerini eğer varsa FastRAM'e yüklenecek şekilde ayarlamak oldu (ayrıca birden çok texture da ekledim - gerçi hepsi birbirine benziyor şimdilik :) ).

Böylelikle FPS turbo kartlı Amiga'larda (030, 040, 060 da farketmiyor ilginç ki) 25-50 FPS arasına dayandı. Bu çok iyi.
Ancak stok Amiga'larda 3-10 FPS. :)

Bu Citadel'i, Gloom'u, AB3D'yi falan zamanında (yavaş diye) beğenmemiştik ama gördüğüm kadarıyla Amiga'ya bu oyunları yapan programcılar oldukça ustalık konuşturmuş.

Copper çipini "Chunky to Planar" dönüşümü yapacak şekilde programlamanın yolları olduğuna dair bir şeyler okudum. Anladığım kadarıyla bundan yararlanmışlar. Görünen o ki yolun bundan sonrasına katırlarla (low level assembly ile) devam etmek gerekecek.

Biraz daha karmaşık bir harita ile son derlenmiş çalıştırılabiliri ekliyorum. Ha bu arada bir harita editörü de geliştirmek gerek. Elle yazmak zor olmaya başladı. :)

Kaynak kodlar için de buraya bakabilirsiniz: https://github.com/alpyre/DLE

Görüşmek üzere...

Çevrimdışı Ref

  • Yönetici
  • Özgür Retrocu
  • *
  • İleti: 2030
  • Advanced User Simulator
    • ae unutmadan
Ynt: Merhaba retrojen (ve ilk 3D denemelerim)
« Yanıtla #27 : 19 Ağustos 2017, 22:47:22 »
Alpyre, bugün yeni bir trick öğrendim, wolf3d ve o dönemin oyunlarında kullanılmış vasit bir trick.

Buna göre k/g duvarlar aydınlık,  doğu/batı duvarlar karanlık.  Böylece bir ışık ilüzyonu oluşuyor.

Sanırım bu daha fazla açı kullandığında da farklı texturelarla da halledilebilir.

Her duvarın bir propertysi olduğuna göre eklemen mümkün olabilir belki.

Ayrıca 7-10 iyi bir rakam aslında. C kodundan üreyen asm koduna da göz atmak iyi olabilir. Fakat amiga demoscene hilelerini kullanmadan o rakam 15-20 aralığına çıkmaz gibi...



Çevrimdışı nightlord

  • RAAT
  • Tedavideki Retromanik
  • *
  • İleti: 366
    • Night Network
Ynt: Merhaba retrojen (ve ilk 3D denemelerim)
« Yanıtla #28 : 22 Ağustos 2017, 10:04:54 »
Alpyre şu an çok kısa bir mesaj yazabiliyorum. Ama koda çok hızlıca bir göz attım. ve pek çok yerde linked list'ler içine atılmış içinde ID barındıran nesneler kullanıyorsun. Bunların mümkün olanlarını düz arraylere yerleştirip ID kavramını da her nesnenın içinde olduğu arraydeki indisi ile değiştirmen sana bütün traversallarda hız kazandırıp, bütün  findXXX metodlarında da O(n)'den O(1)'e gitmeni sağlayabilir.

Yani findVertex(foo) yerine vertices[foo]

Eğer hızlıca bakarken bunun böyle olmasını gerekli kılan birşeyleri gözden kaçırmışsam ignore :)

Çevrimdışı Alpyre

  • RAAT
  • Retromanik
  • *
  • İleti: 19
Ynt: Merhaba retrojen (ve ilk 3D denemelerim)
« Yanıtla #29 : 23 Ağustos 2017, 16:11:06 »
Şey... Şimdi 'find' fonksiyonlarım sadece haritayı yüklerken kullanıliyor. Duvarları çizen ana döngüde çağırılmıyorlar. Her bir vertex'e, duvar'a vs. doğrudan pointer'ı ile erişiliyor orada.

Böyle yapmamın nedeni okuduğum bir makalede Array erişimlerinde her zaman 1 çarpma işlemi yapıldığı, pointer'la erişimin bu nedenle daha hızlı olacağı idi (ne kadar doğrudur bu bilmiyorum gerçi).

Amiga (exec) listlerinde traverse işlemi de tamamen pointer erişimi bu arada (harita allokasyonlarının dinamik olmasını sağlaması da cabası).

Doğru bir şey mi yapmışım? :)