12 Z-Buffer (Depth Buffer, Tiefeninformation)
12.010 Wie kann ich den Z-Buffer aktivieren ?
Das Programm muss zumindest folgende Schritte unternehmen, um den Tiefenbuffer
zu aktivieren:
-
Der Rendering Context muss bereits mit Tiefenbuffer angelegt werden.
-
Nach dem Anlegen des Rendering Context muss der Tiefenbuffer mit
glEnable(GL_DEPTH_TEST) aktiviert werden.
-
Die Grenzen des Viewing Volumes (zNear und zFar) müssen
so gesetzt werden, dass der Tiefenbuffer korrekt arbeiten kann (zNear >= 1.0,
zFar nicht zu gross).
-
glClear() muss zusätzlich mit GL_DEPTH_BUFFER_BIT aufgerufen werden.
Es gibt ausreichend Beispielprogramme im Netz, die mit dem Z-Buffer arbeiten.
Falls es Probleme gibt, sollte man zunächst eines dieser Beispiele austesten.
Links enthält die FAQ hier.
12.020 Der Z-Buffer scheint nicht mit der Zentralperspektive zu funktionieren. Warum nicht ?
Zunächst sollte man sich versichern, dass zNear und zFar
vernünftige Werte enthalten (zu Testzwecken kann man für zNear = 1.0 - 10.0,
für zFar = 200 - 1000) setzen).
Ein häfig gemachter Fehler sind zu geringe Werte für zNear. Dieser muss
positiv und grösser Null sein, da hiermit eine Division durchgeführt wird).
Beide Werte zählen als positiver Abstand vom Auge, dürfen also nie
negativ sein.
Sind die Werte für zNear,zFar ungültig, meldet OpenGL be3i Verwendung
von gluPerspective() trotzdem keine Fehler. Der Tiefenbuffer arbeitet dann aber
nicht oder es werden unerwünschte Ergebnisse erzielt.
Im Falle von glFrustum() kann der Fehler durch glGetError() auch abgefragt werden.
Die Funktion selbst wird deaktiviert.
12.030 Wie kann ich eine kurz vorher gespeicherte Tiefeninformation in
den aktuellen Z-Buffer übertragen ?
Das kann man mittels glDrawPixels() und dem Parameter GL_DEPTH_COMPONENT realisieren.
Es kann sinnvoll sein, den Color Buffer vorher zu deaktivieren, das geht durch
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE).
12.040 Der Z-Buffer scheint zu arbeiten, allerdings werden einige Polygone
durch andere, im Vordergrund befindliche Polygone durchdrungen zu werden. Warum ?
Die Ursache ist meist in falschen Werten für zNear und zFar
zu finden. Insbesondere Werte von zNear nahe Null beschränken die Präzision
des Tiefenbuffers erheblich. Der Einfluss von zu grossen Werten für zFar ist
dagegen nicht ganz so erheblich (sinnvolle Werte für zNear, zFar).
Die OpenGL Reference Manual enthält
eine Aussage darüber, wie gross der Einfluss von zNear, zFar auf
den Tiefenbuffer ist: ca. log2(zFar/zNear) gehen an Präzision verloren.
Ist zNear nahe Null gesetzt, wird das Ergebnis unendlich gross.
Obwohl die Beschreibung aus dem Blue Book das Verhältnis der Werte gut nachvollziehbar
macht, ist sie etwas oberflächlich. Wird der Wert von (zFar/zNear)
grösser, nimmt die Präzision im hinteren Bereich des Tiefenbuffers
im Vergleich zum vorderen Bereich deutlich stärker ab. Damit treten diese
Durchdringungserscheinung von Objekten eher im hinteren Bereich des Viewing Volumes
auf.
Es kann aber auch sein, dass der Tiefenbuffer einfach nicht gross genug für
die Anforderungen der Szene ist (sie auch Frage 12.070).
Eine dritte Ursache kann sein, dass mehrere Flächen auf annähernd gleicher
Höhe liegen. Damit sind Rundungsfehler während der Rasterisation nicht auszuschliessen.
Eine Option ist z.B. der PolygonOffset.
12.050 Warum arbeitet mein Z-Buffer so ungenau ?
Die Präzision des Tiefenbuffers hängt wesentlich vom Verhältnis
zFar/zNear, von zFar und vom Abstand des Objekts zu zNear ab.
Das heisst, zNear und zFar sollten so nah wie möglich beieinander liegen und
zNear nicht zu nahe am Augpunkt.
Ein nachgerechnetes Beispiel findet sich in der
englischen Version der OpenGL FAQ.
12.060 Wie kann ich die vordere Clippingfläche deaktivieren ?
Diese Frage wurde bereits in einem früheren
Abschnitt beantwortet.
12.070 Warum arbeitet der Z-Buffer im vorderen Bereich genauer ?
Nachdem die Projektionsmatrix durchlaufen wurde, werden die Clipping Koordinaten
XYZ durch ihre homogene Komponente W dividiert, die den Abstand des Vertex vom Augpunkt
beschreibt. Daraus ergeben sich die normalisierten Device Koordinaten. Je weiter
dass Objekt vom Augpunkt entfernt ist, desto mehr nähert sich Z/W Null an.
Damit werden auch X/W and Y/W kleiner, dass Objekt als ganzes schrumpft also am
Horizont, die Zentralprojektion ist damit verwirklicht.
Genauso wie in der Realität hat ein Bewegen der Kamera auf die Grösse
der weiter entfernten Objekte wenig Auswirkungen.
12.080 Mein Z-Buffer ist nicht ausreichend gross für meine überdimensionale
Szene. Welche Möglichkeiten habe ich noch ?
Eine typische Lösung ist es, eine Multipass Technik zu nutzen.
Die Anwendung kann die Objekte zu Gruppen zusammenfassen, die in annähernd
gleichem Abstand zum Augpunkt sind und einen ausreichenden Abstand zu anderen
Objekten haben. Dann wird jede Gruppe getrennt gezeichnet, jeweils beginnend
bei den am weitesten entfernten Objekten der Gruppe. Vor dem Zeichnen einer weiteren
Gruppe wird der Tiefenbuffer gelöscht. Dadurch steht jeder Region die volle
Breite des Tiefenbuffers zur Verfügung.
|