Gönderen Konu: Kaç farklı şekilde çizgi çizdirilebilir?  (Okunma sayısı 6800 defa)

0 Üye ve 1 Ziyaretçi konuyu incelemekte.

Çevrimdışı Ref

  • Yönetici
  • Özgür Retrocu
  • *
  • İleti: 3093
  • Advanced User Simulator
    • ae unutmadan
Kaç farklı şekilde çizgi çizdirilebilir?
« : 08 Aralık 2014, 19:13:38 »
Bu sefer ciddi soruyorum :) Şimdi, çizgi çizme algoritmaları arasında DDA var, ve bresenham'ın algoritması var.

Bresenham'ın son zamanlarda üzerine gidildi ve bayağı hızlandı, daha ne kadar optimizasyon yapılabilir bilemiyorum, ama son 3 yılda z80 implementasyonunda 4 kat hız kazanıldı.

Çizgi çizmek işin bir yönü, ama içi dolu poligonlar çizmek başka bir yönü.  Daha önce palpa ile birlikte numo'yu kodlarken, Palpa konveks poligonları doldurmak için bir yöntem kullanmıştı, IET (integer edge tracing), aşağı yukarı şöyle birşey: http://www.phatcode.net/res/224/files/html/ch39/39-03.html

içi dolu poligon demek diyince, bresenham gibi bir modelle aynı anda karşılıklı iki çizgi çekmek, ve pixel pozisyonlarının arasını doldurmak olarak düşünüyorum.

Şimdi, norvax'a bakarsak, c64 üzerinde 50fps küp döndürmek için neler yapmış:

