Voksel oluşturma için daha verimli olanı: önceden yapılmış VBO veya bir geometri gölgelendiricisi?


26

Oldukça statik bir voksel dizisi göz önüne alındığında, daha verimli olanı: voksel yüzlerini oluşturmak için bir VBO önceden üretmek için CPU kullanmak (şu an için yürüyen küpler gibi daha gelişmiş işleme biçimlerini yok sayarak) veya GPU'da bir geometri gölgelendirici kullanmak anında yüzleri?

Değişen vokselleri güncelleme konusunda endişeli değilim ama tabii ki VBO'ları yeniden inşa etmeniz gerekmediğinden GPU sürümünün bir yararı. Ayrıca, GS yaklaşımı biraz daha modern hissediyor :)

Öte yandan, bir GS'nin modern GPU'lardaki rasterleştirme boru hattıyla gerçekte nasıl çalıştığına dair detaylara bakmadım. Köşeleri bir tür akış önbelleğine mi aktarıyor, yoksa köşe noktaları normal GPU belleğine yazılıyor mu? İkincisi ise, o zaman anında üretim mevcut bant genişliğini ve işlem gücünü GPU görevlerinin geri kalanından azaltabilir ve işlemcinin CPU üzerinde yapması daha faydalı olur.

Yanıtlar:


9

Ben bir vecraft tipi sahneyi düşünüyorum, burada voksel ile gerçekten çokgenler kullanılarak yaratılmış bir bloklar dünyası kastediyorsunuz:

Bir geometri gölgelendirici kullanıyorsanız, voksel başına tam olarak üç yüze (veya her neyse) sahip olmaktan kaçınmak zor olacaktır.

Aynı dokuya sahip çok sayıda bitişik blokunuz varsa, VBO yaklaşımında (dejenere) şeridinizde çok daha az üçgen olması için dokuların döşemesini kullanabilirsiniz. Demek istediğim, 6x6 büyük bir çim çimen voksel alanı varsa, tüm üst kısmı 64 yerine sadece 2 üçgene çekebilirsiniz.

GS yaklaşımı ile, VBO yaklaşımıyla da oldukça basit olan bitişik voksellerin tıkadığı yüzlerin önemsiz şekilde toplanmasını yapamazsınız.

GS yaklaşımını denemedim ama VBO yaklaşımının yinelenen bitişik karoların birleştirilmesiyle çok iyi çalıştığını söyleyebilirim. Öğe endeksleriyle uğraşırken, köşeleri tekrar etmekten çok daha yavaş olduğunu buldum. Dünyanızı hoş küçük küplere bölerseniz, tipik olarak her bir köşe başına bileşen başına yalnızca bir bayt kullanabilir ve hatta doku bilgilerini ve normallerini (eksen hizalı bir küpün üzerindeki bir yüzün yalnızca 3 olası normları vardır) vb. Güzel ve hızlı köşe başına 4 bayt.

6 yüzün her biri için ayrı VBO'lar kullandım - yalnızca en fazla üçünü açıkça çizmeniz gerekir. Bu, genellikle minecraft tarzı voksellerin üst kısımlarında kullanılan farklı dokulara uyuyor. Çünkü her set için normal ve böyle bir üniforma var.

GL_REPEATYatay eksenli bir atlasta dikey olarak döşenmiş pixmaplerin kullanımı ve aynı atlasta piksellerin 90 derece döndürülmüş versiyonlarına sahip olduğumda, aynı aramada aynı VBO kullanarak muazzam miktarlarda farklı bloklar çizebileceğimi öğrendim. 6x6 çim alan örneğinde, bunu atlasımdaki sadece bir boyutta tekrarladığım için 12 üçgene böldüm.

Bunu çoğunlukla GS'nin bir gün oynamayı hayal edebileceğim bir şey olduğu entegre grafik yongalarının ve mobil cihazlarının en düşük ucunda çalışmaya başladım.


3
Her voksel için en fazla 3 yüz çizmeniz gerekir, ancak bakış açısına bağlı olarak her voksel için farklı yüzler çizmeniz gerekebilir, böylece optimizasyon o kadar kolay olmaz mı? Önceden yapılmış bir VBO birden fazla voksel içerecektir. Bakış açınız vokseller arasındaysa, birinin doğu tarafını ve diğerinin batı tarafını göreceksiniz. Bunun yardım etmesinin tek yolu, asıl geriye dönük yüzleri önemsiz bir şekilde temizleyebilmenizdir, ancak en kötü durum, yine de 6 taraftan 5'ini bir grup vokselde oluşturmanızdır. Bakış açınız VBO'nun eksenel sınırlarının dışındaysa , o zaman sadece 3 taraf oluşturmanız gerekir.
Bjorn Wesen

Bjorn üzerindeki nokta, onun yapılabilir. (Ama gerektiği gibi bloklar için VBOS oluşturma ve ben dahili yoktur yeniden ele am zaman yerine her zaman VBOS tüm dünyayı kalmadan daha kamera hareketleri; ben bu seçimler yapmak doğal bir zaman var bu yüzden)
Will

