En entornos "modernos", la extensión "NV Occlusion Query" proporciona un método para obtener el número de fragmentos que pasaron la prueba de profundidad. Sin embargo, en el iPad / iPhone que usa OpenGL ES, la extensión no está disponible.
¿Cuál es el enfoque más eficaz para implementar un comportamiento similar en el sombreador de fragmentos?
Algunas de mis ideas
Renderice el objeto completamente en blanco, luego cuente todos los colores juntos usando un sombreador de dos pasadas donde primero se representa una línea vertical y para cada fragmento el sombreador calcula la suma en toda la fila. Luego, se representa un único vértice cuyo fragmento suma todas las sumas parciales de la primera pasada. No parece ser muy eficiente.
Renderice el objeto completamente en blanco sobre un fondo negro. Reduzca la muestra de forma recursiva, abusando de la interpolación lineal de hardware entre texturas hasta obtener una resolución razonablemente pequeña. Esto conduce a fragmentos que tienen un nivel de escala de grises dependiendo del número de píxeles blancos en su región correspondiente. ¿Es esto lo suficientemente preciso?
Use mipmaps y simplemente lea el píxel en el nivel 1x1. Nuevamente, la cuestión de la precisión y si es posible usar texturas que no sean potencia de dos.
El problema con estos enfoques es que la tubería se estanca, lo que resulta en importantes problemas de rendimiento. Por lo tanto, estoy buscando una forma más eficaz de lograr mi objetivo.
Usando la extensión EXT_OCCLUSION_QUERY_BOOLEAN
Apple presentó EXT_OCCLUSION_QUERY_BOOLEAN en iOS 5.0 para iPad 2.
"4.1.6 Occlusion Queries Occlusion queries use query objects to track the number of fragments or samples that pass the depth test. An occlusion query can be started and finished by calling BeginQueryEXT and EndQueryEXT, respectively, with a target of ANY_SAMPLES_PASSED_EXT or ANY_SAMPLES_PASSED_CONSERVATIVE_EXT. When an occlusion query is started with the target ANY_SAMPLES_PASSED_EXT, the samples-boolean state maintained by the GL is set to FALSE. While that occlusion query is active, the samples-boolean state is set to TRUE if any fragment or sample passes the depth test. When the occlusion query finishes, the samples-boolean state of FALSE or TRUE is written to the corresponding query object as the query result value, and the query result for that object is marked as available. If the target of the query is ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, an implementation may choose to use a less precise version of the test which can additionally set the samples-boolean state to TRUE in some other implementation dependent cases."
La primera oración insinúa un comportamiento que es exactamente lo que estoy buscando: obtener el número de píxeles que pasaron la prueba de profundidad de manera asincrónica sin mucha pérdida de rendimiento. Sin embargo, el resto del documento describe solo cómo obtener resultados booleanos.
¿Es posible explotar esta extensión para obtener el recuento de píxeles? ¿El hardware lo admite para que pueda haber una API oculta para obtener acceso al recuento de píxeles?
Otras extensiones que podrían ser explotables serían las funciones de depuración, como la cantidad de veces que se invocó el sombreador de fragmentos (PSInvocations en DirectX, no estoy seguro de si hay algo similar disponible en OpenGL ES). Sin embargo, esto también daría como resultado un bloqueo de la tubería.
fuente
Respuestas:
No y no. Bueno, supongo que si dibujas una serie de triángulos de un píxel en el espacio de la ventana, podrías contar cuántos valores booleanos obtienes. Pero eso requeriría una consulta por separado para cada píxel. Probablemente no sea la cosa más rápida del mundo.
Si hay una "API oculta", no tendrá acceso a ella (ya que está oculta), por lo que no importa. Además, la naturaleza de la extensión ya sugiere que no existe. Después de todo, si el hardware tenía el conteo de fragmentos real, ¿por qué no simplemente exponerlo directamente, como lo hace OpenGL de escritorio? Si el hardware lo admitiera , podrían haber tomado ARB_occlusion_query y usarlo.
Pero no lo hicieron. Lo que sugiere fuertemente que no pudieron.
fuente
Lamentablemente, los resultados se devuelven en un GLuint (también puede ser GLint para una llamada diferente), el resultado siempre es un 0 o un 1, tal vez lo cambiarán para registrar frags en el futuro.
También parece que ni una sola persona en Internet ha publicado sobre estas nuevas extensiones ... así que aquí están configuradas correctamente ... lo que no está documentado en ninguna parte, por lo que puedo decir ... puedes imaginar cómo iría en su código de este pequeño código de sudo aquí:
fuente
GLint
no significa que sea un recuento entero del número de fragmentos que pasan. La especificación es bastante clara de que elQUERY_RESULT_EXT
estado es un valor booleano; solo debes consultarlo como un número entero. EsGL_FALSE
si falló y noGL_FALSE
si pasó.