tutorial programas iluminacion for example español ejemplos beginners c++ opengl

c++ - programas - opengl tutorial for beginners



¿Cuál es el papel de glBindVertexArrays vs glBindBuffer y cuál es su relación? (5)

Desde una perspectiva de bajo nivel, puede pensar que una matriz tiene dos partes:

  • Información sobre el tamaño, la forma y el tipo de la matriz (por ejemplo, números de punto flotante de 32 bits, que contienen filas de vectores con cuatro elementos cada uno).

  • La matriz de datos, que es poco más que una gran cantidad de bytes.

A pesar de que el concepto de bajo nivel ha permanecido casi igual, la forma en que especifica las matrices ha cambiado varias veces a lo largo de los años.

OpenGL 3.0 / ARB_vertex_array_object

Esta es la forma en que probablemente deberías estar haciendo las cosas hoy. Es muy raro encontrar personas que no puedan ejecutar OpenGL 3.x y aún así tener dinero para gastar en su software.

Un objeto de memoria intermedia en OpenGL es una gran cantidad de bits. Piense en el búfer "activo" como solo una variable global, y hay un conjunto de funciones que usan el búfer activo en lugar de usar un parámetro. Estas variables de estado globales son el lado feo de OpenGL (antes del acceso directo al estado, que se trata a continuación).

GLuint buffer; // Generate a name for a new buffer. // e.g. buffer = 2 glGenBuffers(1, &buffer); // Make the new buffer active, creating it if necessary. // Kind of like: // if (opengl->buffers[buffer] == null) // opengl->buffers[buffer] = new Buffer() // opengl->current_array_buffer = opengl->buffers[buffer] glBindBuffer(GL_ARRAY_BUFFER, buffer); // Upload a bunch of data into the active array buffer // Kind of like: // opengl->current_array_buffer->data = new byte[sizeof(points)] // memcpy(opengl->current_array_buffer->data, points, sizeof(points)) glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);

Ahora, su sombreador de vértices típico toma los vértices como entrada, no una gran cantidad de bits. Por lo tanto, debe especificar cómo se decodifica la burbuja de bits (el búfer) en vértices. Ese es el trabajo de la matriz. Del mismo modo, hay una matriz "activa" que se puede considerar simplemente como una variable global:

GLuint array; // Generate a name for a new array. glGenVertexArrays(1, &array); // Make the new array active, creating it if necessary. glBindVertexArray(array); // Make the buffer the active array buffer. glBindBuffer(GL_ARRAY_BUFFER, buffer); // Attach the active buffer to the active array, // as an array of vectors with 4 floats each. // Kind of like: // opengl->current_vertex_array->attributes[attr] = { // type = GL_FLOAT, // size = 4, // data = opengl->current_array_buffer // } glVertexAttribPointer(attr, 4, GL_FLOAT, GL_FALSE, 0, 0); // Enable the vertex attribute glEnableVertexAttribArray(attr);

OpenGL 2.0 (a la antigua usanza)

En OpenGL 2.x, no había matrices de vértices y los datos eran solo globales. Aún tenía que llamar a glVertexAttribPointer() y glEnableVertexAttribArray() , pero tenía que llamarlos cada vez que usaba un búfer. En OpenGL 3.x, acaba de configurar la matriz una vez.

Volviendo a OpenGL 1.5, podría usar búferes, pero utilizó una función separada para vincular cada tipo de datos. Por ejemplo, glVertexPointer() era para datos de vértice, y glNormalPointer() era para datos normales. Antes de OpenGL 1.5, no había búferes, pero podría usar punteros en la memoria de su aplicación.

OpenGL 4.3 / ARB_vertex_attrib_binding

En 4.3, o si tiene la extensión ARB_vertex_attrib_binding, puede especificar el formato de atributo y los datos de atributo por separado. Esto es bueno porque te permite cambiar fácilmente una matriz de vértices entre diferentes almacenamientos intermedios.

