Tutorial NVOcclusionQuery: Unterschied zwischen den Versionen

Aus DGL Wiki
Wechseln zu: Navigation, Suche
K (Beispiel-Programm)
(Korrektur - mit Occlusion Querys lässt sich sehr wohl Füllrate sparen)
Zeile 7: Zeile 7:
 
==Anwendung==
 
==Anwendung==
  
Die Occlusion Queries dienen dazu, Geometrie und auch Füllrate einzusparen. Bevor man z.B. ein komplexes Objekt zeichnet, prüft man mit der Occlusion Query, ob die [[Bounding_Box|Bounding Box]] sichtbar ist. Das spart zwar keine Füllrate, weil die [[Bounding_Box|Bounding Box]] meistens mehr Pixel enthält als das Objekt selber, dafür aber Geometrie.
+
Die Occlusion Queries dienen dazu, Geometrie und auch Füllrate einzusparen. Bevor man z.B. ein komplexes Objekt zeichnet, prüft man mit der Occlusion Query, ob die [[Bounding_Box|Bounding Box]] sichtbar ist. Das spart vor allem Geometrie, man kann aber auch Füllrate sparen, wenn man zb. für die [[Bounding_Box|Bounding Box]] sämtliche Beleuchtungen und Texturierungen deaktiviert, statt den eventuellen aufwendigen Shader des Objektes zu verwenden. Natürlich bieten sich Occlusion Queries von Bounding Boxes auch für einen [[Octree]] an.
 
 
  
 
<pascal>
 
<pascal>

Version vom 20. Februar 2006, 14:59 Uhr

NV_Occlusion_Query

Übersicht

Mit der NV_Occlusion_Query-Erweiterung kann man die Pixel zählen, die den Z-Test und den Stencil-Buffer Test bestehen. NV_Occlusion_Query wird ab einer GF3 oder einer Radeon 7500 unterstützt. Die GeForce1 und GeForce2 Grafikkarten und auch die GeForce4 MX bieten diese Erweiterung leider nicht an. Jede Occlusion Query ist im Prinzip ein Zähler. Es gibt Befehle zum Starten und Stoppen des Zählers und eine Funktion, um den Zählerstand abzufragen.


Anwendung

Die Occlusion Queries dienen dazu, Geometrie und auch Füllrate einzusparen. Bevor man z.B. ein komplexes Objekt zeichnet, prüft man mit der Occlusion Query, ob die Bounding Box sichtbar ist. Das spart vor allem Geometrie, man kann aber auch Füllrate sparen, wenn man zb. für die Bounding Box sämtliche Beleuchtungen und Texturierungen deaktiviert, statt den eventuellen aufwendigen Shader des Objektes zu verwenden. Natürlich bieten sich Occlusion Queries von Bounding Boxes auch für einen Octree an.

glGenOcclusionQueriesNV(1,@query);         // Query erstellen
glBeginOcclusionQueryNV(query);        // Zähler auf 0 und starten
...
glColorMask(0,0,0,0);                        // Farbe ausstellen
glDepthMask(0);                                // Nur DepthTest
...
Bounding Box zeichnen
...
glDepthMask(1);                                // Wieder Z-Wert schreiben
glColorMask(1,1,1,1);                        // Farben an
glEndOcclusionQueryNV;                        // Zähler stoppen
...
// Zum jetzigen Zeitpunkt ist unklar, ob die Grafikkarte das Objekt schon // gezeichnet hat und ob die Query bereits fertig ist.
// Deshalb: Andere Objekte zeichnen oder Berechnungen durchführen

glGetOcclusionQueryuivNV(query, GL_PIXEL_COUNT_NV,@count);
if count>0 then
begin
...
Objekt zeichnen
...
end;


Man sollte besonders sorgfältig überlegen, an welcher Stelle man den Zähler abfragt, weil gegebenenfalls solange gewartet wird, bis der Zählerstand verfügbar ist. Wenn eben möglich, sollte versucht werden, möglichst lange mit der Abfrage zu warten, bis das Ergebnis wirklich benötigt wird.


Die Methode spart nur Geometrie und keine Füllrate. Wenn man aber eine Fläche mehrfach durch Multipass zeichnen muss, dann prüft man einfach beim ersten Mal, ob diese Fläche sichtbar ist. Dann kann man sich die Füllrate für die weiteren und meistens auch aufwendigeren Zeichenvorgänge sparen. Bei Bumpmapping und Stencil-Schatten muss man sowieso alle Flächen erstmal schwarz zeichnen.


