opengl 3d shader

Renderice varios modelos en OpenGL con una sola llamada al sorteo



3d shader (3)

Construí un motor gráfico 2D, y creé un sistema de procesamiento por lotes para él, así que, si tengo 1000 sprites con la misma textura, puedo dibujarlos con una sola llamada a openGl.

Esto se logra al poner en una única matriz de vértice vbo todos los vértices de todos los sprites con la misma textura.

En lugar de "imprimir estos vértices, imprimir estos vértices, imprimir estos vértices", hago "poner todos los vértices juntos, imprimir", solo para ser muy claro. Es bastante fácil, pero ahora estoy tratando de lograr lo mismo en 3D, y estoy teniendo un gran problema.

El problema es que estoy usando una matriz de proyección de vista de modelo para colocar y representar mis modelos, que es el enfoque común para representar un modelo en el espacio 3D.

Para cada modelo en pantalla, necesito pasar la matriz MVP al sombreador, para que pueda usarlo para transformar cada vértice en la posición correcta.

Si hiciera la transformación fuera del sombreador, sería ejecutada por la CPU, lo cual no es una buena idea, por razones obvias.

Pero el problema radica allí. Necesito pasar la matriz al sombreador, pero para cada modelo la matriz es diferente.

Así que no puedo hacer lo mismo que hice con los sprites 2d, porque cambiar un uniforme de sombreado requiere un sorteo cada vez.

Espero haber sido claro, tal vez tengas una buena idea que yo no tenía o que ya tenías el mismo problema. Sé de hecho que hay una solución en alguna parte, porque en un motor como Unity, puedes usar el mismo sombreador para varios modelos y salirte con la tuya


Además de instaurar y agregar otro atributo de vértice como identificación de objeto, me gustaría mencionar otra estrategia (que requiere OpenGL moderno, sin embargo):

La extensión ARB_multi_draw_indirect (en core desde GL 4.3) agrega comandos de dibujo indirectos . Estos comandos obtienen sus parámetros (número de vértices, índice de inicio, etc.) directamente desde otro objeto de búfer. Con estas funciones, se pueden dibujar muchos objetos diferentes con una única llamada de sorteo.

Sin embargo, como todavía quieres un estado por objeto como las matrices de transformación, esa característica no es suficiente. Pero en combinación con ARB_shader_draw_parameters (no en core GL todavía), obtienes el parámetro gl_DrawID , que se incrementará en uno para cada objeto individual en una llamada indirecta de varios sorteos. De esta forma, puede indexar en algunos UBO, o TBO, o SSBO (o lo que sea) donde almacena datos por objeto.


La respuesta depende de si los datos de vértice para cada elemento son idénticos o no. Si es así, puede usar instancias como en la respuesta de @ orost, usando glDrawElementsInstanced , e gl_InstanceID dentro del sombreado de vértices, y ese método debe ser preferido.

Sin embargo, si cada modelo 3D requiere datos de vértice diferentes (que es con frecuencia el caso), puede representarlos utilizando una sola llamada de extracción. Para hacer esto, debería agregar otra secuencia en sus datos de vértice con glVertexAttribPointer (y glEnableVertexAttribArray ). Esta corriente extra contendría el índice de la matriz dentro del buffer uniforme que debería usar el vértice al renderizar, de modo que cada malla dentro de la VBO tendría un índice idéntico en la corriente extra. El buffer uniforme contiene los mismos datos que en la configuración de instancias.

Tenga en cuenta que este método puede requerir un procesamiento de CPU adicional, si necesita volver a realizar el procesamiento por lotes; por ejemplo, un objeto dentro de un lote ya no se debe procesar. Si este proceso se requiere con frecuencia, se debe determinar si los elementos de lotes son realmente beneficiosos o no.


Existe una función exactamente como lo que estás buscando, y se llama instancing . Con la creación de instancias, almacena n matrices (o cualquier otra cosa que necesite) en un Buffer Uniforme y llama a glDrawElementsInstanced para dibujar n copias. En el sombreado, obtienes una entrada adicional gl_InstanceID , con la que gl_InstanceID en el Buffer Uniforme para buscar la matriz que necesitas para esa instancia en particular.

Puede leer más sobre la creación de instancias aquí: https://www.opengl.org/wiki/Vertex_Rendering#Instancing