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.
fonte
Respostas:
Não e não. Bem, eu suponho que se você desenhar uma série de triângulos do tamanho de um pixel no espaço da janela, poderá contar quantos valores booleanos obtém. Mas isso exigiria uma consulta separada para cada pixel. Provavelmente não é a coisa mais rápida do mundo.
Se houver uma "API oculta", você não terá acesso a ela (uma vez que está oculta), por isso não importa. Além disso, a natureza da extensão já sugere que não existe. Afinal, se o hardware tinha a contagem real de fragmentos, por que não apenas expô-lo diretamente, como o OpenGL da área de trabalho? Se o hardware o suportasse, eles poderiam apenas pegar o ARB_occlusion_query e usá-lo.
Mas eles não fizeram. O que sugere fortemente que eles não poderiam.
fonte
Os resultados são retornados em um GLuint (também pode ser GLint para uma chamada diferente), infelizmente, o resultado é sempre 0 ou 1, talvez eles o alterem para registrar frags no futuro.
também parece que nenhuma pessoa em toda a Internet postou sobre essas novas extensões ... então aqui elas estão configuradas corretamente ... o que não está documentado em nenhum lugar, tanto quanto eu saiba ... você pode imaginar como elas iria no seu código a partir deste pequeno código sudo aqui:
fonte
GLint
não significa que é uma contagem inteira do número de fragmentos que passam. A especificação é bastante clara de que oQUERY_RESULT_EXT
estado é um valor booleano; basta consultá-lo como um número inteiro. ÉGL_FALSE
se falhou e nãoGL_FALSE
se passou.