Voksel Yüz Tarama (Muhtemelen açgözlü kullanarak mesh basitleştirme)


9

Edit: Bu sadece kendi öğrenme deneyimim için, bu soru sormak performans nedenleriyle DEĞİLDİR.

Bu, Minecraft benzeri bir arazi motoruyla ilgili. Blokları parçalar halinde saklarım (16x256x16 blokları bir yığın halinde). Bir yığın oluşturduğumda, araziyi ayarlamak ve nesneleri yerleştirmek için birden fazla yordamsal teknik kullanıyorum. Üretirken, tam yığın için bir 1D dizisi (katı veya değil) ve katı blokların ayrı bir 1D dizisi tutuyorum.

Nesilden sonra, komşularını kontrol eden katı blokları yineliyorum, böylece sadece katı komşuları olmayan blok yüzleri üretiyorum. Hangi yüzleri kendi listelerinde oluşturacağımı saklıyorum (6 liste, olası yüz / normal başına bir tane). Bir yığın oluştururken, kameranın geçerli yığınındaki tüm listeleri ve yalnızca diğer tüm parçalardaki fotoğraf makinesine bakan listeleri oluşturuyorum. Bunu 6 listenin tümünü tek bir arabellekte saklayarak yaparım, sonra çizdiğim aralıkları değiştiririm.

Andrew Russell'ın önerdiği bu küçük gölgelendirici hile ile 2B atlas kullanarak , benzer yüzleri tamamen birleştirmek istiyorum. Yani, aynı listede yer alıyorlarsa (aynı normal), birbirlerine bitişik, aynı ışık seviyesine sahipler, vb. Hala dikdörtgenlerle sonuçlanacağımı biliyorum, ancak köşe sayımı% 50 oranında kolayca azaltmalıdır. veya tahminlerim doğru ise daha iyi olur.

