online - opengl ejemplos c++
¿Cuándo está lo que está vinculado a un VAO? (2)
Eso es un montón de sub-preguntas. Pero dado que esta es un área que a menudo confunde a los entusiastas más recientes de OpenGL, permítanme intentar proporcionar un contenido que, con suerte, ayudará a más personas. Intencionalmente hojearé algunos detalles, como los atributos de vértice que no provienen de un búfer, para evitar escribir un libro aquí.
La clave para entender es que una VAO es una colección de estados . No posee ningún dato. Es VBO que poseen datos de vértice. Un VAO, por otro lado, contiene todo el estado utilizado para describir de dónde obtiene una llamada de dibujo sus atributos de vértice. Esto incluye, para cada atributo:
- Si está habilitado.
- En qué búfer se almacena el atributo.
- En qué desplazamiento en el búfer comienzan los datos.
- El espaciado entre los atributos posteriores (también conocido como la zancada).
- El tipo de los datos.
- El número de componentes.
Además, solo una vez:
- El búfer de matriz de elementos está vinculado.
Al asignar esto a las llamadas a la API, las siguientes llamadas cambian al estado seguido por el VAO actualmente vinculado:
-
glEnableVertexAttribArray(...)
-
glDisableVertexAttribArray(...)
-
glVertexAttribPointer(...)
-
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ...)
Tenga en cuenta que esto no incluye el enlace actual de GL_ARRAY_BUFFER
. El búfer utilizado para cada atributo se realiza un seguimiento indirecto, en función de qué búfer se enlazó cuando se llama a glVertexAttribPointer()
para el atributo específico.
Esto debería establecer la base para las subpreguntas específicas:
Si creo un VAO, ¿se puede enlazar algo antes de enlazar el VAO?
No. El VAO debe estar vinculado antes de que pueda modificar cualquier estado almacenado en él.
(Si creo un VBO ahora, ¿está vinculado a la VAO?)
No. Puede vincular un VBO antes de vincular un VAO, y llenar el VBO con datos usando glBufferData()
. Un VBO es esencialmente un simple contenedor de datos. Pero cualquier tipo de configuración de atributo de vértice rastreada en el VAO solo se puede realizar después de que el VAO esté vinculado.
Si obtengo una ubicación de atributo, ¿está vinculada a la VAO?
No, glGetAttribLocation()
solo hace lo que sugiere el nombre, que es obtener una ubicación de atributo. No cambia ningún estado. Utilizará las ubicaciones de atributos para llamadas como glEnableVertexAttribArray()
y glVertexAttribPointer()
.
¿O sucede después de habilitarlo ... o después de configurarlo?
La asociación de un atributo con un VBO dado se establece cuando llama a glVertexAttribPointer()
mientras el VBO dado está vinculado.
Supongo que los EBO se comportan como VBO, así que espero que se apliquen las mismas "reglas".
Sobre todo, pero no del todo. El enlace GL_ELEMENT_ARRAY_BUFFER
es parte del estado almacenado en el VAO. Esto tiene sentido porque solo hay un elemento en el búfer de matriz utilizado para una llamada de sorteo (mientras que los atributos de vértice podrían provenir de múltiples búferes de matriz diferentes), y no hay una llamada separada que especifique que "use los datos de índice del búfer de matriz de elementos actualmente enlazado ", como glVertexAttribPointer()
especifica" usar los datos de vértice del búfer de matriz actualmente enlazado ". En su lugar, eso sucede implícitamente cuando se llama a glDrawElements()
. Por lo tanto, el búfer de matriz de elementos debe vincularse en el momento de la llamada al sorteo, y este enlace es parte del estado VAO.
Los uniformes deben comportarse como globales, por lo que no deben verse afectados por VAO en absoluto.
Correcto. Los uniformes están asociados con programas de sombreado, no con VAO.
Si "vinculo" un VBO a un VAO, y luego desenrollo el VBO, ¿se separa de un VAO?
No. Creo que esto ya está cubierto por las explicaciones anteriores.
Si tengo un VBO que está vinculado a varios VAO, ¿qué sucede cuando desengancho ese VBO?
Como nada sucede con una VAO, todavía nada con múltiples VAO.
¿Qué pasa cuando borro un VBO? ¿Se borra de todos los VAOs? ¿O todavía tienen "referencias pendientes" a ese VBO?
Este es uno de los rincones más oscuros de OpenGL. Si puede recitar las reglas de eliminación exactas para todos los tipos de objetos (no son todas iguales), ha alcanzado el nivel avanzado ... En este caso, el VBO se desvincula automáticamente del VAO actualmente vinculado , pero no de otros VAO. que no están actualmente vinculados. Si otros VAO tienen referencias al VBO, el VBO permanecerá activo hasta que se rompan todos esos enlaces, o se eliminen los VAO.
Sin embargo, si los VAOs enlazan atributos y VBO, y los atributos toman un parámetro de programa, ¿puedo reutilizar los VAO entre programas?
Sí, puedes usar un VAO para múltiples programas. El estado del programa y el estado VAO son independientes. La ubicación del atributo de vértice en el programa especifica qué atributo de vértice se usa para obtener los valores de cada attribute
/ variable en el sombreado de vértice.
Siempre que varios programas utilicen las mismas ubicaciones para los mismos atributos, puede usar la misma VAO. Para hacer esto posible, es posible que desee especificar la ubicación del atributo para cada programa utilizando la directiva layout (location=...)
del sombreado de vértice, o llamando a glBindAttribLocation()
antes de vincular el programa.
¿Hay alguna manera de imprimir bastante la máquina de estados OpenGL?
Hay glGet*()
que te permiten recuperar casi todo el estado actual de OpenGL. No es conveniente, pero está todo disponible. Muchas plataformas / proveedores también proporcionan herramientas de desarrollador que le permiten ver el estado de OpenGL en un punto dado en la ejecución de su programa.
Supongamos que alguien me da un VAO, y tengo que dibujarlo. ¿Hay alguna forma de saber si debería llamar a glDrawArrays o glDrawElements?
Este es un escenario inusual. La mayoría de las veces, crea el VAO, por lo que sabe cómo dibujarlo. O si alguien más lo creó, le pedirías que lo dibuje. Pero si realmente lo necesita, puede obtener el búfer de matriz de elementos actualmente enlazados con glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, ...)
.
He estado aprendiendo OpenGL durante tres días y puedo hacer cosas, pero tengo ganas de copiarlas sin saber lo que estoy haciendo. Pienso seriamente que no entiendo cuándo es exactamente qué (VBO, atributos, ...) está vinculado a un objeto de matriz de vértices (VAO), y no he encontrado ningún recurso que aclare estos aspectos en detalle.
En particular, estos son algunos de mis problemas. Si creo un VAO:
GLuint vao;
glGenVertexArrays(1, &vao);
¿Se puede atar algo a él antes de atar el VAO? (Si creo un VBO ahora, ¿está vinculado a la VAO?)
glBindVertexArray(vao);
Después de enlazar el VAO, si creo un VBO:
GLuint vbo;
glGenBuffers(1, &vbo);
¿Está vinculado a la VAO? ¿O sucede cuando lo atan?
glBindVertexArray(vbo);
¿O tal vez cuando le copie algo?
Si obtengo una ubicación de atributo:
att = glGetAttribLocation(program_id, "name");
¿Está vinculado a la VAO? O sucede después de habilitarlo:
glEnableVertexAttribArray(att);
... o después de configurarlo:
glVertexAttribPointer(att, ...);
?
Supongo que los EBO se comportan como VBO, así que espero que se apliquen las mismas "reglas".
Los uniformes deben comportarse como globales, por lo que no deben verse afectados por VAO en absoluto.
Ahora, sobre el desvinculación:
Si "vinculo" un VBO a un VAO, y luego desenrollo el VBO, ¿se separa de un VAO?
Si tengo un VBO que está vinculado a varios VAO, ¿qué sucede cuando desengancho ese VBO?
Y sobre liberar recursos:
¿Qué pasa cuando borro un VBO? ¿Se borra de todos los VAOs? ¿O todavía tienen "referencias pendientes" a ese VBO?
Y sobre los programas:
IIUC Puedo reutilizar los VBO entre programas. Sin embargo, si los VAOs enlazan atributos y VBO, y los atributos toman un parámetro de programa, ¿puedo reutilizar los VAO entre programas? ¿Por qué los atributos toman un parámetro de programa?
Y sobre la depuración:
¿Hay alguna manera de imprimir bastante la máquina de estados OpenGL? Me gustaría una forma de conocer los programas que se han vinculado, con qué sombreadores, qué VAO hay, qué VBO están vinculados a qué VAO, qué atributos están vinculados a qué VAO y VBO se han configurado. ¿Están habilitados? que uniformes hay ahi ...
Y sobre dibujar llamadas:
Supongamos que alguien me da un VAO, y tengo que dibujarlo. ¿Hay alguna forma de saber si debería llamar a glDrawArrays o glDrawElements? ¿Puedo consultar de alguna manera esta información de un VAO? Tal vez junto con los tamaños de mis VBO almacenados allí?
La tabla VAO se puede encontrar en la sección Tablas de estado de la especificación
en el código psuedo se ve así:
struct VAO{
GL_INT element_array_binding; //IBO used for glDrawElements and friends
char* label;//for debugging
struct{//per attribute values
bool enabled; //whether to use a VBO for it
//corresponding to the values passed into glVertexAttribPointer call
int size;
unsigned int stride;
GL_ENUM type;
bool normalized;
bool integer; //unconverted integers
bool long; //double precision
void* offset;
int bufferBinding;//GL_ARRAY_BUFFER bound at time of glVertexAttribPointer call
int attributeDiviser; //as used for instancing
} attributes[MAX_VERTEX_ATTRIBS];
};
Cabe destacar que está ausente el estado del programa (cuál está vinculado, los valores uniformes, etc.)