Ottenere il numero di frammenti che hanno superato il test di profondità


8

In ambienti "moderni", l' estensione "NV Occlusion Query" fornisce un metodo per ottenere il numero di frammenti che hanno superato il test di profondità. Tuttavia, su iPad / iPhone che utilizza OpenGL ES, l'estensione non è disponibile.

Qual è l'approccio più efficace per implementare un comportamento simile nello shader di frammenti?

Alcune delle mie idee:

  • Rendi l'oggetto completamente in bianco, quindi conta tutti i colori insieme usando uno shader a due passaggi in cui viene rappresentata prima una linea verticale e per ogni frammento lo shader calcola la somma sull'intera riga. Quindi, viene visualizzato un singolo vertice il cui frammento somma tutte le somme parziali del primo passaggio. Non sembra essere molto efficiente.

  • Rende l'oggetto completamente in bianco su uno sfondo nero. Sottocampionare ricorsivamente, abusando dell'interpolazione lineare hardware tra le trame fino a raggiungere una risoluzione ragionevolmente piccola. Questo porta a frammenti che hanno un livello di scala di grigi a seconda del numero di pixel bianchi nella loro regione corrispondente. È anche abbastanza preciso?

  • Usa le mipmap e leggi semplicemente il pixel sul livello 1x1. Ancora una volta la questione dell'accuratezza e se è persino possibile usare trame senza potenza di due.

Il problema con questi approcci è che la pipeline viene bloccata e ciò comporta gravi problemi di prestazioni. Pertanto, sto cercando un modo più performante per raggiungere il mio obiettivo.

Utilizzo dell'estensione EXT_OCCLUSION_QUERY_BOOLEAN

Apple ha introdotto EXT_OCCLUSION_QUERY_BOOLEAN in iOS 5.0 per 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 prima frase suggerisce un comportamento che è esattamente quello che sto cercando: ottenere il numero di pixel che hanno superato il test di profondità in modo asincrono senza troppe perdite di prestazioni. Tuttavia, il resto del documento descrive solo come ottenere risultati booleani.

È possibile sfruttare questa estensione per ottenere il conteggio dei pixel? L'hardware lo supporta in modo che ci possa essere un'API nascosta per ottenere l'accesso al conteggio dei pixel?

Altre estensioni che potrebbero essere sfruttabili sarebbero funzioni di debug come il numero di volte in cui è stato invocato il framment shader (PSInvocations in DirectX - non sono sicuro che qualcosa di simile sia disponibile in OpenGL ES). Tuttavia, ciò comporterebbe anche uno stallo della pipeline.


Qual è l'effetto finale che stai cercando di ottenere?
Tetrad,

Ho bisogno del conteggio dei pixel non per un effetto di rendering, ma per il calcolo. Voglio usarlo per calcolare i pesi delle particelle in un filtro antiparticolato.
Etan,

Apple supporta AMD_performance_monitor? In caso affermativo, potresti essere in grado di trovare il contatore che mostra i pixel passati. Nota che questo è molto, molto specifico per il dispositivo anche se riesci a farlo funzionare.
Jari Komppa,

Il problema con AMD_performance_monitor sarebbe che non è asincrono, quindi la perdita di prestazioni sarebbe anche lì poiché devo aspettare tra i frame per sapere che le invocazioni dal frame successivo non avranno già effetto sui contatori delle prestazioni.
Etan,

Inoltre, AMD_performance_monitor non è disponibile.
Etan,

Risposte:


1

È possibile sfruttare questa estensione per ottenere il conteggio dei pixel? L'hardware lo supporta in modo che ci possa essere un'API nascosta per ottenere l'accesso al numero di pixel?

No e no. Beh, suppongo che se disegni una serie di triangoli di un pixel nello spazio della finestra, potresti contare quanti valori booleani ottieni. Ma ciò richiederebbe una query separata per ogni pixel. Probabilmente non è la cosa più veloce del mondo.

Se esiste un'API nascosta, non avrai accesso ad essa (poiché è nascosta), quindi non importa. Inoltre, la natura dell'estensione suggerisce già che non esiste. Dopotutto, se l'hardware aveva il conteggio effettivo dei frammenti, perché non semplicemente esporlo direttamente, come fa OpenGL sul desktop? Se l'hardware lo supportasse, avrebbero potuto prendere ARB_occlusion_query e usarlo.

Ma non lo fecero. Il che suggerisce fortemente che non potevano.


Grazie per la risposta! L'approccio con triangoli di dimensioni di un pixel può essere migliorato semplicemente mediante il rendering di punti o piccole linee e potrebbe anche essere migliorato da un ridimensionamento logaritmico in cui una linea che restituisce "vero" viene semplicemente divisa nel mezzo e quindi entrambe le parti vengono nuovamente controllate. Non sono ancora sicuro delle prestazioni in quanto i modelli non avranno più di 100-200 vertici. È valido anche il ragionamento per la non esistenza dell '"API nascosta". Esistono altri mezzi per riportare i dati dalla GPU alla CPU in modo asincrono senza uno stallo della pipeline (per favore, anche in modo confuso)?
Etan,

0

I risultati vengono restituiti in un GLuint, (può anche essere GLint per una chiamata diversa) sfortunatamente, il risultato è sempre uno 0 o un 1, forse lo cambieranno per registrare errori in futuro.

inoltre sembra che nessuna singola persona su Internet abbia pubblicato su queste nuove estensioni ... quindi qui sono configurate correttamente ... che non è documentato da nessuna parte per quanto posso dire ... puoi immaginare come andrebbe nel tuo codice da questo piccolo codice sudo qui:

import UIKit/UIKit.h

import GLKit/GLKit.h

import "GLProgram.h"

GLuint testBox,hasBeenTested,theParams;

//...

glGenQueriesEXT(1, &testBox);

glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, testBox);


//... draw an object .......

glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);

glGetQueryObjectuivEXT(testBox, GL_QUERY_RESULT_AVAILABLE_EXT, &hasBeenTested);

if (hasBeenTested) glGetQueryObjectuivEXT(testBox, GL_QUERY_RESULT_EXT, &theParams);

glDeleteQueriesEXT(1, &testBox);

if (!theParams)  object is hidden;  don't draw next time;

Solo perché il tipo dice GLintnon significa che è un conteggio intero del numero di frammenti di passaggio. La specifica è abbastanza chiara che lo QUERY_RESULT_EXTstato è un valore booleano; basta interrogarlo come numero intero. Lo è GL_FALSEse ha fallito e non GL_FALSEse è passato.
Nicol Bolas,

Avevo appena implementato il codice e ho scoperto che era solo un vero o falso e ho cambiato la mia risposta prima di vedere il tuo commento ... dal momento che è un gluint, forse aggiungeranno stati in futuro, si spera.
honjj

a proposito, sembra che ci sia un bug in GKKit, dove se usi self.effect2 = [[[GLKBaseEffect alloc] init]; tipo di codice GLKit tipo di codice per il rendering di un oggetto, piuttosto che una normale pipeline GLES2.0, le query non riusciranno a darti la risposta corretta ... (mai nascosta) anche se ho testato un oggetto pipeline nascondendo un oggetto GLKBaseEffect, quindi potrebbe esserci un errore nel mescolare i due, non ho ancora testato ulteriormente ...
honjj

Le estensioni sono spiegate con esempi nei video WWDC che possono essere trovati sul sito di Apple con un account sviluppatore attivo.
Etan,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.