Benim varsayım 6 listenin her birinin üzerinde durdukları eksene göre, daha sonra diğer iki eksene göre sıralanması olacaktır (bir bloğun üstündeki liste Y değerine, sonra X, sonra Z'ye göre sıralanır).

Bu tek başına, yüz şeritlerini kolayca birleştirebilirim, ancak mümkün olduğunda sadece şeritlerden daha fazlasını birleştirmek istiyorum. Bu açgözlü ağ algoritmasını okudum , ama bunu anlamakta çok zorlanıyorum.

Yani, sorum: Açıklandığı gibi yüzlerin birleştirilmesini gerçekleştirmek için (dinamik arazi / aydınlatma için kötü bir fikir olup olmadığını göz ardı etmek), belki de uygulanması daha basit bir algoritma var mı? Ayrıca, beni açgözlü algoritmadan çok daha basit bir şekilde (bir bağlantı veya açıklama) yürüyen bir cevabı da memnuniyetle kabul ediyorum.

Uygulaması daha kolaysa veya sadece şerit yapmaktan biraz daha iyi olsa bile, performansta hafif bir düşüş umursamıyorum. Çoğu algoritmanın dörtlü yerine üçgenlere odaklandığından ve bir 2D atlas'ı benim gibi kullandığımdan endişeleniyorum, mevcut becerilerime dayalı bir üçgen uygulayabileceğimi bilmiyorum.

PS: Ben zaten yığın başına frustum cull ve açıklandığı gibi, aynı zamanda katı bloklar arasında yüzleri cull. Henüz tıkanıklığı yok ve asla yapamam.

* Düzenleme: Muhtemelen bir adı olan kendi küçük tekniğimi uyguladım, ancak sadece dinledikleri eksenlere, ardından blok tipine ve ardından aydınlatma seviyesine göre sıralanmış 6 listemden geçiyorum. Onları yineliyorum, aynı anda yeni dikdörtgenler yaratıyorum ve aynı anda büyütüyorum (belirli bir eksene doğru ağır bir önyargı ile). Kesinlikle optimal değil, ama gerçekten oldukça hızlı ve tepe sayımı ortalama% 50'ye kadar düşürüyor. Byte56'nın yorumu gerçek bir cevabı düşündüğüm dolap, ama cevap / ödül için bunu seçemiyorum.

İşte benim hızlı ve basit bir şekilde herhangi bir optimizasyon olmadan tam ilk arazi ürettikten SONRA bu sorunu ele alıyorum. Verilen tüm kareler aynı görüntü, ışık seviyesi, normal vb. Varsayarsak, her renk farklı bir dörtlüdür. Listelerim sıralandığı gibi, bu çok kolay / hızlı bir yaklaşımdır.


Tüm optimizasyonlarınızdan sonra hala performans sorunlarıyla mı karşılaşıyorsunuz? Sorunların nerede olduğunu görmek için kodu profillemeyi denediniz mi?
MichaelHouse

@ Byte56 Oh, bu kesinlikle bir performans sorunu değil. Gelecekte gerçek bir oyun için kullanmayı öğrendiğimi koymaya çalıştığımda bir tane olabilir. Şimdilik, sadece öğrenmek istiyorum. Bunlardan hiçbirini belirtmedim çünkü sadece basitçe öğrenmek için bir şeyler öğrenmek istiyorsam daha az yardım alıyorum.
Efsane

Ben de söylemeliyim ki, eğer gerçekten bununla uygun bir oyun oynamaya çalışırsam görünür dünyanın BÜYÜK olmasını isteyeceğim. Karakterin Minecraft ve diğerleri gibi 2 blok yüksekliğinde ve 1 blok genişliğinde olmasını istemezdim, ama 3 / genişliğinde ve 6-9 yüksekliğinde. Muhtemelen statik arazi.
Efsane

1
Ah, tamam Tim. Açıklama için teşekkürler. Oyunum için motoru yaparken bu konuda biraz araştırma yaptım. Manzaram dinamik olduğundan, her şey değiştiğinde performans maliyetine değeceğini düşünmemiştim. Ancak, bu makaleden maksimal dikdörtgen sorunu hakkında bazı kullanımlar bulabilirsiniz . Temelde benzer yüzleri birleştirmek için bahsettiğiniz algoritma (belki açgözlü değil, optimal). İyi şanslar!
MichaelHouse

@ Byte56 Teşekkürler, çok takdir ediyorum. Bu, spot olmasa bile aradığım algoritmaya daha yakın görünüyor. Tüm maksimum dikdörtgenleri tek bir işlemle elde edip edemeyeceğimi görmek için biraz uğraşmak zorunda kalacağım. Hem soru hem de ayrıntılı bir cevabın gelecekte birçok kişiye yardımcı olabileceğini düşündüğüm için bunun için bir ödül de verebilirim.
Efsaneler

Yanıtlar:


4

Sadece şeritler yapmak veya en iyi şekilde dikdörtgen yapmak istiyorsunuz. Sizin için çözülebilecek veya faydalı olacak başka şekil yoktur.

Ayrıca, her parça için 6 liste tutarak, herhangi bir noktada, kardinal yönlerde parçalardan 5 liste ve her birinde en az 3 kullanacağınızı belirtmek isterim. Burada zaman harcıyorsunuz, video kartı bu optimizasyonu sadece sizin için yapmakla kalmaz, aynı zamanda kendiniz yapsanız bile, tüm yüzleri tek bir yerde tutmak ve normal olanı yön ile karşılaştırmak daha iyi olur. kamera (Vektörlerin araştırma DOT ürünü).

CaptainRedMuff'ın daha önce gördüğünüz Açgözlü ağ üzerindeki bağlantıları sorununuzun cevabıdır. Ayrıca, "Çizgili" ağlarla sonuçlanacağınızdan da anlaşılacaktır, ancak mükemmel etkilidirler ve daha uygun bir şeyle gelmek daha karmaşık olacaktır ve açgözlü ağın zaten çok karmaşık olduğunu ifade ettiniz.

Tek bir parça ile performans sorunları yaşıyorsanız, başka bir şeyin büyük ölçüde yanlış olduğunu düşündürüyor.

İlk tahminim, çok sık bir beraberlik operasyonu çağırmak olacaktır. Grafik kartına donanıma bağlı olarak saniyede yalnızca 50 ila 400 ~ çizim yapmasını söyleyebilirsiniz. .SetData veya .draw ____ Primitives'a kaç çağrı yapıyorsunuz?


Dikdörtgenler istediğim şey. Byte56, takip etmesi açgözlü olmaktan çok daha basit bir algoritma bağladı, ancak bir yorumu cevap olarak kabul edemiyorum. Bunun yerine yorum yaptığını varsaydım çünkü açıklamak yerine sadece bir algoritmaya bağlandı. Listelerimle ilgili ne demek istediğini bilmiyorum. Ben genellikle yığın başına 1-2 beraberlik çağrı var. Listelerim yığın başına bir arabellekte saklanır. Her kare için çizilecek aralıkları değiştiriyorum. Yanılıyor olabilirim ama GPU'ya gereksiz veri göndermek verimsiz görünüyor. Fazladan bir beraberlik veya yığın başına iki tane, gpu'ya daha fazla veri göndermek ve aynı zamanda cull'a zorlamaktan daha iyi görünüyor.
Efsane

Performans sorunları yaşamıyorum. Ben sadece bunları öğrenmekten zevk alıyorum. Bunu söylemek için sorumu düzenleyeceğim, ama Byte56'ya da söylediğim gibi, yapmaya çalıştığım şey aslında bir problemi çözmezse daha az yardım alırım. Sorunuzu cevaplamak için, şu anda en fazla 200-260 parça oluşturuyorum. Bu, çerçeve başına oldukça yaygın bir 500ish DrawIndexedPrimitives. Vsync olmadan düzenli olarak 100-130 FPS alıyorum, bu da saniyede 65.000 çağrı yapıyor. Kaba olmaya çalışmıyorum, ama az dediğin benim için anlamlı. Anlamayabilirim, bu yüzden yanlış anladıysam lütfen detaylandırın. Belki de XNA ile ilgili?
Efsane

Ah, üzgünüm, her karede değil, her karede söylemek istedim. Orada bir üst sınıra yaklaşıyorsunuz ve sadece arazideyseniz, neredeyse tükeniyorsunuz.
Phil

Yapabileceğim birkaç gelişmeyi düşünmeme sebep olarak cevabınızı + 1'ledim, ancak soru ile ilgisi yok. Ayrıca, olası çağrı sınırlaması bağlantısında
Reed'ten

400-500 alıntı yapılan makaleyi bir sınır olarak bulmam gerekecek. Hızlı bir google bana yardımcı olmadı.
Phil

0

Bağlantı verdiğiniz makale aslında ağ oluşturmak için bir algoritma vermez; olası çözümleri değerlendirmenin bir yolunu belirtir.

Genel olarak, makale iyi bir özet verir: 1) saf çözüm kötü, 2) optimal bir çözüm var, ancak hem yazmak hem de çalıştırmak için zaman alıcı olacak, 3) hızlı bir ayıklama çok daha iyi sonuçlar verir ( ve bu Minecraft'ın kendisi) ve son olarak 4) daha akıllı bir çözüm olabilir (açgözlü algoritma).

Eğer söz konusu görüntüde ima "çözüm" olduğunu açgözlü algoritma. Sorunuz "çözümünü doğru bir şekilde uyguladım mı?" cevap vermeliyim ki "bir çözüm vermedi; bunu kendiniz çözdünüz."

Çözümünüz daha iyi olabilir mi? Meh. Elbette. Muhtemelen buna değmez. Ben oklüzyon ayıklama veya LOD sonraki adımlar daha iyi olacağını düşünüyorum. Minecraft, yeraltında olsanız bile yüzeyi çizen çok sayıda döngüyü ve yüzeydeyken geniş mağara ve maden sistemleri ağlarını çizer. İyi bir ağ kopuşunuz olduğunda, evet, karanlık yüzeylerden kurtulmak iyi bir şey olabilir - ancak (örn.) Genellikle ekran kartınızın CPU üzerinde yapmaktan öte arka plan ayıklaması yapması daha hızlıdır.

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.