İmzalı mesafe alanlarını (2D) gerçek zamanlı olarak nasıl hızlı bir şekilde oluşturabilirim?


21

Bir de önceki soruya , imzalandıktan mesafe alanlarının, önceden hesaplanabilir çalışma zamanında yüklenen edilebileceği öne sürüldü ve oradan kullandı.

Bu sorunun sonunda açıklayacağım nedenlerle (ilgilenen insanlar için), gerçek zamanlı olarak mesafe alanları oluşturmam gerekiyor.

Orada (önerildiği gibi Pah mesafe dönüşümleri ve Voronoi diyagramı-yaklaştırma bazlı dönüşümleri yöntemleri gibi gerçek zamanlı ortamlarında uygulanabilir olması gerekiyordu farklı yöntemler için orada bazı evrakları burada PixelJunk Nişancı dev adam tarafından bu sunumda ), ancak Ben (ve böylece diğer birçok insanın varsayılabileceği gibi) gerçekten onları kullanmaya koymakta çok zorlanıyorum, çünkü genellikle uzun, matematikle şişirilmiş ve açıklamalarında çok algoritmik değiller.

Mesafe alanlarının gerçek zamanlı olarak (uygun şekilde GPU'da) oluşturulması için, özellikle mesafe alanlarının sonuç kalitesi dikkate alınarak hangi algoritmayı önerirsiniz?

Başka bir kağıt ya da slaytla bağlantının aksine gerçek bir açıklama / öğretici aradığım için, bu soru :-) için uygun olduğunda bir lütuf alacak.

İşte bu yüzden gerçek zamanlı olarak yapmam gerekiyor:

Bu SDF'leri büyük 2B ortamlar için önceden hesaplamanız gerekiyorsa (büyük bir Terraria benzeri harita düşünün), bu, depolama alanında (ve harita oluşturma zamanında) daha fazla uygulama lehine oldukça büyük bir genel gider kabul ettiğiniz anlamına gelir. gerçek zamanlı SDF üretimi için yeterince hızlı olan karmaşık bir algoritma.

Örneğin, 10 * 10 piksel karo boyutuna sahip 1000 * 256 (genişlik * yükseklik) ve dolayısıyla toplam 10000 * 2560 piksel boyutuna sahip nispeten küçük bir harita, eğer nispeten küçük bir miktar seçerseniz, 2 megabaytlık bir boyutta size mal olacak Yalnızca 0 ile 255 arasındaki mesafe değerlerini sakladığınızı varsayarsak, 128x128 SDF çözünürlüğü.

Açıkçası, bu hızla çok fazla olabilir ve sahip olmak istemediğim bir yük.

Başka bir şey var:

SDF'ler birçok şey için kullanılabilir (çarpışma tespiti gibi) ve bazı faydalı uygulamalar henüz keşfedilmedi. Bence gelecekte pek çok insan bu şeyleri arayacak ve burada kapsamlı bir cevap alırsak, pek çok insana yardım edeceğimizi düşünüyorum.


"İmzalı bir mesafe alanı nedir" diye bir şey yazmıştım ve ilk hit GPU versiyonuydu: http.developer.nvidia.com/GPUGems3/gpugems3_ch34.html Biraz eski ama aramalarınızı ilerletmenize yardımcı olabilir.
Patrick Hughes,

1
Belki bir şeyleri özlüyorum, ama neden bunu gerçek zamanlı olarak yapmanız gerektiğine dair bir ifadeyle kafam karıştı (en azından neden bunun spoiler olarak etiketlendi); ilk olarak, 128x128 SDF için 2 MB rakamı nereden buluyorsunuz? İkincisi, neden 2MB'lık bir çok ağır bellek kullanımı olduğunu düşünüyorsunuz? Önemsiz olmadığına katılıyorum, ancak genel harita belleği kullanımınızın küçük bir kısmı gibi görünüyor. Üçüncüsü, alanı gerçek zamanlı olarak üretmek bu belleği nasıl koruyacak? Hala aynı veriyi anında oluşturulmuş veya önceden hesaplanmış olarak mı kaydetmelisiniz?
Steven Stadnicki

Daha geniş anlamda, SDF'lerin ihtiyaç duyduğunuz teknik olmadığı kolayca anlaşılabilir. Özel durumunuz hakkında daha fazla bilgi - statik engel sayımı, dinamik engel sayımı vb. - ve tam olarak elde etmeyi umduğunuz etki, sizin için en muhtemel olanı tespit etmeye yardımcı olacaktır.
Steven Stadnicki

1
Mesafe alanını gerçek zamanlı olarak oluştursaydım, bu kare başına sadece 2 MB'lık bir zaman oluştururdum (toplam bellek yükü her zaman bir mesafe alanı için gereken bellek olurdu, çünkü sadece ekran için bir taneye ihtiyacım vardı). 1000x128 örneğimden daha büyük bir haritam varsa (büyük Terraria haritalarının 10000'lerin ötesine geçtiğini düşünüyorum), o haritanın her 1000x128 alt haritası için bu 2mb'den birine ihtiyacım var. Neden ilk önce SDF'lere ihtiyacım var, bu sorunun başında bağlantı verdiğim ilk soru (GPU 2D gölge dökümü için).
TravisG

