Wie kann ich in OpenGL den Tiefenbereich eines Tiefenpuffers ermitteln?


11

Ich mache eine GL-Multi-Pass-Rendering-App für iOS. Der erste Durchgang wird zu einer Tiefenpuffertextur gerendert. Der zweite Durchgang verwendet die Werte im Tiefenpuffer, um die Anwendung eines Fragment-Shaders zu steuern. Ich möchte die Werte im Tiefenpuffer auf etwas Nützliches skalieren, aber bevor ich das tun kann, muss ich den Tiefenwertbereich der Tiefenpufferwerte kennen. Wie mache ich das?

Antworten:


10

Der Bereich der in den Tiefenpuffer geschriebenen Werte ist beliebig. Typischerweise fallen sie in den Bereich von 0 zu 1. Der tatsächliche Wert, der in den Tiefenpuffer geschrieben wird, wird während der Ansichtsfenstertransformation basierend auf dem Z-Wert des Scheitelpunkts im NDC-Raum berechnet (nach der perspektivischen Division durch w im Clip-Raum).

Der NDC-Tiefenwert (Z, nach der perspektivischen Division durch W) wird durch den Tiefenbereich der Ansichtsfenstertransformation skaliert (wodurch Ihre X- und Y-Koordinaten in einen Koordinatenraum gebracht werden, den Sie mit Pixeln im Fenster verknüpfen würden) und anschließend um skaliert (2^n-1)- das soll als "zwei hoch der Macht von" gelesen werdenn - nist die Bitgenauigkeit des Tiefenpuffers. Der resultierende Wert wird in den Tiefenpuffer geschrieben.

OpenGL teilt die Definition der Ansichtsfenster-Transformationsmatrix in glViewport- und glDepthRange- Aufrufe auf. glDepthRange steuert den Skalierungsfaktor, der für die Bestimmung des gewünschten Tiefenbereichs verantwortlich ist. Sie können glGetFloatv mit dem aufrufenGL_DEPTH_RANGE Selektor , um den aktuellen Bereich wiederherzustellen. Auf diese Weise können Sie den Bereich nutzen, ohne von 0 bis 1 auszugehen (obwohl in 99,9% der Fälle in der Praxis niemand ihn ändert).

Lesen Sie weiter, wenn Sie einen Einblick in die Rekonstruktion der Mathematik erhalten möchten, um dem Z-Wert vom Augenraum bis zum Tiefenpuffer zu folgen.


Ich werde Josh dieses für all das zusätzliche Referenzmaterial und den Tipp zur Dreiecksebenheit geben. Ich bin geneigt, einen Hack durchzuführen, bei dem die Positionen in der Nähe / Ferne der Clip-Ebenen genau der Z-Ausdehnung der Geometrie entsprechen, die ich rendere, damit die Tiefenkarte schöne Werte aufweist. Was habe ich vor? Ich möchte während des zweiten Durchgangs interessante ortsspezifische Unschärfeeffekte erzeugen, basierend auf der Tiefenkarte des ersten Durchgangs.
Dugla

7

Die Werte im Tiefenpuffer liegen immer im Bereich zwischen 0 und 1. Null ist, dass sich das gerenderte Fragment in der Tiefe der nahen Ebene befindet, und 1 ist, dass sich das Fragment in der Tiefe der fernen Ebene befindet. Und alles dazwischen.

Wenn Sie die reale Tiefe im Weltraum kennen möchten, können Sie sie einfach aus dem Tiefenpuffer berechnen.

depth = nearPlane + ( farPlane - nearPlane ) * depthBufferValue;

Aus diesem Grund geben Sie die Nah- und Fernebene in Ihrer Projektionsmatrix an, um die Genauigkeit des Tiefenpuffers zu erhöhen.

Beachten Sie auch den Unterschied zwischen Tiefe und Entfernung, wenn Sie Tiefenpufferwerte verwenden.


@notebene. Fast dort. Ich möchte den Wertebereich im Tiefenpuffer neu skalieren und genau 0 -> 1 sein. Wenn also die gerenderten Min / Max-Tiefenwerte .25 / .75 sind, möchte ich (Tiefenwert - .25) / (. 75 - .25). Gibt es also eine Möglichkeit, das Min / Max des Tiefenpuffers nach Pass 1 zu ermitteln und dieses zu verwenden, um es während Pass 2 neu zu
skalieren?

1
@dugla: Da Sie ebene Dreiecke rendern, werden die minimalen und maximalen Tiefenwerte zwangsläufig den minimalen und maximalen Scheitelpunkten in der Szene zugeordnet. Wenn Sie diese beiden kennen, können Sie sie manuell durch die Pipeline transformieren und kennen die minimalen und maximalen Werte, die Sie in den Tiefenpuffer schreiben würden. Dies ist möglicherweise einfacher als das Rendern, dann das Zurücklesen des gesamten Tiefenpuffers und das Iterieren.
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.