Tengo un código que recorre un conjunto de objetos y muestra instancias de esos objetos. La lista de objetos que necesita ser renderizada se almacena como un std :: map>, donde un objeto de la clase MeshResource contiene los vértices e índices con los datos reales, y un objeto de classMeshRenderer define el punto en el espacio donde la malla debe ser prestado en.
Mi código de representación es el siguiente:
glDisable(GL_BLEND);
glEnable(GL_CULL_FACE);
glDepthMask(GL_TRUE);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
for (std::map<MeshResource*, std::vector<MeshRenderer*> >::iterator it = renderables.begin(); it != renderables.end(); it++)
{
it->first->setupBeforeRendering();
cout << "<";
for (unsigned long i =0; i < it->second.size(); i++)
{
//Pass in an identity matrix to the vertex shader- used here only for debugging purposes; the real code correctly inputs any matrix.
uniformizeModelMatrix(Matrix4::IDENTITY);
/**
* StartHere fix rendering problem.
* Ruled out:
* Vertex buffers correctly.
* Index buffers correctly.
* Matrices correct?
*/
it->first->render();
}
it->first->cleanupAfterRendering();
}
geometryPassShader->disable();
glDepthMask(GL_FALSE);
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
La función en MeshResource que maneja la configuración de los uniformes es la siguiente:
void MeshResource::setupBeforeRendering()
{
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glEnableVertexAttribArray(3);
glEnableVertexAttribArray(4);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iboID);
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0); // Vertex position
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*) 12); // Vertex normal
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*) 24); // UV layer 0
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*) 32); // Vertex color
glVertexAttribPointer(4, 1, GL_UNSIGNED_SHORT, GL_FALSE, sizeof(Vertex), (const GLvoid*) 44); //Material index
}
El código que representa el objeto es este:
void MeshResource::render()
{
glDrawElements(GL_TRIANGLES, geometry->numIndices, GL_UNSIGNED_SHORT, 0);
}
Y el código que limpia es este:
void MeshResource::cleanupAfterRendering()
{
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
glDisableVertexAttribArray(3);
glDisableVertexAttribArray(4);
}
El resultado final de esto es que obtengo una pantalla negra, aunque el final de mi canal de renderizado después del código de renderizado (esencialmente solo dibujando ejes y líneas en la pantalla) funciona correctamente, así que estoy bastante seguro de que no es un problema con el paso de uniformes. Sin embargo, si cambio el código ligeramente para que el código de representación llame a la configuración inmediatamente antes de la representación, así:
void MeshResource::render()
{
setupBeforeRendering();
glDrawElements(GL_TRIANGLES, geometry->numIndices, GL_UNSIGNED_SHORT, 0);
}
El programa funciona según lo deseado. Sin embargo, no quiero tener que hacer esto, ya que mi objetivo es configurar los datos de vértices, materiales, etc. una vez por tipo de objeto y luego hacer que cada instancia actualice solo la información de transformación.
UniformizeModelMatrix funciona de la siguiente manera:
void RenderManager::uniformizeModelMatrix(Matrix4 matrix)
{
glBindBuffer(GL_UNIFORM_BUFFER, globalMatrixUBOID);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(Matrix4), matrix.ptr());
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
offsetof
al especificar atributos de vérticeRespuestas:
En primer lugar, OpenGL está lleno de cosas raras, por lo que un error del controlador, aunque sea poco probable, sigue siendo una opción: considere probar la aplicación en diferentes configuraciones (nVidia vs. AMD, controladores más antiguos) y otras pequeñas modificaciones de código. Por ejemplo, podría comenzar con la eliminación de "glBindBuffer (GL_UNIFORM_BUFFER, 0);" línea: parece no estar haciendo nada útil de todos modos.
Como todo aquí parece ser correcto, el problema probablemente no esté aquí. Hay dos opciones: gDEBugger y recorrer el código en el depurador de C ++. Parece que algo se reinicia justo antes de dibujar. En gDEBugger, hay una función de "historial de llamadas" que podría ayudarlo a ver qué llamadas se realizaron antes de la llamada de extracción y en qué orden.
Por cierto, le sugiero encarecidamente que envuelva cada llamada que devuelve errores con una macro que verifica todos los posibles errores y los arroja. Tiene que ser una macro para admitir la depuración extendida (archivo de impresión, línea y la línea de código defectuosa) que se puede deshabilitar en las versiones de lanzamiento. Si se rompe alguna regla secreta, dicha configuración debería advertirlo de inmediato.
fuente
Estoy bastante seguro de que el atributo debe unirse al búfer actual, por lo que no hay razón para rehacer este negocio con los atributos en cada marco a menos que reconstruya el búfer cada vez ...
Por lo tanto, probablemente debería hacerlo de una forma u otra, ya sea dejarlo o reconstruirlo todo en cada fotograma.
fuente
TL; DR: errores del controlador.
En mis pruebas a partir de hoy (octubre de 2016), la mayoría de los conductores no admiten adecuadamente los buffers uniformes .
Algunos no respetan,
glUniformBlockBinding
algunos no actualizan los datos uniformes (glBufferSubData
yglBufferData
) correctamente, donde las copias internas en caché de los sombreadores / GPU de dichos búferes no se mantienen coherentes.La forma en que lo entiendo (y la forma en que Nvidia también lo entiende)
glBindBufferBase
oglBindBufferRange
.glUniformBlockBinding(shader_id, shader_ubo_index, global_ubo_index);
esta configuración es por programa de sombreador , no se comparte globalmente.Nota: global_ubo_index NO es el nombre del objeto de búfer uniforme sino un índice en esa tabla global.
Esta "complejidad" (que es una gran característica para compartir UBO entre diferentes sombreadores, como los valores de iluminación) parece ser lo que la mayoría de los controladores de OpenGL se equivocan. Para ser justos, la redacción de la documentación de OpenGL no es la más inequívoca que podría ser.
Tuve que recurrir a usar uniformes viejos y simples para otros conductores.
Ambas capturas de pantalla con objetos de búfer uniformes, dos controladores diferentes:
fuente