2010-12-13 10 views
5

İnsanlar sürekli en azından Vertex Array'ları kullanmamı söylüyor. Ama ben 3d dünyasında bir nesneyi konumlandırmak için glTranslatef/glRotatef ile glPushMatrix() kullanıyorum beri iyi bir fikir değil düşünüyorum.OpenGL: Vertex dizilerini kullanarak derinlemesine sıralama ile verimli render sistemi nasıl tasarlanır?

glPushMatrix()'u kullanmayı bırakıp dünyadaki döndürülen/taşınan vertex konumlarını "el ile" hesaplamalıyım ve daha sonra vertex verilerini bir köşe dizisine itmeli ve sonra hepsini bir seferde oluşturmalı mıyım? ben de derinlik boylanmalıdır ekrandaki tüm nesneler için farklı doku yüzey kullandığımızda

Ama bütün bu daha da berbat alacak.

Böylece:

  1. I hem de doku yüzeyi kimliği ile her nesnenin saklanması gerekir.
  2. Tüm görünen nesneleri Z konumlarına göre sıralıyorum (oyun yalnızca aşağıdan yukarıya bakacak ve tüm nesneler düz olacak şekilde).
  3. yeni tampon oluşturma ve bu tampon içine normaldir sadece tepe/texcoord/renk/kopyalama:
  4. doku yüzeyi kimliği önceki kimliğinden değişti her zaman, ben bağlayacak bu sıralanan dizide gider
  5. Doğru doku kimliğine:
  6. Topladığım vertex verilerini yükleyin.
  7. Geçici köşe dizisi için kullanılan arabelleği boşaltın.
  8. Başta sıraladığım tüm verileri gözden geçirene kadar adım 4-7'yi tekrarlayın.
  9. Sıralı dizi verilerimi serbest bırakın ve 1-9 arasındaki adımları yineleyin.

Am i Doğru yapıyor?

Ayrıca, sıralayacağım nesneler için veri yapısını nasıl tasarlamalıyım? Örneğin, her nesne için vertex verilerini depolamak std::vector kullanmak iyidir? Yoksa daha iyi bir alternatif var mı? Ben std::vector Bütün bu veriler gibi görünür depolamak için bunu düşünüyordum: 4. adıma,

Ayrıca
struct GameObject { 
    int TexID; 
    float z; // we will sort by this 
    vector<VTCNStruct> VertexData; // store each point of the object here (including color/normal/texcoord points). 
}; 

vector<GameObject> GameObjectBuffer; // push all sortable objects here 

,: bu durumda mevcut std::vector kullanmak mümkündür? Ben verteks dizi benim GPU göndermek için new float[100] gibi ham diziler kullanmanız gerektiğini, ya da her zaman doku kimliği değişiklikleri her defasında yeni tampon oluşturmadan bir şekilde (zaten verimli) benim zaten mevcut sıralanmış std::vector kullanabilirsiniz ?

cevap

2

Nesne başına bir köşe dizisi tutmalısınız. GlTranslatef/glRotatef, vb. Kullanmayın. Bunun yerine, dönüşümleri tek bir matrise dönüştürün. Nesnelerinizi sıralamak için bu matrisi kullanın. Sonra nesneleri matris dönüştürebilir, köşe dizisini çizerek, sonra dönüştürme matrisini açarak nesneleri önden arkaya doğru çizin.

Bu yaklaşım, sürekli olarak grafik olarak tepe verilerini depolamak için dizileri serbest anlamına gelir.

Std :: vektör kullanılarak ilgili olarak, çoğu uygulamaları, yapabilirsiniz böylece, içinde bir ham C dizi kullanımı Bu diziye ulaşmak için & myVec [0]. Ancak, std :: vektör dizisini yeniden düzenleyebildiğinden ve bu durumda kalıcı göstericinizin artık geçerli olmayacağından bu göstericiyi kullanmaya çalışmayın.

+0

başına 4 * 32 bit "Nesne başına bir tepe dizisi tutmalı" - tüm bu zeki mi? Nesnelerimin çoğu sadece dörtlü olduğu için ve GPU'ya (renkli/normal diziler aracılığıyla) daha fazla veri göndermediğimde, bu daha fazla bant genişliği kullanmıyor, ama aynı zamanda her nesne arasında köşe dizisi yükleme komutları göndermem gerekiyordu . – Newbie

+0

Dönüşümlerimi bir matrise nasıl daraltırım? Ayrıca, arkadan öne demek istemiyor musun? Yani, temelde 'glPushMatrix()' i saklayacağımı mı düşünüyorsun ama glBegin/glEnd yerine köşe dizileri kullanacağım? Eğer VBO kullanmak istediysem, önerdiğin aynı yaklaşımı tutmalı mıyım? – Newbie

