Dans les environnements "modernes", l' extension "NV Occlusion Query" fournit une méthode pour obtenir le nombre de fragments qui ont réussi le test de profondeur. Cependant, sur l'iPad / iPhone utilisant OpenGL ES, l'extension n'est pas disponible.
Quelle est l'approche la plus performante pour implémenter un comportement similaire dans le shader de fragments?
Certaines de mes idées:
Rendez l'objet complètement en blanc, puis comptez toutes les couleurs ensemble à l'aide d'un shader à deux passes où une ligne verticale est d'abord rendue et pour chaque fragment, le shader calcule la somme sur toute la ligne. Ensuite, un seul sommet est rendu dont le fragment additionne toutes les sommes partielles de la première passe. Ne semble pas très efficace.
Rendez l'objet complètement en blanc sur un fond noir. Sous-échantillonner récursivement, en abusant de l'interpolation linéaire matérielle entre les textures jusqu'à atteindre une résolution raisonnablement petite. Cela conduit à des fragments qui ont un niveau de gris en fonction du nombre de pixels blancs dans leur région correspondante. Est-ce même assez précis?
Utilisez des mipmaps et lisez simplement le pixel au niveau 1x1. Encore une fois, la question de la précision et s'il est même possible d'utiliser des textures sans puissance de deux.
Le problème avec ces approches est que le pipeline est bloqué, ce qui entraîne des problèmes de performances majeurs. Par conséquent, je recherche un moyen plus performant pour atteindre mon objectif.
Utilisation de l'extension EXT_OCCLUSION_QUERY_BOOLEAN
Apple a introduit EXT_OCCLUSION_QUERY_BOOLEAN dans iOS 5.0 pour 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 première phrase fait allusion à un comportement qui est exactement ce que je recherche: obtenir le nombre de pixels qui ont réussi le test de profondeur de manière asynchrone sans beaucoup de perte de performances. Cependant, le reste du document décrit uniquement comment obtenir des résultats booléens.
Est-il possible d'exploiter cette extension pour obtenir le nombre de pixels? Le matériel le prend-il en charge afin qu'il puisse y avoir une API cachée pour accéder au nombre de pixels?
D'autres extensions qui pourraient être exploitables seraient le débogage de fonctionnalités comme le nombre de fois où le shader de fragment a été invoqué (PSInvocations dans DirectX - je ne sais pas si quelque chose de similaire est disponible dans OpenGL ES). Cependant, cela entraînerait également un blocage du pipeline.
la source
Réponses:
Non et non. Eh bien, je supposais que si vous dessinez une série de triangles d'un pixel dans l'espace fenêtre, vous pourriez compter le nombre de valeurs booléennes que vous obtenez. Mais cela nécessiterait une requête distincte pour chaque pixel. Probablement pas la chose la plus rapide au monde.
S'il y a une "API cachée", vous n'y aurez pas accès (car elle est cachée), donc cela n'a pas d'importance. De plus, la nature de l'extension suggère déjà qu'il n'y en a pas. Après tout, si le matériel avait le nombre réel de fragments, pourquoi ne pas simplement l'exposer directement, comme le fait OpenGL de bureau? Si le matériel le supportait, ils auraient pu prendre ARB_occlusion_query et l'utiliser.
Mais ils ne l'ont pas fait. Ce qui suggère fortement qu'ils ne pouvaient pas.
la source
Les résultats sont retournés dans un GLuint, (peut également être GLint pour un appel différent) malheureusement, le résultat est toujours un 0 ou un 1, peut-être qu'ils le changeront pour enregistrer des frags à l'avenir.
il semble également qu'aucune personne sur Internet n'ait posté sur ces nouvelles extensions ... alors ici, elles sont correctement configurées ... ce qui n'est pas documenté nulle part pour autant que je sache ... vous pouvez imaginer comment elles irait dans votre code à partir de ce petit code sudo ici:
la source
GLint
n'est pas parce que le type dit que c'est un nombre entier du nombre de fragments qui passent. La spécificationQUERY_RESULT_EXT
indique clairement que l' état est une valeur booléenne; vous l'interrogez simplement comme un entier. C'estGL_FALSE
s'il a échoué et nonGL_FALSE
s'il a réussi.