2012-08-06 24 views
80

Estoy empezando a aprender OpenGL hoy de este tutorial: http://openglbook.com/the-book/
Llegué al capítulo 2, donde dibujo un triángulo, y entiendo todo, excepto VAO (¿este acrónimo es correcto?). El tutorial tiene este código:¿Qué son los objetos de matrices vértice?

glGenVertexArrays(1, &VaoId); 
glBindVertexArray(VaoId); 

Si bien entiendo que el código es necesario, no tengo idea de lo que hace. Aunque nunca uso VaoId después de este punto (excepto para destruirlo), el código no funciona sin él. Estoy asumiendo que esto se debe a que es obligatorio estar obligado, pero no sé por qué. ¿Este código exacto solo necesita ser parte de cada programa OpenGL? El tutorial explica VAOS como:

un vértice objeto de matriz (o VAO) es un objeto que describe cómo se almacenan los atributos de vértices en un objeto de Vertex Buffer (o VBO). Esto significa que el VAO no es el objeto real que almacena los datos de vértice, sino el descriptor de los datos de vértice. Los atributos de vértice pueden describirse mediante la función glVertexAttribPointer y sus dos funciones hermanas glVertexAttribIPointer y glVertexAttribLPointer, la primera de las cuales exploraremos a continuación.

No entiendo cómo el VAO describe los atributos de los vértices. No los he descrito de ninguna manera. ¿Obtiene la información del glVertexAttribPointer? Creo que esto debe ser. ¿El VAO es simplemente un destino para la información de glVertexAttribPointer?

En una nota lateral, ¿es aceptable el tutorial que estoy siguiendo? ¿Hay algo de lo que debería tener cuidado o un mejor tutorial para seguir?

Respuesta

77

"Objeto Vertex Array" es traído a usted por el Subcomité OpenGL ARB para Silly Names.

Piense en ello como un objeto de geometría. (Como un programador de SGI Performer antiguo, los llamo geosets.) Las variables de instancia/miembros del objeto son su puntero de vértice, puntero normal, puntero de color, puntero N de atrot, ...

Cuando un VAO es primero Encuadernado, asigne estos miembros llamando al

glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer...; 
glEnableClientState(GL_NORMAL_ARRAY); glNormalPointer...; 

y así sucesivamente. Qué atributos están habilitados y los punteros que suministra están almacenados en el VAO.

Después de eso, cuando vuelve a vincular el VAO, todos esos atributos y punteros también se actualizan. Entonces, una llamada glBindVertexArray es equivalente a todo el código previamente necesario para configurar todos los atributos. Es útil para pasar geometría entre funciones o métodos sin tener que crear sus propias estructuras u objetos.

(Una configuración de tiempo, el uso múltiple es la forma más fácil de usar VAOS, pero también se puede cambiar atributos simplemente mediante la unión y haciendo más permitir que las llamadas/puntero. VAOS no son constantes.)

Más información en respuesta a las preguntas de Patrick:

El valor predeterminado para un VAO recién creado es que está vacío (AFAIK). No hay geometría en absoluto, ni siquiera vértices, por lo que si intentas dibujarlo, obtendrás un error de OpenGL. Esto es razonablemente sensato, como en "inicializar todo a False/NULL/zero".

Solo necesita glEnableClientState cuando configura cosas. El VAO recuerda el estado habilitar/deshabilitar para cada puntero.

Sí, el VAO almacenará glEnableVertexAttribArray y glVertexAttrib. Las matrices de vértice antiguo, normal, color ... son las mismas que las matrices de atributos, vértice == # 0 y así sucesivamente.

+41

'Objeto Vertex Array' es presentado por el Subcomité OpenGL ARB para Silly Names. ' Sí, un nombre tan tonto para un ** objeto ** que almacena enlaces de ** vertex ** ** array **. –

+0

Si lo entiendo correctamente, al llamar 'glGenVertexArrays (1, & VaoId);' y 'glBindVertexArray (VaoId);' crea un VAO con los valores por defecto para guardarlo de 'glEnableClientState'? ¿O estoy completamente malentendiéndote? En el futuro, ¿es probable que use mucho 'glEnableClientState'? – Patrick

