Em ambientes "modernos", a extensão "NV Occlusion Query" fornece um método para obter o número de fragmentos que passaram no teste de profundidade. No entanto, no iPad / iPhone usando o OpenGL ES, a extensão não está disponível.
Qual é a abordagem de melhor desempenho para implementar um comportamento semelhante no shader de fragmento?
Algumas das minhas idéias:
Renderize o objeto completamente em branco, depois conte todas as cores usando um sombreador de duas passagens, onde primeiro uma linha vertical é renderizada e, para cada fragmento, o sombreador calcula a soma em toda a linha. Então, um único vértice é renderizado, cujo fragmento soma todas as somas parciais da primeira passagem. Não parece ser muito eficiente.
Renderize o objeto completamente em branco sobre um fundo preto. Reduza a amostra recursivamente, abusando da interpolação linear do hardware entre as texturas até atingir uma resolução razoavelmente pequena. Isso leva a fragmentos que possuem um nível de escala de cinza, dependendo do número de pixels brancos em sua região correspondente. Isso é preciso o suficiente?
Use mipmaps e simplesmente leia o pixel no nível 1x1. Novamente, a questão da precisão e se é possível usar texturas que não sejam de duas.
O problema com essas abordagens é que o pipeline fica parado, o que resulta em grandes problemas de desempenho. Portanto, estou procurando uma maneira mais eficiente de alcançar meu objetivo.
Usando a extensão EXT_OCCLUSION_QUERY_BOOLEAN
A Apple apresentou EXT_OCCLUSION_QUERY_BOOLEAN no 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."
A primeira frase sugere um comportamento exatamente o que estou procurando: obter o número de pixels que passaram no teste de profundidade de maneira assíncrona, sem muita perda de desempenho. No entanto, o restante do documento descreve apenas como obter resultados booleanos.
É possível explorar esta extensão para obter a contagem de pixels? O hardware o suporta para que possa haver API oculta para obter acesso à contagem de pixels?
Outras extensões que poderiam ser exploradas seriam recursos de depuração, como o número de vezes que o shader de fragmento foi chamado (PSInvocations no DirectX - não tenho certeza se algo semelhante está disponível no OpenGL ES). No entanto, isso também resultaria em uma paralisação do pipeline.