1. Önce 16 bit hesaplamalarla yatay doldurma tekniğini kullanmış, burada 16x16 bir alandan bahsediliyor, ne kastediliyor anlamadım.
2. Olmamış, tablo yapmaya başlamış. Önce kartezyen kordinat sisteminin tek bir çeyreğini alıp, 128 açıya bölmüş,  kordinat farklılıklarından tablo yapmış ama pek anlamadım neden, biri anlatması lazım. Sonra bu çeyreği mirrorlayarak diğer çeyrekler bulunabiliyor orada sorun yok. Bu sablo bir sinüs tablosu mu acaba? (bu Cruzer'in tekniği imiş)
3. Olmamış, çünkü sorun kordinat hesaplamaktan ziyade poligonu doldurmak. Burada devreye sadece matematiği değil, c64'ün inceliklerini bilen biri girmesi lazım, skate sprite doldurma yöntemini öğretmiş. Bu yöntemde doldurulacak yerlere spritelar yan yana dizilerek doldurma yapılıyor, işin güzel tarafı sprite'lar hires kordinatlara sahip! Böyle olunca hires bir ekranda hiç pixel basmadan bütün küpü sprite ile çizmek mümkün (bu da Chorus'dan Clearance'nin tekniği imiş).
4. Norvax bu yöntemi ikinci bir kat sprite'ı alta döşeyerek geliştirmiş, buna "boşluk doldurma" işlemi diyor, ben zaten sprite'larla doldurduğumuz yöntemin daha neresini sprite'larla dolduruyoruz tam çözemedim, belki de allta kalan bir kısım sprite'ın yerini hiç değiştirmiyordur, buraya biraz daha açıklama gerek.
4. Bu da yetmemiş, bütün 3d hesaplamasını önceden hesaplayarak 8 noktanın koordinatlarını bir tabloya girmişler.
5. bu da yetmemiş olayı bir video player'a çevirecek bir yöntemi de uygulamışlar. Buna göre her köşenin bilgisinin yanında, renk bilgisi, boşluk doldurma bilgisi vs. de akışa eklenmiş.
6.böyle olunca veri çok büyümüş, son olarak basit bir sıkıştırma yöntemi uygulayarak veriyi küçültmüşler.

Görünüşe göre c64'de bu boyutlarda (140x140) bir küp döndürmenin daha iyi bir yolu yok. Sprite fill tekniği harika görünüyor.

Benim de aklımda da alternatif bir yöntem var ama bunu grafiklerle anlatmam gerek. Doldurma için karakter tabanlı bir yöntem izlemek adına belki yine pre-calc yöntemler desteği ile çözünürlüğü 40x20 gibi düşünerek hesaplamak.

Şimdilik burada duruyorum, enteresan bilgi-yöntemler bilenler varsa devam etsin.

Çevrimdışı wizofwor

  • RAAT
  • Tedavideki Retromanik
  • *
  • İleti: 398
Ynt: Kaç farklı şekilde çizgi çizdirilebilir?
« Yanıtla #1 : 08 Aralık 2014, 22:05:16 »
Konuyu çizgi çizmekten karakter bazlı poligon doldurmaya nasıl getirdiğini anlamadım. Bu konuda ciddi bir yeteneğin olduğu su götürmez. Sprite doldurma yönteminin detaylarına ne kadar hakimsin? Sonuçta elimizde 8 tane sprite var. Küp döndürürken bu yeterli olmayacaktır. Kaldı ki bazı yerlerde (kübün kenarlarında) sprite datasını yeniden düzenlemek gerek. Bu da cycle count olarak bitmap datayı düzenlemekle aynı şey.

Neyse ben bu konulara çok fazla girmeyeyim. Ne de olsa 2D dünyamda mutluyum.
Gosub ile gidilen yerden goto ile dönen adam

Çevrimdışı Wisdom

  • RAAT
  • Retroman
  • *
  • İleti: 44
Ynt: Kaç farklı şekilde çizgi çizdirilebilir?
« Yanıtla #2 : 09 Aralık 2014, 00:52:26 »
Ref, char matrix bazli bir doldurma islemini kastediyorsun sanirim. Bu benim de aklima gelmisti ama yakin zamanda bir Oxyron demo'sunda Axis yapti bu olayi.

Norvax'in bahsettigi 16x16 char matrix'tir muhtemelen (ben nerede, ne sekilde bahsetmis bilmiyorum, senin yazdigindan anladigim bu sekilde). Yani, 128x128 pixel, 16x16 char matrix ile adresleniyor. C64'te cogu demo'da kullanilan, pixel adreslemeyi basitlestirmek uzere tasarlanmis bir layout bu. Bizim Tied demo'sunda da var.


Çevrimdışı Ref

  • Yönetici
  • Özgür Retrocu
  • *
  • İleti: 3093
  • Advanced User Simulator
    • ae unutmadan
Ynt: Kaç farklı şekilde çizgi çizdirilebilir?
« Yanıtla #3 : 09 Aralık 2014, 11:27:19 »
Ref, char matrix bazli bir doldurma islemini kastediyorsun sanirim. Bu benim de aklima gelmisti ama yakin zamanda bir Oxyron demo'sunda Axis yapti bu olayi.

Norvax'in bahsettigi 16x16 char matrix'tir muhtemelen (ben nerede, ne sekilde bahsetmis bilmiyorum, senin yazdigindan anladigim bu sekilde). Yani, 128x128 pixel, 16x16 char matrix ile adresleniyor. C64'te cogu demo'da kullanilan, pixel adreslemeyi basitlestirmek uzere tasarlanmis bir layout bu. Bizim Tied demo'sunda da var.

Ah evet, tamam, norvax 16x16 derken ben piksel olarak anlamıştım, elbette, 128x128'i kastediyor olmalı.

Daha sonra bu işi tamamen terk edip sprite bazlı doldurmaya geçmiş olmalılar, lakin 140x140 17.5 gibi bir küsüratlı rakam çıkıyor, bu yöntem tamamen terk edilmiş.

Benim önerdiğim şey şöyle birşey, eminim çokça yapılmıştır. İlk akla gelen şey bu, bildiğiniz var mı?



Böyle birşey kast ediyordum, poligonun sadece kenarlarındaki byte'ları doldurmak, içini ise arka planı set ederek doldurmak. c64'te hi-res modunu düşünürsek, bir karakterin arka planlanını tek bir byte set ederek boyamak mümkün diye biliyorum.

Şimdi sorun iç kısımların hangisinin tamamen set edilmesi gerektiğini bulmak. Bunun için çözünürlüğü karakter tabanlı düşünelim, hadi 16x16 olsun. Sonra buraya küçük alana karakter tabanlı olarak çok düşük çözünürlüklü bir poligon çizdirelim ve karakter tabanlı olarak boyuyalım. Sonra ikinci pass'da karakter çözünürlüğünden dolayı kutu kutu görünen kenarları bresenham ile hızlıca pixelleyerek poligonu netleştirelim.

Tabii denemeden bilemeyiz, ayrıca c64'de wireframe çizdirmek bile problem oluyor diye biliyorum. Ama hires modda 8x1'lik bir alanı tek bir byte set ederek doldurabiliyoruz, bütün poligonun kenarlarını çizmek 1 frame'den az alır diye düşünmekteyim.

c64'de 1 kare görüntüye kaç cycle düşüyor?

Çevrimdışı Wisdom

  • RAAT
  • Retroman
  • *
  • İleti: 44
Ynt: Kaç farklı şekilde çizgi çizdirilebilir?
« Yanıtla #4 : 09 Aralık 2014, 13:05:01 »
Ref, evet tam olarak ayni seyden bahsediyoruz. Axis'in part'ini buldum:

Oxyron - Natural Wonders - Real C64, 8580 SID

"C64'de 1 kare görüntüye kaç cycle düşüyor?" -> 312*63 = 19656 cycle (PAL). 312 rasterline var ve her bir rasterline'da 63 cycle'in var. Zaten onu da 50 frame ile carpinca 0.98 Mhz ediyor. Yalniz, VIC'in CPU'dan caldigi zamanlari hesaba katmadan boyle. DMA ve sprite display'leri sayinca bu rakam biraz daha dusuk.

Edit: Video'da tam o part'in ciktigi yeri isaretlemistim ama forum'dan bakarken en basindan basliyor video. 26. saniyeden itibaren bahsettigim part.

Çevrimdışı Ref

  • Yönetici
  • Özgür Retrocu
  • *
  • İleti: 3093
  • Advanced User Simulator
    • ae unutmadan
Ynt: Kaç farklı şekilde çizgi çizdirilebilir?
« Yanıtla #5 : 09 Aralık 2014, 15:05:15 »
"C64'de 1 kare görüntüye kaç cycle düşüyor?" -> 312*63 = 19656 cycle (PAL). 312 rasterline var ve her bir rasterline'da 63 cycle'in var. Zaten onu da 50 frame ile carpinca 0.98 Mhz ediyor. Yalniz, VIC'in CPU'dan caldigi zamanlari hesaba katmadan boyle. DMA ve sprite display'leri sayinca bu rakam biraz daha dusuk.

evet işi son noktaya bağlamış, ekrandan daha büyük poligonlar gibi görünen şeyler çizme durumu gerçekleşmiş :D Tabii 50 fps olmamış.

19656 cycle hiç de az sayılmaz, hele ki 6502'nin 2-4 cycle'lik opcode'ları düşününce demoların nasıl sürekli ileri gidebildiğini daha iyi görebiliyorum.


Çevrimdışı norvax

  • RAAT
  • Retromanik
  • *
  • İleti: 5
Ynt: Kaç farklı şekilde çizgi çizdirilebilir?
« Yanıtla #6 : 10 Aralık 2014, 11:24:31 »
Merhaba. Ben de biraz katkida bulunayim.

Oncelikle 16 x 16 hikayesi Wisdom’in dedigi gibi. Cogu C64 vektor parti, kolay adreslenebilsin ve kod hizli calisabilsin diye karakter modu ekraninda 16 x 16 (128 x 128 piksel) karakterlik bir alana cizilir.  Snapshot’da bu boyutta sigamayacak buyuklukte bir vektor var (140 x 140 piksel gerekiyor.). Bu yuzden ve aslinda bir suru baska sebepten karakter ekranini kullanmadik. Notta anlatmaya calistigim buydu.

Asil konuya donersek yine Wisdom'un dedigi gibi c64’de 1 kare (frame) 19656 (312 * 63) cycle.  Yanliz bunun bazi on kosulllari var.

1.  Ic ekran legal bir modda olmamali. Karakter ya da bitmap ekran modunda her 8 satirda bir “bad line” denilen bir durum var. Bu satirlarda 40-43 cycle aresi bir sure processor calismiyor. Yani bu satirlarda sadece 23 cycle var faydali bir seyler yapabilmek icin.

2. Tum spritelar pasif olmali. Aktif bir sprite bulundugu her satirdan 2 cycle yiyor. Mesela bir satirda 8 sprite birden varsa ( 63 - (8 * 2)) = 47 cycle kaliyor faydali birsey yapmak icin.

Ayni zamanda eger demo icin bir efekt hazirliyorsan muzik olmazsa olmazlardan. Bu da her frame’de muzige “cycle” ayirmak demek. Normalde populer muzik editorleri 25-20 raster’dan fazla kullanabiliyor her kare (frame). Bu sayi her karede degisiyor. Yani emin olmak icin maksimumda kullandigi satir kadar her ayirman gerekiyor kodunda. Kisacasi yaklasik 1500 - 2000 cycle daha gitti gozuyle bakabilirsin.
Aslinda 10 raster’dan az yiyen muzikler de yapilabilir (bkz Andropolis, Snapshot vektor parti (12-13 raster)). Ancak muzisyenin eli baya bir kisitlanmis oluyor haliyle. Andropolis demosunda Dane'in muzigi nerdeyse "bip bip" basitliginde.

Snapshot vektor partinda gerek olmayan fakat neredeyse diger tum tekniklerde gereken bir ekran temizleme suresi de var. Yani bir sonraki kareyi hazir etmek icin ekrani temizlemek. Ekrani temizlemek icin kod soyle bir sey. Acilmiş bir dongu.

lad #$00  ; Accumulator'e 0 yukle (temizleme rengi)
sta $adres
sta $adres + 1
sta $adres + 2
sta $adres + 3
....
...

Diyelim karakter ekranina ciziyoruz. 16 x 16 karakterden olusan bir ekran var. 256 karakter demek bu. Her karakter 8 sta ile temizlenebiliyor.  Yani 256 * 8 = 2048 tane sta'ya ihtiyac var. her sta 4 cycle. Bu da 8192 + 2 (lda icin)  cycle demek. Bu zaten karenin (frame) yarisi :)

Butun anlattiklarimi optimize edicek yontemler olsa da ve 19656 cycle goze ilk bakista cok goruse de, aslinda bayagi az. O yuzdendir ki 50 fps efektler her zaman ugrastirici ve degerli olmustur.

Simdi saat gec oldu. Yarin cizgi cizme ve doldurma teknigi ile ilgili birseyler daha ekleyecegim.

- Norvax

Çevrimdışı Ref

  • Yönetici
  • Özgür Retrocu
  • *
  • İleti: 3093
  • Advanced User Simulator
    • ae unutmadan
Ynt: Kaç farklı şekilde çizgi çizdirilebilir?
« Yanıtla #7 : 10 Aralık 2014, 15:19:36 »
norvax, hoşgeldin, birinci ağızdan gelen bilginin değeri bambaşka oluyor.

Benim sorum, kendi yönteminde kullandığın ve "gap filling" olarak bahsettiğin işlemin ne olduğunu da tam anlayamadım. Burada birkaç teknik problem yaşıyor olaiblirim. Ezberden yazıyorum, google'a sorsam çıkacaktır elbette, c64 sprite'ının genişliğinin 24 piksel limiti vardı sanırım. Bu durumda 8 sprite yan yana basılamıyor demekki, yoksa 192 pixellik bir horizontal fill yapılabiliyor olurdu. Burada 63 cycle'lık limit de taş koyuyor olaiblir, yeni sprite pozisyonlarını yazmak 8 sprite için mümkün olmuyor olabilir. Varsayımları bir kenara bırakayaım, bu konuda yeterli bilgim yok, asıl soruyu tekrar edeyim, vaktin olursa cevaplarsan çok sevinirim:

Gap filling'den kasıt nedir?

Çevrimdışı norvax

  • RAAT
  • Retromanik
  • *
  • İleti: 5
Ynt: Kaç farklı şekilde çizgi çizdirilebilir?
« Yanıtla #8 : 11 Aralık 2014, 01:38:15 »
hos bulduk. Konuya direk gap filling teknigi ile gireyim o zaman. Daha sonra merak edersen cizgi cizdirme metodunu da konusabiliriz. 

Ne kadar dataya sahipsiniz bilmiyorum ama gap filling'i anlatmam icin once bir kac on bilgi vermem lazim. Hali hazirda bilip bilmediginizi bilmiyorum.

1. C64 spritelari 24 piksel genisliginde, 21 piksel yuksekliginde. Ayni zamanda her sprite'in 2x genisleme yetenegi var. Ilgili Sprite'in genisleme registerini aktif hale getirisen 48 x 42 piksellik bir boyuta ulasabilirsin.
2. En fazla 8 sprite kullanabiliyorsun bir satirda (Clarence bunu 9 yapti ama neyse) ve sprite'larin oncelikleri var. Sprite 0 ile Sprite 5 ekrande ustuste ise Sprite 0'i gorursun. Oncelik su sekilde 0 >> 1 >> 2 >> 3 >> .. >> 7. Kisacasi herkes 7'yi dovuyor. 
3. Sprite stretching: Bu aslinda yazilimin donanimi kadirdigi bir metod. Her raster satirinda bir taktik uygulayarak istedigin kadar sprite'i uzatabiliyorsun. Her raster aslinda ayni sprite satirini ciziyor. Yani Diyelim ki soyle bir sprite'in var.

+: Mor renkli piksel
=: Kirmizi renkli piksel

        24 piksel

++++++++++++++++++++++++
========================
========================
========================
========================
========================
========================  2
========================  1      
========================
========================  p
========================  i
========================  k
========================  s
========================  e
========================  l
========================
========================
========================
========================
========================
========================
========================

Bunu ekranda su sekilde gosterebilirsin.

++++++++++++++++++++++++
++++++++++++++++++++++++
++++++++++++++++++++++++
++++++++++++++++++++++++
...
... (istedigin kadar y yonunde uzatabilirsin)
 
Yani sprite'in ilk satirini asagiya kadar tekrar tekrar cizdiriyorsun.

Ekran goruntusu su sekilde olacaktir. (bkz. Resim1.png)

4. Her raster satirinda sprite'in x konumunu degistirebilirsiniz. (Mesela bkz. Resim2.png)

Bu kadar on bilgi yeter saniyorum. Zaten gap filling ihtiyacini neredeyse gormus olduk Resim2'de.

Bir sonraki yazida bunlari kullanarak gap filling nasil calisiyor anlatacagim.

Devami gelecek...

Çevrimdışı norvax

  • RAAT
  • Retromanik
  • *
  • İleti: 5
Ynt: Kaç farklı şekilde çizgi çizdirilebilir?
« Yanıtla #9 : 11 Aralık 2014, 08:19:14 »
Devam edelim. Ustteki iletimde en son Resim2.png'de kalmistik. Simdi burda bir seye dikkat cekmek istiyorum. her satirda yapilan
tek bir lda ile (sprite'in x konumunu degistirmek) 48 piksel koymus oluyoruz ekrana. Bu bize cok buyuk bir avantaj sagliyor. Bu hizda bir fill-rate baska turlu imkansiz c64'te.

Gelelim SMGF metoduna. Sprite Masking with Gap Filling.   

Diyelim ulasmak istegimiz goruntu Resim 5 olsun. (Bkz: Resim5.png) Bunu tek yuzunu gordugumuz bir kup olarak dusunebiliriz.

Iki onemli isleme ihtiyacimiz var.

1- Fazlaliklari maskelemek.
2- Bosluklari doldurmak.

Fazlaliklari maskelemek:
Bunun icin yaptigimiz sey aslinda basit. 2. bir sprite kullaniyoruz. Bu ikinci sprite bahsettigim sprite onceliginde onde olan bir sprite. Yani ustune geldigi sprite'i maskeleyebiliyor. Eger bu sprite'i Resim3'deki gibi ekrana yerlestirirsek (Bkz: Resim3.png) ulasmak istedigimiz goruntuye bir adim daha yaklasmis oluyoruz. Burda maske sprite'inin rengini gri yaptim gorebilmeniz icin. Aslinda arka plan ile ayni renkte oldugu zaman gozle goremiyoruz ama maskelemeye devam ediyor.

Bosluklari doldurmak:
Simdi goruntumuzde bir bosluk kaldi. Mor ile gri renkli 2 sprite arasindaki siyah alan. Iste buna "gap" dedik biz Glance olarak. Eger burayi akilci bir sekilde doldurabilirsek amacimiza ulasmis olacagiz.

Bir sprite'imiz daha olsa. Sprite onceliginde en altta olan bir sprite. Yani butun sprtielar bunu dovuyor. Ve su sekilde yerlestirsek. (Bkz: Resim4.png).
Resimde sprite'in ekranda gercekte nasil durdugunu kirmizi cerceve ile gosterdim. Diger sprite'lar daha fazla oncelige sahip olduklari icin bu sprite'in cogunu maskeliyorlar ve sprite sadece gorunmesi gerekn yerde gorunuyor.

Burda onemli olan 2 nokta var:

- Dikkat ederseniz bu sprite'in x yonunde konumunu her raster satirinda degistirmek gerekmiyor. Her frame basinda 1 kereligine kapatacagi yuzeyin maksimum X degerine koyuyoruz. Yani frame basina bir lda, sta yetiyor bu alani doldurmak icin.
- Sprite'in y yonunde baslayacagi ve bitecegi yerlerin hesabi kolay degil. Karmasik bir algoritma ama en sonunda sadece bir tablo okumasi ile halledebilecek sekilde basitlestirebiliyoruz. Diger y konumlarinda ise sprite'i x yonunde 0'a konumlandiriyoruz. Boylece ekran disi kaliyor ve gorunmuyor.

Iste boyle. En sonunda da renkleri olmasi gereken degerlere cevirdigimizde Resim 5'e ulasmis oluyoruz.

Aslinda daha bir suru detay var ama 50fps kupu hayata geciren fikrin en can alici kismi bu.

Çevrimdışı witchdoktor

  • RAAT
  • Normalleşmiş Retroman
  • *
  • İleti: 757
Ynt: Kaç farklı şekilde çizgi çizdirilebilir?
« Yanıtla #10 : 11 Aralık 2014, 15:11:22 »
Wisdom & norvax, ref'in abuk sabuk fantazilerinin sizi gaza getirmesi acayip güzel oldu. Keyifle okuyoruz ;)

Çevrimdışı Ref

  • Yönetici
  • Özgür Retrocu
  • *
  • İleti: 3093
  • Advanced User Simulator
    • ae unutmadan
Ynt: Kaç farklı şekilde çizgi çizdirilebilir?
« Yanıtla #11 : 12 Aralık 2014, 13:47:44 »
ref'in abuk sabuk fantazilerinin...

Ref olmak kolay değil :) Aslında benden çok başkalarının fantezilerine bakış atmaktayız :) Bu ara kış depresyonu geçiriyorum büyük ihtimal, fazla focus olamıyorum, kıvılcımlar şeklinde gelip gidiyor, ondan böyle. Ama faydalı bir kıvılcım yakalayınca ordan devam edebilirim.

Norvax teşekkür ederim, olayın büyük kısmını kavradığıma inanıyorum. Biraz uygulama yaptıktan sonra bu konuya yeni sorularla döneceğimi sanıyorum.

Tabii ben bir 6502 adamı değilim, yine de bu konu, bir işin çok farklı şekillerde yapılacağını göstererek alternatif düşünmeyi tetikliyor. Ama amerikayı yeniden keşfetmeye de kararlıyım. İlk yapacağım tablosuz, kestirmesiz, edge tracing ile bir üküp döndürüp kaç fps bakmak olacak. Sonra düşünürüm.

Çevrimdışı norvax

  • RAAT
  • Retromanik
  • *
  • İleti: 5
Ynt: Kaç farklı şekilde çizgi çizdirilebilir?
« Yanıtla #12 : 12 Aralık 2014, 20:58:53 »
Eyvallah. Yardimim olduysa ne guzel.

Pamuk elleri klavyeye koyup baslamadan bitmiyor. Bir taraftan yakalayip baslamak lazim.