Tutorial NVOcclusionQuery: Unterschied zwischen den Versionen

Aus DGL Wiki
Wechseln zu: Navigation, Suche
(Neue Funktionen)
K (Der Ausdruck ''<pascal>(.*?)</pascal>'' wurde ersetzt mit ''<source lang="pascal">$1</source>''.)
 
(4 dazwischenliegende Versionen von 4 Benutzern werden nicht angezeigt)
Zeile 3: Zeile 3:
  
 
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.
 
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==
 
==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 zwar keine Füllrate, weil die 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.&nbsp;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 z.&nbsp;B. 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>
+
<source lang="pascal">
 
glGenOcclusionQueriesNV(1,@query);        // Query erstellen
 
glGenOcclusionQueriesNV(1,@query);        // Query erstellen
 
glBeginOcclusionQueryNV(query);        // Zähler auf 0 und starten
 
glBeginOcclusionQueryNV(query);        // Zähler auf 0 und starten
Zeile 33: Zeile 31:
 
...
 
...
 
end;
 
end;
</pascal>
+
</source>
 
 
  
 
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.
 
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.
 
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.&nbsp;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.
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.
 
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==
 
==Neue Funktionen==
  
<pascal>
+
<source lang="pascal">
 
procedure glGenOcclusionQueriesNV(n:glsizei;ids:pgluint);stdcall;
 
procedure glGenOcclusionQueriesNV(n:glsizei;ids:pgluint);stdcall;
</pascal>
+
</source>
  
 
Occlusion Queries sind Objekte wie Texturen. Bevor man eine Query nutzen kann, muss man sie erstmal mit [[glGenOcclusionQueriesNV]] erzeugen.
 
Occlusion Queries sind Objekte wie Texturen. Bevor man eine Query nutzen kann, muss man sie erstmal mit [[glGenOcclusionQueriesNV]] erzeugen.
  
 
Bsp:
 
Bsp:
<pascal>glGenOcclusionQueriesNV (1,@query);</pascal> Hier wird eine Occlusion Query erzeugt und das Handle in der Variable query gespeichert.
+
<source lang="pascal">glGenOcclusionQueriesNV (1,@query);</source> Hier wird eine Occlusion Query erzeugt und das Handle in der Variable query gespeichert.
  
 
+
<source lang="pascal">
<pascal>
 
 
procedure glDeleteOcclusionQueriesNV(n:GLsizei;const ids:pgluint);stdcall;
 
procedure glDeleteOcclusionQueriesNV(n:GLsizei;const ids:pgluint);stdcall;
</pascal>
+
</source>
  
 
Ähnlich wie Texturen kann man auch die Occlusion Queries wieder löschen.
 
Ähnlich wie Texturen kann man auch die Occlusion Queries wieder löschen.
  
 
Bsp:
 
Bsp:
<pascal>glDeleteOcclusionQueriesNV(1,@query);</pascal> Das Beispiel löscht die oben erzeugte Occlusion Query wieder.
+
<source lang="pascal">glDeleteOcclusionQueriesNV(1,@query);</source> Das Beispiel löscht die oben erzeugte Occlusion Query wieder.
  
 
+
<source lang="pascal">
<pascal>
 
 
function  glIsOcclusionQueryNV(id:gluint):boolean;stdcall;#
 
function  glIsOcclusionQueryNV(id:gluint):boolean;stdcall;#
</pascal>
+
</source>
  
 
Die Funktion [[glIsOcclusionQueryNV]] prüft, ob die Variable ''id'' eine gültige Occlusion Query Nummer enthält.
 
Die Funktion [[glIsOcclusionQueryNV]] prüft, ob die Variable ''id'' eine gültige Occlusion Query Nummer enthält.
  
 
+
<source lang="pascal">
<pascal>
 
 
procedure glBeginOcclusionQueryNV(id:gluint);stdcall;
 
procedure glBeginOcclusionQueryNV(id:gluint);stdcall;
</pascal>
+
</source>
  
 
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.
 
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.
  
 
+
<source lang="pascal">
<pascal>
 
 
procedure glEndOcclusionQueryNV;stdcall;
 
procedure glEndOcclusionQueryNV;stdcall;
</pascal>
+
</source>
  
 
Mit [[glEndOcclusionQueryNV}} wird der Zähler der aktuellen Occlusion Query gestoppt. Danach ist es möglich, den Zählerstand abzufragen.
 
Mit [[glEndOcclusionQueryNV}} wird der Zähler der aktuellen Occlusion Query gestoppt. Danach ist es möglich, den Zählerstand abzufragen.
  
 
+
<source lang="pascal">
<pascal>
 
 
procedure glGetOcclusionQueryivNV(id:gluint;pname:glenum;params:PGLint); stdcall;
 
procedure glGetOcclusionQueryivNV(id:gluint;pname:glenum;params:PGLint); stdcall;
 
procedure glGetOcclusionQueryuivNV(id:gluint;pname:glenum;params:PGLuint); stdcall;
 
procedure glGetOcclusionQueryuivNV(id:gluint;pname:glenum;params:PGLuint); stdcall;
</pascal>
+
</source>
  
 
Diese beiden Prozeduren dienen dazu, Parameter der Occlusion Query abzufragen. Mögliche Parameter sind:
 
Diese beiden Prozeduren dienen dazu, Parameter der Occlusion Query abzufragen. Mögliche Parameter sind:
Zeile 102: Zeile 90:
  
 
:'''GL_PIXEL_COUNT_AVAILABLE_NV'''
 
:'''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.
+
::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 asynchron 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=
 
=Beispiel-Programm=
Zeile 108: Zeile 96:
 
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.
 
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
  
Euer
+
:Lars Middendorf
 +
 
 +
{{TUTORIAL_NAVIGATION|[[Tutorial_Vertexprogramme]]|[[Tutorial_Pixelbuffer]]}}
  
Lars Middendorf
+
[[Kategorie:Tutorial|NVOcclusionQuery]]

Aktuelle Version vom 10. März 2009, 19:13 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 z. B. 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 asynchron 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.