GLuint array; // Generate a name for a new array array. glGenVertexArrays(1, &array); // Make the new array active, creating it if necessary. glBindVertexArray(array); // Enable my attributes glEnableVertexAttribArray(loc_attrib); glEnableVertexAttribArray(normal_attrib); glEnableVertexAttribArray(texcoord_attrib); // Set up the formats for my attributes glVertexAttribFormat(loc_attrib, 3, GL_FLOAT, GL_FALSE, 0); glVertexAttribFormat(normal_attrib, 3, GL_FLOAT, GL_FALSE, 12); glVertexAttribFormat(texcoord_attrib, 2, GL_FLOAT, GL_FALSE, 24); // Make my attributes all use binding 0 glVertexAttribBinding(loc_attrib, 0); glVertexAttribBinding(normal_attrib, 0); glVertexAttribBinding(texcoord_attrib, 0); // Quickly bind all attributes to use "buffer" // This replaces several calls to glVertexAttribPointer() // Note: you don''t need to bind the buffer first! Nice! glBindVertexBuffer(0, buffer, 0, 32); // Quickly bind all attributes to use "buffer2" glBindVertexBuffer(0, buffer2, 0, 32);

OpenGL 4.5 / ARB_direct_state_access

En OpenGL 4.5, o si tiene la extensión ARB_direct_state_access, ya no necesita llamar a glBindBuffer() o glBindVertexArray() solo para configurar cosas ... especifica las matrices y los buffers directamente. Solo necesita enlazar la matriz al final para dibujarla.

GLuint array; // Generate a name for the array and create it. // Note that glGenVertexArrays() won''t work here. glCreateVertexArrays(1, &array); // Instead of binding it, we pass it to the functions below. // Enable my attributes glEnableVertexArrayAttrib(array, loc_attrib); glEnableVertexArrayAttrib(array, normal_attrib); glEnableVertexArrayAttrib(array, texcoord_attrib); // Set up the formats for my attributes glVertexArrayAttribFormat(array, loc_attrib, 3, GL_FLOAT, GL_FALSE, 0); glVertexArrayAttribFormat(array, normal_attrib, 3, GL_FLOAT, GL_FALSE, 12); glVertexArrayAttribFormat(array, texcoord_attrib, 2, GL_FLOAT, GL_FALSE, 24); // Make my attributes all use binding 0 glVertexArrayAttribBinding(array, loc_attrib, 0); glVertexArrayAttribBinding(array, normal_attrib, 0); glVertexArrayAttribBinding(array, texcoord_attrib, 0); // Quickly bind all attributes to use "buffer" glVertexArrayVertexBuffer(array, 0, buffer, 0, 32); // Quickly bind all attributes to use "buffer2" glVertexArrayVertexBuffer(array, 0, buffer2, 0, 32); // You still have to bind the array to draw. glBindVertexArray(array); glDrawArrays(...);

ARB_direct_state_access es bueno por muchas razones. Puede olvidarse de las matrices y los búferes vinculantes (excepto cuando dibuje) para no tener que pensar en las variables globales ocultas que OpenGL está rastreando para usted. Puede olvidarse de la diferencia entre "generar un nombre para un objeto" y "crear un objeto" porque glCreateBuffer() y glCreateArray() hacen ambas cosas al mismo tiempo.

Vulkan

Vulkan va incluso más lejos y te hace escribir código como el pseudocódigo que escribí arriba. Entonces verás algo como:

// This defines part of a "vertex array", sort of VkVertexInputAttributeDescription attrib[3]; attrib[0].location = 0; // Feed data into shader input #0 attrib[0].binding = 0; // Get data from buffer bound to slot #0 attrib[0].format = VK_FORMAT_R32G32B32_SFLOAT; attrib[0].offset = 0; // repeat for attrib[1], attrib[2]

Soy nuevo en OpenGL y programación de gráficos. He estado leyendo un libro de texto que ha sido muy minucioso y está bien escrito hasta ahora. Sin embargo, he tocado un punto en el código que no entiendo muy bien y me gustaría dar sentido a estas líneas antes de siga adelante.

GLuint abuffer; glGenVertexArrays(1, &abuffer); glBindVertexArray(abuffer);

GLuint buffer; glGenBuffers(1, &buffer); glBindBuffer(GL_ARRAY_BUFFER, buffer); glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);

El libro explica que las tres primeras líneas están creando un objeto de matriz de vértices , que se utiliza para agrupar los datos asociados con una matriz de vértices. La segunda línea encuentra un nombre no utilizado (supongo que un identificador de entero sin signo almacenado en abuffer ) y la tercera línea crea el objeto / lo hace activo.

