OpenGL: VAO'ları bir VBO belirtmeden kullanmak mümkün mü


12

VAO'lar (Vertex Array Objects) hakkında bulabileceğim tüm eğitimlerde, vertex niteliklerini yapılandırarak ve bir VBO (Vertex Buffer Object) bağlayarak bunları nasıl kullanacaklarını gösterirler. Ancak, her arabellek aynı veri desenini (tepe noktası, uv, renk vb.) Kullantığı sabit bir gölgelendirici ile birlikte bir dizi VBO için yapılandırılacak bir VAO oluşturmak istiyorum. Bu nedenle, bir gölgelendirici kullanılarak çizilecek birden çok VBO için bir VAO oluşturmak istiyorum.

Bu konuda herhangi bir demo bulamadım, bu yüzden sadece denemeye karar verdim. Ama çalışmıyor ve glDrawArrayçağrıda çöküyor . Görünüşe göre VBO bağlı değil. İşte kullanıyorum kodu:

Rendering:

/* Prepare vertex attributes */
glBindVertexArrayOES(vao);

/* Upload the buffer to the GPU */
glBindBuffer(GL_ARRAY_BUFFER, pool->next());
glBufferSubData(GL_ARRAY_BUFFER, 0, parts * buffer.stride() * 6, buffer.getBuffer());

/* Draw the triangles */
glDrawArrays(GL_TRIANGLES, 0, parts * 6);

glBindVertexArrayOES(0);

VAO Oluşturma:

glBindVertexArrayOES(vao);

glEnableVertexAttribArray(ls.position);
glVertexAttribPointer(ls.position, 2, GL_FLOAT, GL_FALSE, buffer.stride(), 0);

glEnableVertexAttribArray(ls.color);
glVertexAttribPointer(ls.color, 3, GL_FLOAT, GL_FALSE, buffer.stride(), GL_BUFFER_OFFSET(buffer.dataTypeSize * 2));

glBindVertexArrayOES(0);

Nerede lsbasit bir structnitelik yerini saklar.

Rendering bölümünde glBindBufferve glBindVertexArrayOESçevresini değiştirmek işe yaramadı.

Yani soru şu: Bunu yapmak mümkün mü, yoksa her tampon için bir VAO oluşturmak zorunda mıyım? Ve her bir VBO için bir VAO oluşturmam gerekirse, VBO'nun verilerini glBufferSubDatabir VAO ile birlikte güncellemek mümkün mü?

Yanıtlar:


18

VAO'lar GL_ELEMENT_ARRAY_BUFFERbağlanma durumu dışında "glBindBuffer" durumunu içermez . Ne anlamıyorsun yani glBindBuffer(GL_ARRAY_BUFFER) şey yapmaz . Peki, oluşturma konusunda hiçbir şey yapmaz. Dene; glDraw * 'ı aramadan hemen önce glBindBuffer(GL_ARRAY_BUFFER, 0); oluşturma işleminiz iyi çalışır.

Yolu glVertexAttribPointerçalışmaları bunun GL_ARRAY_BUFFER bağlı ne bakar ki zaman glVertexAttribPointerdenir . Oluşturma zamanında değil. Daha sonra değil. Tam o anda. Hangi tampon nesnesi varsa onu alır ve onu VAO içinde kapsüllenmiş başka bir OpenGL durumu parçasında saklar.

Genel olarak, iki seçeneğiniz var, bunlardan biri yeni ve muhtemelen bu noktada kullanılmamalıdır.

İlk seçeneğiniz, aynı köşe biçimini kullanan tüm nesneleri (yani: tampon nesnesi ve ofset hariç her şey) aynı tampon nesnesine koymaktır . Temel olarak, aynı biçimi kullanan tüm nesneler için tüm köşeleri içeren dev bir dizi oluşturun.

Oluşturma zamanı geldiğinde, köşelerin bir bölümünü oluşturabilirsiniz. glDrawArraysgörüntülenmesi için bir dizi öğe alır ve aynı işlemi yapmak için endekslerinizi ayarlayabilirsiniz glDrawElements. Alternatif olarak, kullanabilirsiniz glDrawElementsBaseVertexiçin önyargı köşe bir her dizine eklenir ofset böylece. Bu uzaklık, büyük dizideki köşe noktasından önceki köşe sayısıdır.

Diğer alternatif GL 4.3'e eklenen nispeten yeni format öznitelik ayırma sistemini kullanmaktır . Biçimi sıfırlamadan arabellekleri değiştirmenize izin verir. Böylece tek bir VAO bağlarsınız, daha sonra gerektiğinde farklı tamponlarla değiştirirsiniz glBindVertexBuffer. Bu, ES 3.1 sürümünde de mevcuttur.


1
NV GL4.3 sürücüleri artık tam sürüm.
Maximus Minimus

GlVertexAttribPointer'ın çalışma şeklini açıkladığınız için çok teşekkür ederiz. Bu aydınlatıcıydı ve neden ve nasıl çalıştığını açıklıyor.
Martijn Courteaux

5

VAO glVertexAttribPointer durumunu saklar. VAO'nun değiştirilmesi geçerli glBindBuffer'ı veya glBindBuffer'ın değiştirilmesi VAO'yu etkilemez. Yalnızca glVertexAttribPointer çağrısı, çağrıda kullanılan arabelleği kaydederek VAO'yu etkiler.

Yani sorunuzun cevabı hayır.

Nesne sayısını azaltmak istiyorsanız, tüm mesh verilerinizi tek bir büyük VBO'ya koymak ve 'first' ve 'count' argümanlarını kullanarak mesh verilerinin glDrawArrays çağrısında VBO'da nerede yaşadığını belirtmektir.


VAO'lar üzerindeki internetteki tüm makaleler, bir VAO'nun bağlanmasının VBO'yu otomatik olarak bağladığını göstermektedir. Yani, bir VAO hem glVertexAttribPointer durumlarını hem de glBindBuffer durumunu tutan bir yapılandırma olduğunu düşünüyorum . Ve evet, bir VAO bağlı olduğunda bir VBO'nun bağlanması VAO'yu değiştirir. Bunu söylüyorum çünkü bunu test ettim ve etkili bir şekilde yapıyor. Bu bilgi nereden geliyor?
Martijn Courteaux

2
@MartijnCourteaux: "VAO'nun internetteki tüm makaleleri, bir VAO'nun bağlanmasının VBO'yu otomatik olarak bağladığını gösteriyor. " Hayır. Köşe özelliklerinde OpenGL Wiki yoktur. Gerçekten de, bana herhangi söylüyor internette tek bir makale göstermek glBindBufferdevlet dışında GL_ELEMENT_ARRAY_BUFFER bir vào bağlanarak değiştirilir.
Nicol Bolas

Diğer cevap glVertexAttribPointer yönteminin nasıl çalıştığını iyi açıkladı. O sırada bağlı VBO kullanır. Haklısın! Teşekkürler, şimdi anlıyorum.
Martijn Courteaux
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.