+0

Acemi bir OpenGL programcısı değilim, ama inanıyorum ki, Josh en önce en arkadaki en uzaktaki nesneyi (örn., Ekrana dolaba dolacak) nesneler çizmelisiniz. DÜZENLEME - Dönüşümleri tek bir matrise dönüştürerek, hem dönüş/hem de döndürme/dönüşüme bir dönüşüm elde etmek için bazı matematik hilelerini kullanabileceğinizi düşünüyorum. birinde düştü. – ZachS

11

Pleae hemen glBegin/glEnd terk, bu önerilmemektedir ve OpenGL-4 çıkarıldı. Verteks arabellek nesnelerini kullanırsanız, verteks dizilerini kesinlikle kullanmalısınız.

Acil mod (glBegin/glEnd) kullanıldığında, OpenGL sürücüsünün işlev çağrılarından bir köşe dizisi oluşturması gerekir. Ne kadar çok uzaklığın geleceği belli olmadığı için, bu bellek bir çok kez yeniden tahsis edilir (GPU'ların glBegin/glEnd arasındaki çağrıları doğrudan gerçekleştirdiği süreler uzun sürebilir).

Bir köşe dizisi kullanmak asla acil moddan daha az performans göstermez. Birden fazla nesnenin geometrilerini tek bir köşe dizisine koymak tamamdır, bunları köşe dizin listelerinden ayırabilirsiniz. Vertex indeks listeleri de tampon nesnelerde saklanabilir. Nesneleri çizmek arasında model görünümü matrisini ayarlayın.

Sıralama sipariş followig gibi olmalıdır: opak ve saydam nesneler

  1. bölün. Saydamlığı sırala
  2. GL nesnelerini değiştirmenin en pahalı olduğu için opqa'ları GL nesnelerine (doku, gölgelendirici, materyaller vb.) Göre sıralayın. uzak ve çizmek söz konusu sipariş
  3. sırala translucents içinde uzaktan yakına ve çizmek bu sırayla Sen tampon yukarı/downloads ile ilgilenmek çalışmamalıdır

te sıralama yakınında her farklı GL nesne grubu için

  • . Sadece vertex verilerini bir kez yükleyin ve sonra dizin dizilerini ve bunların gönderilme sırasını ayarlayın. Kullanılabilir OpenGL belleği hakkında endişelenmenize gerek yok, zorlanan bir sınır yok. Verileriniz GPU RAM'e uymuyorsa, sürücü sistem belleğine takmaktan sorumludur - bu nedenle OpenGL nesnelerini ilk önce açmanız gerekir, çünkü OpenGL nesnelerini (glBindTexture, glBindBuffer vb.) Her değiştirdiğinizde sürücü takas etmek gerekiyor, bu yüzden bu takas işlemlerini minimumda tutmak istersiniz.
    • Endeksi dizisi

      : vertex başına 16 bit (16 bit boyut endeksleri en nelerdir acil modu tarafından gönderilen en azından aramaları daha indeks diziler şeklinde GPU gönderilen veri miktarı çok daha az olacaktır ölçülebilir).

    • Acil mod çağrısı: tepe

  • +0

    'Dizin dizisi: vertex' VS başına 16 bit. 'Hemen mod çağrısı: 4 * 32 bit perdelik 'Yanlış hesaplama yoktur, çünkü köşe dizileriyle ayrıca tepe verisini göndermeniz gerekir.GlVertex3f (1,1,1) gönderdiğimi söyleyelim, fonksiyon adresi için 3 * 32 bit + 32bit alacak? ama köşe dizileri ile, x bit, 16 bit, toplam kaydedilmiş bit = 16 alır 3 * 32 bit + indeksi alır z göndermek zorunda? Ya da neyi özledim? Bildiğim kadarıyla sana GPU içine can not mağaza köşe dizileri biliyorum, o yüzden tekrar tekrar o has not changed bile köşe verilerin her kareyi göndermek zorunda olduğu ...? bir köşe Tampon nesne tepe dizileri kullanılarak – Newbie

    +0

    gerçekten grafik işlemcisi bellekte depolanır. VBO kullanmadan, çoğu modern sürücü bunları in-situ oluşturma eğilimindedir, çünkü modern GPU'lar bu şekilde çalışır. – datenwolf

    +0

    in-situ? Ne demek istiyorsun, modern GPU'lar tüm verteks dizileri otomatik olarak VBO'ya dönüştürüyor? – Newbie

    İlgili konular