El libro explica que las líneas 4ª-7ª crean un objeto de memoria intermedia para almacenar nuestros datos, con la 5ª línea que nos da un identificador no utilizado (similar a la línea 2 para el objeto de matriz de vértices?), La 6ª línea que crea el almacenamiento intermedio y la 7ª línea asignando suficiente memoria en la CPU y creando un puntero a nuestros datos (puntos) para GL_STATIC_DRAW .

¿Qué significa que el objeto esté activo? ¿Cuándo utilizarías posteriormente abuffer ? ¿Qué significa para una matriz de vértices agrupar los datos asociados y cuándo se asociaron los datos con este objeto de matriz de vértices?

Estoy confundido acerca de la relación entre abuffer y buffer . Estoy confundido acerca de cuál es la relación de la matriz de vértices con el objeto de memoria intermedia, y en qué punto se forma esa relación. No estoy seguro de si están, de hecho, relacionados, pero se presentan en el libro de texto uno inmediatamente después del otro.

Cualquier ayuda sería apreciada. Gracias.


La relación se crea al llamar a glVertexAttribPointer .

GL_VERTEX_ARRAY_BINDING y GL_ARRAY_BUFFER_BINDING son constantes pero pueden señalar el estado global del enlace. Me refiero al estado, no a la constante (naranja) en la imagen. Usa glGet para encontrar diferentes estados globales.

VertexArray está agrupando información (incluido el búfer de matriz) sobre un vértice o muchos vértices paralelos.

Utilice GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING con glGetVertexAttrib para encontrar qué atributo de matriz de almacenamiento está configurado.

glBindBuffer(GL_ARRAY_BUFFER establece el estado global GL_ARRAY_BUFFER_BINDING

glBindVertexArray establece el estado global GL_VERTEX_ARRAY_BINDING


No hay relación entre VertexArray y VBO.

Una matriz de vértices asigna la memoria en la RAM y envía un puntero a la API. VBO asigna la memoria en la tarjeta gráfica, la memoria del sistema no tiene dirección. Si necesita acceder a los datos vbo desde el sistema, primero debe copiarlos de vbo al sistema.

Además, en las versiones más nuevas de OpenGL, las matrices de vértices se eliminan por completo (se depuran en 3.0, se eliminan en 3.1)


OpenGL es una interfaz con estado. Es malo, anticuado y feo, pero eso es un legado para ti.

Un objeto de matriz de vértices es una colección de enlaces de buffer que el controlador puede usar para obtener los datos para las llamadas al sorteo, la mayoría de los tutoriales solo usan el uno y nunca explican cómo usar varios VAO.

Un enlace de buffer le dice a OpenGL que use ese buffer para métodos relacionados, en particular para los métodos glVertexAttribPointer .


Tu interpretación del libro no es completamente correcta. Vertex Array Objects no almacena datos. Son una clase de objetos conocidos como contenedores, como objetos Framebuffer. Puede adjuntar / asociar otros objetos con ellos, pero nunca almacenan los datos ellos mismos. Como tales, no son un recurso que se pueda compartir en el contexto.

Básicamente, los Objetos de matriz de vértices encapsulan el estado de matriz de vértices en OpenGL 3.0. A partir de OpenGL 3.1 (en lugar de GL_ARB_compatibility ) y OpenGL 3.2+ Core profiles, debe tener un VAO distinto de cero enlazado en todo momento para que glVertexAttribPointer (...) comandos como glVertexAttribPointer (...) o glDrawArrays (...) . El VAO encuadernado forma el contexto necesario para estos comandos y almacena el estado persistentemente.

En versiones anteriores de GL (y compatibilidad), el estado almacenado por VAO era una parte de la máquina de estado global.

También vale la pena mencionar que el enlace "actual" para GL_ARRAY_BUFFER no es uno de los estados que los VAO siguen. Si bien este enlace lo usan comandos como glVertexAttribPointer (...) , los VAO no almacenan el enlace, solo almacenan punteros (la extensión GL_ARB_vertex_attrib_binding introducida junto con GL 4.3 lo complica un poco, así que GL_ARB_vertex_attrib_binding por simplicidad).

Los VAO recuerdan lo que está ligado a GL_ELEMENT_ARRAY_BUFFER , de modo que los comandos de dibujo indexados como glDrawElements (...) funcionan como cabría esperar ( p . Ej., Los VAO reutilizan el último elemento del conjunto de búferes de matriz).