Terminolojinin bir kısmı biraz yanlış:
- A
Vertex Array
sadece float[]
köşe verilerini içeren bir dizidir (tipik olarak a ). Hiçbir şeye bağlı olmasına gerek yok. A Vertex Array Object
veya VAO ile karıştırılmamalı , daha sonra buna değineceğim
Buffer Object
Genellikle Vertex Buffer Object
köşeleri depolarken veya kısaca VBO olarak adlandırılan A , yalnızca a Buffer
.
- Hiçbir şey köşe dizisine geri kaydedilmez,
glVertexAttribPointer
tam olarak aynı şekilde çalışır glVertexPointer
veya glTexCoordPointer
çalışır, sadece adlandırılmış öznitelikler yerine kendi özniteliğinizi belirten bir sayı sağlamanız gerekir. Bu değeri olarak geçersiniz index
. Tüm glVertexAttribPointer
aramalarınız bir dahaki sefere glDrawArrays
veya aradığınızda sıraya alınır glDrawElements
. Bağlanmış bir VAO'nuz varsa, VAO tüm öznitelikleriniz için ayarları kaydedecektir.
Buradaki ana sorun, köşe özniteliklerini VAO'larla karıştırmanızdır. Köşe nitelikleri, çizim için köşeleri, metinleri, normalleri vb. Tanımlamanın yeni yoludur. VAO'lar depo durumu. Önce çizimin köşe nitelikleriyle nasıl çalıştığını açıklayacağım, ardından VAO'larla yöntem çağrılarının sayısını nasıl azaltabileceğinizi açıklayacağım:
- Gölgelendiricide kullanmadan önce bir niteliği etkinleştirmelisiniz. Örneğin, köşeleri bir gölgelendiriciye göndermek istiyorsanız, büyük olasılıkla onu ilk öznitelik olarak göndereceksiniz, 0. Bu nedenle, oluşturmadan önce, ile etkinleştirmeniz gerekir
glEnableVertexAttribArray(0);
.
- Artık bir öznitelik etkinleştirildiğine göre, kullanacağı verileri tanımlamanız gerekir. Bunu yapmak için VBO'nuzu bağlamanız gerekir -
glBindBuffer(GL_ARRAY_BUFFER, myBuffer);
.
- Ve şimdi - özelliğini tanımlayabiliriz
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
. Parametre sırasına göre: 0, tanımladığınız özniteliktir, 3 her köşenin boyutudur GL_FLOAT
, türdür, GL_FALSE
her köşeyi normalleştirmemek anlamına gelir, son 2 sıfır, köşelerde adım veya kayma olmadığı anlamına gelir.
- Onunla bir şeyler çizin -
glDrawArrays(GL_TRIANGLES, 0, 6);
- Bir sonraki çizeceğiniz şey 0 özelliğini kullanmayabilir (gerçekçi olarak kullanacaktır, ancak bu bir örnektir), böylece onu devre dışı bırakabiliriz -
glDisableVertexAttribArray(0);
Bunu glUseProgram()
çağrılara sarın ve gölgelendiricilerle düzgün şekilde çalışan bir işleme sistemine sahip olun. Ancak 5 farklı niteliğiniz, köşeleriniz, metin kodlarınız, normalleriniz, renk ve ışık haritası koordinatınız olduğunu varsayalım. Her şeyden önce, glVertexAttribPointer
bu özelliklerin her biri için tek bir çağrı yaparsınız ve önceden tüm özellikleri etkinleştirmeniz gerekir. Diyelim ki 0-4 niteliklerini listelediğim gibi tanımladınız. Hepsini şu şekilde etkinleştirirsiniz:
for (int i = 0; i < 5; i++)
glEnableVertexAttribArray(i);
Sonra da (eğer bir VBO ve kullanım uzaklıklar / adımlarla saklayabilir sürece) her özellik için farklı VBOS bağlamak zorunda kalacak, o zaman 5 farklı yapmak gerekir glVertexAttribPointer
gelen çağrıları glVertexAttribPointer(0,...);
için glVertexAttribPointer(4,...);
sırasıyla lightmap koordinatlara köşeler için.
Umarım bu sistem tek başına mantıklıdır. Şimdi, bu tür bir işleme yaparken yöntem çağrılarının sayısını azaltmak için onları nasıl kullanacağımı açıklamak için VAO'lara geçeceğim. Bir VAO kullanmanın gerekli olmadığını unutmayın.
A Vertex Array Object
veya VAO, tüm glVertexAttribPointer
aramaların ve her glVertexAttribPointer
arama yapıldığında hedeflenen VBO'ların durumunu saklamak için kullanılır .
Bir çağrı ile bir tane oluşturursunuz glGenVertexArrays
. İhtiyaç duyduğunuz her şeyi bir VAO'da saklamak için, ona bağlayın glBindVertexArray
ve ardından tam bir çizim çağrısı yapın . Tüm beraberlik bağlama çağrıları yakalanır ve VAO tarafından saklanır. VAO'nun bağlantısını şu şekilde çözebilirsiniz:glBindVertexArray(0);
Eğer nesne çizmek istediğinizde Şimdi, gerek yok tüm VBO bağlar veya yeniden çağrı glVertexAttribPointer
aramaları, sadece birlikte vào bağlamak gerekir glBindVertexArray
sonra çağrı glDrawArrays
veya glDrawElements
ve size sanki aynı şeyi çizim yapacak tüm bu yöntem çağrılarını yapıyorlardı. Muhtemelen daha sonra da VAO'nun bağlantısını çözmek istersiniz.
VAO’yu çözdüğünüzde, tüm durum, VAO’yu bağlamadan önceki haline döner. VAO bağlıyken yaptığınız herhangi bir değişikliğin saklanıp saklanmadığından emin değilim, ancak bu bir test programıyla kolayca anlaşılabilir. Sanırım glBindVertexArray(0);
"varsayılan" VAO'ya bağlayıcı olduğunu düşünebilirsiniz ...
Güncelleme: Biri gerçek bir çekiliş çağrısı ihtiyacına dikkatimi çekti. Görünüşe göre, VAO'yu kurarken aslında bir TAM çizim çağrısı yapmanıza gerek yok, sadece tüm bağlayıcı şeyler. Neden daha önce gerekli olduğunu düşündüğümü bilmiyorum ama şimdi düzeltildi.