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.
quelle
Antworten:
Nein und nein. Nun, ich nahm an, wenn Sie eine Reihe von Dreiecken mit einer Pixelgröße im Fensterraum zeichnen, können Sie zählen, wie viele Boolesche Werte Sie erhalten. Dies würde jedoch eine separate Abfrage für jedes einzelne Pixel erfordern . Wahrscheinlich nicht die schnellste Sache der Welt.
Wenn es eine "versteckte API" gibt, haben Sie keinen Zugriff darauf (da sie versteckt ist), es spielt also keine Rolle. Darüber hinaus deutet die Art der Erweiterung bereits darauf hin, dass dies nicht der Fall ist. Wenn die Hardware die tatsächliche Fragmentanzahl hatte, warum sollte sie dann nicht einfach direkt verfügbar gemacht werden, wie es Desktop OpenGL tut? Wenn die Hardware dies unterstützt hätte, hätten sie einfach ARB_occlusion_query nehmen und diese verwenden können.
Aber sie haben es nicht getan. Was stark darauf hindeutet, dass sie es nicht konnten.
quelle
Die Ergebnisse werden in einem GLuint zurückgegeben (kann auch GLint für einen anderen Aufruf sein). Leider ist das Ergebnis immer eine 0 oder eine 1, möglicherweise wird es in Zukunft geändert, um Frags zu registrieren.
Es sieht auch so aus, als hätte keine einzige Person im gesamten Internet über diese neuen Erweiterungen geschrieben ... also sind sie hier richtig eingerichtet ... was, soweit ich das beurteilen kann, nirgendwo dokumentiert ist ... Sie können sich vorstellen, wie sie sind würde in Ihren Code von diesem kleinen Sudo-Code hier gehen:
quelle
GLint
bedeutet dies nicht, dass es sich um eine Ganzzahl der Anzahl der übergebenen Fragmente handelt. Die Spezifikation ist ziemlich klar, dass derQUERY_RESULT_EXT
Zustand ein boolescher Wert ist; Sie fragen es einfach als Ganzzahl ab. Es ist,GL_FALSE
wenn es fehlgeschlagen ist und nicht,GL_FALSE
wenn es bestanden hat.