¿Es posible averiguar cuántos fragmentos lograron pasar la prueba de plantilla?

11

Tengo una aplicación OpenGL que utiliza pruebas de galería de símbolos de forma bastante extensa para representar formas irregulares (un poco como un simple CSG 2-D ). Si pudiera averiguar cuántos fragmentos pasaron la prueba de plantilla y realmente se procesaron, esto sería muy útil para simplificar algunos cálculos en el futuro. Específicamente, me permitiría determinar el área de la forma renderizada de forma gratuita en lugar de tener que aproximarla con una simulación de Monte Carlo más adelante.

Sé que existe un concepto similar para las primitivas emitidas por el sombreador de geometría, llamado transformación de retroalimentación . Me gustaría saber si existe un concepto similar para los fragmentos y la prueba de plantilla.

Martin Ender
fuente
Una solución cruda sería simplemente pintar un color contrastante sobre otro a través de la plantilla, guardar ese búfer y contar la cantidad de píxeles que se alteraron.
TheBuzzSaw
Hmm, la especificación dice que las consultas de oclusión cuentan el número de fragmentos que pasan la prueba de profundidad , pero fuera de mi cabeza no estoy seguro de cómo interactúa con la prueba de plantilla en este momento.
Chris dice que reinstala a Mónica el
@ChristianRau Parece que solo se contarán los fragmentos que pasan las pruebas de profundidad, pero se ignoran las pruebas de plantilla, descarte y alfa.
Maurice Laveaux
2
Sin embargo, @ChristianRau y Maurice, la especificación original ARB_occlusion_query dice explícitamente que cuenta las muestras que pasan las pruebas de profundidad y de plantilla. Vea también esta pregunta de StackOverflow .
Nathan Reed
@NathanReed Parece que estás a punto de escribir una respuesta.
Chris dice que reinstala a Mónica el

Respuestas:

10

Un posible enfoque podría ser el uso de Hardware Occlusion Query.

Puede utilizar los hechos de que, por especificación, la Prueba de plantilla se ejecuta antes de la prueba de profundidad, y solo los fragmentos que pasan la prueba de profundidad se cuentan en la Consulta de oclusión.

Un ejemplo simple (no probado) sería como:

    GLuint samples_query = 0;
    GLuint samples_passed = 0;
    glGenQueries(1, &samples_query);
    // Initialize your buffers and textures ...
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_STENCIL_TEST);

    // Set up the values on the stencil buffer ...

    // Now we count the fragments that pass the stencil test
    glDepthFunc(GL_ALWAYS); // Set up the depth test to always pass
    glBeginQuery(GL_SAMPLES_PASSED, samples_query);
    // Render your meshes here
    glEndQuery(GL_SAMPLES_PASSED);
    glGetQueryObjectuiv(samples_query, GL_QUERY_RESULT, &samples_passed);
    // samples_passed holds the number of fragments that passed the stencil test (if any)

    // Release your resources ...
    glDeleteQueries(1, &samples_query);

Tenga en cuenta que la llamada para obtener el número de muestras requerirá el vaciado de la tubería y esperará a que finalice la consulta. Si necesita un enfoque más asíncrono, puede consultar si la consulta de oclusión se realiza o no mediante:

    GLuint query_done = 0;
    glGetQueryObjectuiv(samples_query, GL_QUERY_RESULT_AVAILABLE, &query_done);
    if (query_done != 0)
        // Your query result is ready
    else
        // Maybe check the next frame?
Matteo Bertello
fuente
2

Si lo que le interesa es el área, puede reducir el tamaño del búfer de la plantilla hasta llegar a un píxel y deducir esa área de su color.

Los pasos serían:

  • Copie la plantilla a una textura, utilizando un formato con suficiente precisión.
  • Cargue un sombreador que genere un color proporcional al número de texels con un color dado.
  • Haga ping-pong entre los framebuffers para reducir el tamaño a la mitad hasta alcanzar un píxel.
  • El color del píxel es el porcentaje de la vista cubierta por el área: simplemente multiplíquelo por el área de la vista.
Julien Guertault
fuente