In "modernen" Umgebungen bietet die Erweiterung "NV Occlusion Query" eine Methode zum Abrufen der Anzahl der Fragmente, die den Tiefentest bestanden haben. Auf dem iPad / iPhone mit OpenGL ES ist die Erweiterung jedoch nicht verfügbar.
Was ist der performanteste Ansatz, um ein ähnliches Verhalten im Fragment-Shader zu implementieren?
Einige meiner Ideen:
Rendern Sie das Objekt vollständig in Weiß und zählen Sie dann alle Farben mit einem Shader mit zwei Durchgängen zusammen, wobei zuerst eine vertikale Linie gerendert wird und der Shader für jedes Fragment die Summe über die gesamte Zeile berechnet. Dann wird ein einzelner Scheitelpunkt gerendert, dessen Fragment alle Teilsummen des ersten Durchgangs summiert. Scheint nicht sehr effizient zu sein.
Rendern Sie das Objekt vollständig in Weiß über einem schwarzen Hintergrund. Rekursives Downsample, Missbrauch der linearen Hardware-Interpolation zwischen Texturen bis zu einer relativ kleinen Auflösung. Dies führt zu Fragmenten, die abhängig von der Anzahl der weißen Pixel in ihrem entsprechenden Bereich einen Graustufenpegel aufweisen. Ist das überhaupt genau genug?
Verwenden Sie Mipmaps und lesen Sie einfach das Pixel auf der 1x1-Ebene. Wieder die Frage nach der Genauigkeit und ob es überhaupt möglich ist, Texturen ohne Zweierpotenz zu verwenden.
Das Problem bei diesen Ansätzen ist, dass die Pipeline blockiert wird, was zu erheblichen Leistungsproblemen führt. Daher suche ich nach einem performanteren Weg, um mein Ziel zu erreichen.
Verwenden der Erweiterung EXT_OCCLUSION_QUERY_BOOLEAN
Apple hat EXT_OCCLUSION_QUERY_BOOLEAN in iOS 5.0 für iPad 2 eingeführt.
"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."
Der erste Satz weist auf ein Verhalten hin, nach dem ich genau suche: Die Anzahl der Pixel, die den Tiefentest bestanden haben, wird asynchron ohne großen Leistungsverlust ermittelt. Der Rest des Dokuments beschreibt jedoch nur, wie boolesche Ergebnisse erzielt werden.
Ist es möglich, diese Erweiterung zu nutzen, um die Pixelanzahl zu ermitteln? Unterstützt die Hardware dies, sodass möglicherweise eine versteckte API vorhanden ist, um Zugriff auf die Pixelanzahl zu erhalten?
Andere Erweiterungen, die ausgenutzt werden könnten, wären Debugging-Funktionen wie die Häufigkeit, mit der der Fragment-Shader aufgerufen wurde (PSInvocations in DirectX - nicht sicher, ob in OpenGL ES etwas Ähnliches verfügbar ist). Dies würde jedoch auch zu einem Pipeline-Stillstand führen.