Tamponları çözmeli mi?


12

OpenGL ES 2 ile bazı testler yapıyorum ve bazı sorularım var, mevcut programım şöyle:

Init
-------
-> create index buffer
-> fill index buffer glBufferData 
-> create vertex buffer
-> fill vertex buffer glBufferData 

Draw
-------
 1. Apply vertex buffer

    -> Bind VAO
       -> bind vertex buffer
          - enable attributs (glVertexPointer, …)
       -> unbind vertex buffer
    -> Unbind VAO
    -> Bind VAO

 3. Apply index buffer
 4. Draw

Sorun

Verilen kod çökmesi, bazı araştırmalar sonra nedenini anladım: init bölümünde benim dizin arabelleğini ("dizin arabelleği glBufferData doldurun" sonra) bağlamak veya ilk "Bind VAO" önce onu bağlamak gerekir

Sorularım:

  • Dizin arabelleğimi VAO'ya (VAO hisse senedi dizin arabelleği) koyabilir miyim?
  • Her güncellemeden sonra arabellekleri ayırmak zorunda mıydım (glBufferData)?

Benim uygulamada her çerçeve (Exemple: Parçacıklar) güncellenen bazı tamponlar var bu yüzden böyle bir OpenGL yığını var:

-> bind buffer 1
-> update buffer 1
-> close buffer 1
-> bind buffer 1
-> draw

İlk 3 satır, son iki çizim nesnesi olan Vertex arabelleğini günceller ve bu şöyle bir şey olmalıdır:

-> bind buffer 1
-> update buffer 1
-> draw

Teşekkürler

Yanıtlar:


12

Gereksiz ciltleme / bağlama konusunda çok şey yapıyor gibi görünüyorsunuz. Bir VAO kullanıyorsanız, VAO'yu yalnızca kurarken ve geometri çizerken bağlamanız gerekir. VBO / IBO'yu yalnızca güncellemeniz gerektiğinde tekrar bağlarsınız.

Bir arabellek çizdikten veya güncelledikten sonra, mutlaka ciltten çıkarmanız gerekmez, ancak bağlı bırakılan arabelleklere yanlışlıkla yazmamak için bunu yapmak iyi bir fikir olabilir.

Şimdi yumruk işlem dizisini alarak, bu görmeyi umduğum genel sıra:

Başlangıçta:

  1. Bir VAO oluşturun ve bağlayın. Dizide bağladığınız VBO ve IBO, mevcut VAO (bu) ile ilişkilendirilir.

  2. Dizin arabelleği oluşturma ve bağlama.

    • Dizin arabelleğini ile doldurun glBufferData/glMapBuffer.
  3. Köşe tamponu oluştur ve bağla.

    • Tepe tamponunu doldurun glBufferData/glMapBuffer.
  4. glEnableVertexAttribArray/glVertexAttribPointerVb. İle köşe noktası özelliklerini ayarlayın .

  5. İsteğe bağlı olarak, tamponların ve VAO'nun yanlışlıkla değiştirilmesini önlemek için her şeyi çözün. Önce VAO'yu ayırmayı unutmayın . Örneğin:glBindVertexArray(0);

Çekilişte:

  1. Yalnızca arabellekleri çiziyorsanız :

    • VAO'yu bağlayın;
    • Çekiliş (ler) i gerçekleştirin.
  2. Güncelleniyor ve çiziliyorsa :

    • VAO, VBO, IBO'yu bağlayın;
    • Arabellekleri güncelleyin (tepe noktası özniteliklerinin güncellenmesi sadece köşe biçimi değiştiğinde gereklidir);
    • Çekiliş (ler) i gerçekleştirin.
  3. Tamponların ve VAO'nun yanlışlıkla değiştirilmesini önlemek için isteğe bağlı olarak çözme.

Bu kadar basit. Bu işlem sırası sorunsuz çalışmalıdır.


2
Deneylerime (2014) gerçek hayattaki vakalarla (ancak GPU'da darboğaz oluşturmayacak basit gölgelendiriciler) eklemek istiyorum, uygun sipariş verdikten sonra VAO kullanarak performans iyileştirmelerinin önemsiz olduğunu gördüm (<% 2 CPU tasarrufu) ardışık render çağrılarında (% 10 ila 33 CPU tasarrufu) aynı VBO kullanılırken VBO kurulumunu tamamen atlamak için render çağrıları uygulandı ve VAO ile bazı sürücü hatalarına çarptım, böylece varsayılan olarak kapattım. GPU'da darboğaz, CPU'yu mobilde bile boşta bekletmeye bırakan karmaşık gölgelendiriciler, MSAA, vb.
Stephane Hockenhull

2
Köşe verilerinin donanım tarafından desteklenmeyen bir şekilde yanlış hizalanmasının, GPU sürücülerini her kurulumda VBO verilerini yeniden sıralamaya zorlarken, sürücüler VAO ile bir kez yeniden düzenlenebileceğinden YMMV'yi değiştiremez. Yine de köşe verilerini hizalamak ve doldurmak için en iyisi.
Stephane Hockenhull

1
VAO neden her şeyden önce bağlanmamış olmalı?
Daniel Safari

@DanielSafari, kurulumdan sonra mı demek istiyorsun? Önce bir tamponu bağlarsanız (ciltleme tamponu 0 / null), mevcut VAO'daki o ciltleme noktasını temizler. Bu yüzden önce boş VAO ayarlanmalıdır.
glampert

@glampert - hayır, bağlamalar bu şekilde çalışmaz; tampon bağlaması glVertexAttribPointer çağrıldığında kullanılır, aksi halde kullanılmaz (istisna: GL_ELEMENT_ARRAY_BUFFER). GlVertexAttribPointer çağrınızdan sonra arabellek bağını değiştirmenin bir etkisi yoktur.
Maximus Minimus
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.