Terminolojinin bir kısmı biraz yanlış:
- A
Vertex Arraysadece float[]köşe verilerini içeren bir dizidir (tipik olarak a ). Hiçbir şeye bağlı olmasına gerek yok. A Vertex Array Objectveya VAO ile karıştırılmamalı , daha sonra buna değineceğim
Buffer ObjectGenellikle Vertex Buffer Objectköşeleri depolarken veya kısaca VBO olarak adlandırılan A , yalnızca a Buffer.
- Hiçbir şey köşe dizisine geri kaydedilmez,
glVertexAttribPointertam olarak aynı şekilde çalışır glVertexPointerveya 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 glVertexAttribPointeraramalarınız bir dahaki sefere glDrawArraysveya 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_FALSEher 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, glVertexAttribPointerbu ö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 glVertexAttribPointergelen ç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 Objectveya VAO, tüm glVertexAttribPointeraramaların ve her glVertexAttribPointerarama 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 glBindVertexArrayve 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ı glVertexAttribPointeraramaları, sadece birlikte vào bağlamak gerekir glBindVertexArraysonra çağrı glDrawArraysveya glDrawElementsve 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.