Eine weitere Methode ist z.B., von einer Lichtquelle aus in alle sechs Richtungen zu zeichnen und so zu prüfen, ob eine Fläche vom Licht aus sichtbar ist und beleuchtet werden kann. Natürlich kostet das sechsfache Zeichnen etwas, aber bei statischen Lichtern kann diese Methode trotzdem eine Menge Füllrate einsparen. Denn die nicht sichtbaren Flächen müssen nicht beleuchtet werden. Sie liegen ja schon im Schatten und man braucht die Schattenvolumina für diese Flächen ebenfalls nicht zu zeichnen.


Wenn man Lenseflares zeichnet, liest man ja meistens den Z-Buffer oder Color-Buffer aus, um festzustellen, ob eine Lichtquelle sichtbar ist. Stattdessen kann man einfach die Lichtquelle als Kugel zeichnen, die sichtbaren Pixel zählen und diesen Wert als Helligkeit für das Lenseflare nehmen.

Neue Funktionen

procedure glGenOcclusionQueriesNV(n:glsizei;ids:pgluint);stdcall;

Occlusion Queries sind Objekte wie Texturen. Bevor man eine Query nutzen kann, muss man sie erstmal mit glGenOcclusionQueriesNV erzeugen.

Bsp:

glGenOcclusionQueriesNV (1,@query);
Hier wird eine Occlusion Query erzeugt und das Handle in der Variable query gespeichert.


procedure glDeleteOcclusionQueriesNV(n:GLsizei;const ids:pgluint);stdcall;

Ähnlich wie Texturen kann man auch die Occlusion Queries wieder löschen.

Bsp:

glDeleteOcclusionQueriesNV(1,@query);
Das Beispiel löscht die oben erzeugte Occlusion Query wieder.


function  glIsOcclusionQueryNV(id:gluint):boolean;stdcall;#

Die Funktion glIsOcclusionQueryNV prüft, ob die Variable id eine gültige Occlusion Query Nummer enthält.


procedure glBeginOcclusionQueryNV(id:gluint);stdcall;

Mit der Prozedur glBeginOcclusionQueryNV startet man den Zähler einer Occlusion Query neu. Alle Pixel, die danach den Z-Test oder Stencil-Test bestehen, erhöhen den Zähler der Occlusion Query. Es kann immer nur eine Occlusion Query zählen. Mehrere parallele Zähler sind daher nicht möglich.


procedure glEndOcclusionQueryNV;stdcall;

Mit [[glEndOcclusionQueryNV}} wird der Zähler der aktuellen Occlusion Query gestoppt. Danach ist es möglich, den Zählerstand abzufragen.


procedure glGetOcclusionQueryivNV(id:gluint;pname:glenum;params:PGLint); stdcall;
procedure glGetOcclusionQueryuivNV(id:gluint;pname:glenum;params:PGLuint); stdcall;

Diese beiden Prozeduren dienen dazu, Parameter der Occlusion Query abzufragen. Mögliche Parameter sind:

GL_PIXEL_COUNT_NV
Gibt den Zählerstand der Occlusion Query in Pixeln zurück.
GL_PIXEL_COUNT_AVAILABLE_NV
Prüft, ob der Zählerstand schon verfügbar ist. Das Ergebnis der Occlusion Query ist nicht sofort nach dem Aufruf von glEndOcclusionQueryNV verfügbar, weil die Grafikkarte und der Prozessor asyncron arbeiten. Die Funktion glEndOcclusionQueryNV wartet, bis der Zählerstand abgefragt werden kann. Wenn man sich die Wartezeit ersparen möchte, ist es sinnvoll, vorher zu testen, ob die Query schon beendet ist, und ansonsten in der Zeit andere Rechnungen durchzuführen.

Beispiel-Programm

Das Beispiel-Programm basiert auf dem VCL Template. Es stellt eine Fläche und eine Kugel dar. Das ganze Gebilde kann man drehen, so dass die Kugel mal mehr und mal weniger sichtbar ist. Am unteren Rand wird die Anzahl der Pixel, die von der Kugel sichtbar sind, dargestellt. In der Unit gl_occlusion_query_nv.pas sind die Funktionen und Konstanten deklariert.


Euer

Lars Middendorf

Vorhergehendes Tutorial:
Tutorial_Vertexprogramme
Nächstes Tutorial:
Tutorial_Pixelbuffer

Schreibt was ihr zu diesem Tutorial denkt ins Feedbackforum von DelphiGL.com.
Lob, Verbesserungsvorschläge, Hinweise und Tutorialwünsche sind stets willkommen.