10

Anlık dizileri kullanan üçüncü seçenek ne olacak? Temel olarak, tek bir beraberlik çağrısı ile birçok pozisyonu (basit 8-vertex küpten yapılmış) çiziyorsunuz, pozisyonları (ve diğer verileri) VXEL-VBO'dan ( glVertexAttribDivisorOpenGL'de kullanarak) örnek nitelikler olarak alıyorsunuz. DX de buna sahip). Bu, geometri gölgelendirici yaklaşımından daha hızlı olabilir, ancak uygulama kodu (gölgelendirici olmayan) oldukça benzer olmalıdır, çünkü geometri gölgelendiricilerin yavaş olma ününe sahip olduklarını hatırlıyorum, çünkü onlarla hiç deneyimim yok (veya instancing) 2.1 donanım üzerinde.

Ancak yine de, geometri gölgelendiricileri veya örneklenmiş diziler, özellikle voksel verileri değişime maruz kaldığında, CPU tarafından oluşturulan voksel geometrisinden daha uygun olmalıdır. Dönüştürme geribildirimi (DX'te akış çıkışı?) İle birlikte bazı iyi GPU tabanlı toplama tekniklerini kurabilirsiniz.


Evet bu, bu sorunun en iyi çözümü. Neden başıma gelmedi? :)
Notabene 12:11

Bazı denemelerden sonra, size söyleyeyim, pişmiş geometrinin geniş bir kenar boşluğuyla her türlü atışı geçtiğini söylemek zorundayım. Yine de geometri gölgelendiricileri henüz denemedim.
Jari Komppa 13:11

@ JariKomppa, pişmiş geometri ile ne demek istediğinizi açıklayabilir misiniz?
Steven Lu,

Örnekler önceden çevrilmiş ve tek bir ağa kopyalanmıştır. Yüz küpü temsil eden bir ağa sahip olmak gibi.
Jari Komppa

@JariKomppa Aynı sonuçları gördüm, burada mesh oluşturmanın çok daha hızlı olduğu. Ancak gtx 680'de örnekleme seçeneği çok daha hızlı çalışıyor, garip görünüyor.
Levi H,

1

Geometri gölgelendirici sürümü bana çok daha iyi geliyor. Sadece sinek üzerinde vbo noktası ve yapı kutusu olabilir (giriş noktası, çıkış üçgeni akışı). Hızlı olacaktır (shader model 5 eq. DX11 modelinde mozaikleme ünitesini kullanırsanız daha da hızlı olacaktır) ve bant genişliğini son derece azaltacak, güzel ve temiz bir çözüm olacaktır.

GS hakkında. Köşe gölgelendiricisi ve piksel gölgelendiricisi arasına yerleştirilir ve çıktı köşesini (ilkel maddeler) akışını değiştirir. Köşe gölgelendiricisi yalnızca köşeler üzerinde çalışırken, geometri gölgelendiricisi tüm ilkellerde çalışır. Bu akışın çıkışı yalnızca piksel gölgelendiriciye gider (ve bu işlemden önce rasterleştirilir :)) ve kaydetmenin bir yolu yoktur. (Belki biraz çılgınca renderleme yaparak dokuları ayrıştırma ... belki de basit bir olasılık yoktur)

Performans notu: Geometri gölgelendiricisindeki her şeye erişebilmeli ve vertex gölgelendiricisini atlayabilmeli (sadece veri iletebilmeli). Ama bu en iyi yol değil. Daha iyi (daha hızlı), köşe gölgelendiricisinde olası dönüşümün çoğunu yapmak ve geometri gölgelendirici programını en aza indirmeye çalışmaktır. İhtiyacınız olursa döngü için kullanmaktan korkmayın (örneğin kutu oluşturma için). Derleyici sizin için açacak.


2
Geometri ve / veya tepe gölgelendiricideki bitişik vokselleri kontrol etmek ve köşeleri atmak veya tıkalıysa yüzleri atlamak iyi bir fikir olabilir. Aksi takdirde, GS çözümü bunun yerine kullanılan bant genişliğini artıracaktır.
Tamschi

Bant genişliği büyük bir problem olmayacak (deneyimlerime göre), ama elbette bu doğru. Ve GS'deki diğer ilkelleri arayamazsınız (bildiğimden :)).
Notabene

@Tamschi: evet bu problemi sadece bu soruyu yazdıktan sonra meydana geldi .. CPU-sürümü için katıların ortasındaki vokseller bastırıldı, ancak bu, GPU’da bir öneme sahip olmadan, önceden belirlenmiş bir rakam olmadan imkansız olabilir. ayırt edici ..
Bjorn Wesen 12:11

1
Köşe arabelleğini gölgelendiricideki bir isamplerBuffer veya usamplerBuffer'a bağlayabilir, ardından doku ile aramalar yapabilirsiniz (name_of_uniform, index). Başka bir seçenek de tamponu tek tip bir diziye bağlamak olacaktır, hangi köşe biçimini kullanmak istediğinizde size daha fazla özgürlük verir.
Tamschi
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.