Error de instancia de OpenGL Fast-Object

8

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);
}
HJ Media Studios
fuente
Tengo una configuración casi idéntica para renderizar mis modelos. Excepto que mi llamada de renderización vincula el búfer y establece los punteros de atributos cada vez. ¿Te encuentras con problemas de rendimiento con esto? Funciona muy rápido para mí.
MichaelHouse
No me he encontrado con problemas de rendimiento a menos que tenga cientos de objetos idénticos en la pantalla, pero aún así, no puedo entender qué está mal aquí, y sería genial saber por qué el código no funciona como se esperaba.
HJ Media Studios
1
Solo necesitamos llamar la atención de @NicolBolas, él es el experto residente de OpenGL.
MichaelHouse
Podría ser una buena idea usar offsetofal especificar atributos de vértice
JBeurer

Respuestas:

2

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.

serpiente5
fuente
55
Evitaría vincular al sitio de Gremedy. Esa versión de gDEBugger es antigua, sin soporte y con muchos errores. developer.amd.com/tools/heterogeneous-computing/amd-gdebugger es la versión actualizada compatible con AMD, con soporte para Windows y Linux (desafortunadamente no OS X). También hay otras herramientas fantásticas de depuración / perfilado GL en el sitio de AMD, sin mencionar las herramientas que ofrecen NVIDIA e Intel.
Sean Middleditch
0

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.

Yudrist
fuente
0

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, glUniformBlockBindingalgunos no actualizan los datos uniformes ( glBufferSubDatay glBufferData) 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)

  • Enlace / Asigne su Objeto Uniform Buffer a una tabla global compartida por todos los sombreadores dentro del controlador / GPU OpenGL usando glBindBufferBaseo glBindBufferRange.
  • La asignación de los accesos uniformes del búfer del sombreador a una entrada en esa tabla global usando 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:

Errores uniformes de amortiguamiento

Stephane Hockenhull
fuente
¿Con qué controladores probaste? Que plataforma
akaltar el