+2

Además, todos los VAO están relacionados con 'glVertexAttribPointer' – Patrick

8

Vertex Array Objetos son como macros en programas de procesamiento de textos y similares. Una buena descripción se encuentra here.

macros solo recordar las acciones que hizo, como Activar este atributo, se unen a ese búfer, etc. Cuando se llama a glBindVertexArray(yourVAOId), simplemente repeticiones esas fijaciones puntero de atributos y los enlaces de amortiguamiento.

Por lo que su próxima llamada a dibujar utiliza lo que estaba obligado por el VAO.

VAO no almacene datos de vértice. No. Los datos de vértice se almacenan en un vértice buffer o en una matriz de memoria del cliente.

+12

-1: No son como macros. Si lo fueran, enlazar un VAO nuevo no deshabilitaría las matrices de vértices habilitadas por un VAO previo, a menos que el VAO nuevo haya "grabado" usted * deshabilitando explícitamente esas matrices. Los VAO, como * todos * los objetos OpenGL, mantienen * estado *, no los comandos. Los comandos simplemente * cambian * estado, pero los objetos vienen con el estado predeterminado establecido. Es por eso que vincular un VAO recién creado * * siempre * deshabilita todos los atributos. –

4

VAO es un objeto que representa la etapa de captación de vértices de la tubería OpenGL y se utiliza para suministrar entrada al sombreador de vértices.

Puede crear vértice tabla de objeto como éste

GLuint vao; 
glCreateVertexArrays(1, &vao); 
glBindVertexArray(vao); 

En primer lugar vamos a hacer un ejemplo sencillo. Considere un parámetro de dicha entrada en un código de sombreado

layout (location = 0) in vec4 offset; // input vertex attribute 

rellenar este atributo podemos utilizar

glVertexAttrib4fv(0, attrib); // updates the value of input attribute 0 

Aunque los almacenes de objetos de matriz vértice estos valores de atributos estáticos para usted, puede hacer mucho Más.

Después de crear el objeto de matriz de vértices podemos comenzar a completar su estado. Le pediremos a OpenGL que lo complete automáticamente utilizando los datos almacenados en un objeto de memoria intermedia que suministramos. Cada atributo de vértice obtiene datos de un búfer vinculado a uno de varios enlaces de búfer de vértices. Para este fin, utilizamos glVertexArrayAttribBinding(GLuint vao, GLuint attribindex, GLuint bindingindex). También utilizamos la función glVertexArrayVertexBuffer() para vincular un búfer a uno de los enlaces de búfer de vértices. Usamos la función glVertexArrayAttribFormat() para describir el diseño y el formato de los datos, y finalmente habilitamos el llenado automático del atributo llamando al glEnableVertexAttribArray().

Cuando se activa un atributo vértice, OpenGL alimentar datos al vertex shader basado en la información de formato y la ubicación que haya proporcionado con glVertexArrayVertexBuffer() y glVertexArrayAttribFormat(). Cuando el atributo está deshabilitado, al sombreador de vértices se le proporcionará la información estática que usted proporciona con una llamada al glVertexAttrib*().

// First, bind a vertex buffer to the VAO 
glVertexArrayVertexBuffer(vao, 0, buffer, 0, sizeof(vmath::vec4)); 

// Now, describe the data to OpenGL, tell it where it is, and turn on automatic 
// vertex fetching for the specified attribute 
glVertexArrayAttribFormat(vao, 0, 4, GL_FLOAT, GL_FALSE, 0); 

glEnableVertexArrayAttrib(vao, 0); 

Y código en un shader

layout (location = 0) in vec4 position; 

Después de todo lo que necesita para llamar a glDeleteVertexArrays(1, &vao).


Puede leer OpenGL SuperBible para comprenderlo mejor.

+2

Es bueno ver a las personas promocionar el uso de OpenGL de estilo DSA. –

Cuestiones relacionadas