1
@ heishe her kare için bir kez 2Mb veri oluşturmaya mı çalışıyorsunuz? Ciddi anlamda?
kaoD

Yanıtlar:


9

Catalin Zima , makalesinde dinamik 2D gölgelerin nasıl elde edileceğini açıklıyor - ve imzalı bir mesafe alanı kullanıyor (bu bağlamda gölge tamponu için sadece süslü bir isim olduğunu söyleyebilirim). Metodunun bir GPU'ya ihtiyacı var ve uygulaması en iyisi değil (makinemdeki yaklaşık 20 ışıkta 60Hz'in altına düşmüş, benimki yaklaşık 500 ışık almış); Bu, hızın üstünde kodun netliğini tercih ettiği için beklendiği gibi.

uygulama

Aynen onun uyguladığı gibi:

  1. Tüm gölge tekerleklerini bir dokuya dönüştürün.
  2. Her piksel için ışığın merkezine olan mesafeyi hesaplayın ve bu değeri opak piksellerin RGB'sine atayın.
  3. Görüntüyü, 3B kameranın bu pikselleri nasıl göreceğini gösterecek şekilde bozun.
  4. Resmi, makalesinde açıklanan sıradışı yeniden boyutlandırma kullanarak 2xN boyutunda bir görüntüyle ezin (düz bir yeniden boyutlandırma işe yaramaz).
  5. 2xN görüntü şimdi ışığın dört çeyreğinin tamamı için imzalı mesafe alanınızdır (bir çeyreğin temelde 90 derecelik tek bir kamera frustum olduğunu unutmayın).
  6. Işık haritasını çiz.
  7. Işık haritasını (ışıkla olan mesafeye göre) bulanıklaştırarak yumuşak gölgeler elde edin.

Son uygulamam: (her adımın bir tek gölgelendirici olması):

  1. (1) yapın.
  2. Do (2) ve (3) .
  3. (4) yapın. Uygulaması gerçekten yavaştır: GPGPU'yu bunun için deneyip kullanabilirsiniz. GPGPU (XNA) kullanamadım, öyleyse yaptığım şey:
    • İlk N / 2 sütunun N / 2 dörtlüsü ile temsil edildiği ve EXACT aynı pozisyonda (son tamponun ilk sütununu kapsayan) ancak farklı doku koordinatlarında (ikinci N / 2 sütun için aynı olan) bir kafes oluşturun
    • GPU'daki derinlik testini kapatın.
    • MIN piksel karıştırma işlevini kullanın.
  4. (6) ve (7) yapın.

Oldukça zekice: temelde gölgelerin 3B olarak 2B'ye nasıl işlendiğinin doğrudan bir çevirisi.

tuzaklar

Asıl tuzak, bazı nesnelerin gölgelenmemesi gerektiğidir: benim örneğimde bir Liero (gerçek zamanlı solucanlar) klonu yazıyordum ve bu nedenle örneğin oyuncuların solucanlarının gölgelenmesini istemedim (en azından bir tane) Her oyuncunun ekranında). Bu 'özel' nesneler için tek yaptığım, onları son adım olarak yeniden çizmekti. Buradaki ironi, çoğu nesnenin gölgeli olmamasıydı (solucanlar, manzara ön planı), bu nedenle burada bir geri çekilme sorunu var.


Yeniden boyutlandırma yöntemine yaptığınız ayarlama, 60fps'nin üzerindeki 500 ışığı tutabilmek için hızlandıran tek şey miydi?
TravisG,

Tamam, cevabı orijinal problemimi çözdüğü için kabul edeceğim, ancak ödül için neye verdiğimi cevaplamıyor. Bekleyeceğim ve belki de birisi etrafındaki imzalı mesafe alanı üretimi için birkaç O (N) yönteminden birini açıklamak için çok uzun sürebilir.
TravisG,

İlk soru ile ilgili @heishe: emin değil. Tüm optimizasyonları tek seferde yaptım - sanırım kapatmayı ve kare hızındaki düşüşü büyük oranda izlemeyi hatırladığımı hatırlıyorum. All-in-all 6 ışıktaki arama çağrıları kare hızınızı öldürür. Söylediğim gibi, söyleyebileceğim kadarıyla, adım 5'te (4) işaretli bir mesafe alanınız var - ama onlar hakkında daha fazla şey bilen birisinin bunu onaylaması gerekecek.
Jonathan Dickinson

Bu, imzalı bir mesafe alanının çok özel bir hali. Normal işaretli bir mesafe alanında, her piksel en yakın engele olan mesafeyi içerir. Bu algoritmada, mesafe alanı sadece bir engel içerir ve ayrıca engel tüm görüntüde sadece 1 pikseldir (ışık kaynağı), bu nedenle bu mesafe alanı O (N) 'de üretilebilir.
TravisG,

1
@heishe burada gölgelendiricim: gist.github.com/2384073 . Bozulmalar 2 + 3.
Jonathan Dickinson
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.