Tutorial NVOcclusionQuery: Unterschied zwischen den Versionen
K (→Link Bounding Box) |
Flash (Diskussion | Beiträge) K (→Beispiel-Programm) |
||
Zeile 110: | Zeile 110: | ||
Euer | Euer | ||
− | Lars Middendorf | + | :Lars Middendorf |
+ | |||
+ | {{TUTORIAL_NAVIGATION|[[Tutorial_Vertexprogramme]]|[[Tutorial_Pixelbuffer]]}} | ||
+ | |||
+ | [[Kategorie:Tutorial|NVOcclusionQuery]] |
Version vom 18. Januar 2006, 13:37 Uhr
Inhaltsverzeichnis
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 zwar keine Füllrate, weil die Bounding Box meistens mehr Pixel enthält als das Objekt selber, dafür aber Geometrie.
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. |