Linearer Tiefenpuffer

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Antworten
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Linearer Tiefenpuffer

Beitrag von CodingCat »

Aus aktuellem Anlass bin ich gerade über diesen in der Zwischenzeit fast schon antiken Artikel zu linearer Tiefenpufferung gestolpert. Dieser Artikel aus den Anfängen der Shader-Zeit beschreibt, wie man die Tiefenpufferung von den gängigen z/w-Tiefen hin zu linearer z-Tiefenpufferung (normiert auf 1) verbiegt, indem man einfach am Ende des Vertex Shaders noch schnell den z-Wert mit dem w-Wert multipliziert, um in der anschließenden standardmäßigen w-Division durch die Grafikpipeline wieder den ursprünglichen z-Wert zu erhalten.

Aus heutiger Sicht erscheint mir dieses Vorgehen höchst fragwürdig. Das fängt schon beim Clipping an: Vor der Division steht in z jetzt quasi z^2. Liegt ein Dreieck nun nur teilweise im Viewport, interpoliert die Clippingstufe also quadratische Werte linear, wie sollen da noch sinnvolle Werte rauskommen? Aber es geht noch weiter.

Selbst nach erfolgreicher Division, einfach mal angenommen, dass kein Clipping stattgefunden hat, stellt sich die Frage, was da denn nun im Bildraum wie interpoliert wird. Wenn alles nach Plan (also wie im Artikel) läuft, steht nach der Division in z wieder ein linearer Tiefenwert. Wird der nun wie der standardmäßige z/w-Wert einfach linear im Bildraum interpoliert, wovon wohl auszugehen ist, sind spätestens in der Rasterisierung die Tiefenwerte, die im Pixel Shader und am Ende im Tiefenpuffer landen, doch meilenweit von irgendwelchen sinnvollen Ergebnissen entfernt?

Habe ich hier irgendeinen groben Denkfehler gemacht, oder ist der Artikel einfach von vorne bis hinten Quatsch? Und wenn er Quatsch ist, gibt es überhaupt eine Möglichkeit, irgendetwas anderes als die gängige z/w-Pufferung zu nutzen? (W-Buffering ist ja offensichtlich ausgestorben.)
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
Schrompf
Moderator
Beiträge: 4859
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: Linearer Tiefenpuffer

Beitrag von Schrompf »

Nach meinem Wissen ist der Z-Wert frei für Deine Nutzung, die Grafikkarte clippt nach der W-Komponente.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Linearer Tiefenpuffer

Beitrag von CodingCat »

Frei für meine Nutzung, ja, bringt mir aber nicht viel, wenn alles außer der Standardnutzung rein mathematisch keinen Sinn und damit garantiert kein im Sinne der Verdeckungsberechnung konsistentes Ergebnis liefert. Ein Clipping nach der w-Komponente würde mich im Übrigen sehr wundern, damit wäre doch nicht mal das Singularitätsproblem bei der Projektion behoben? Das Problem mit der Interpolation bei der Rasterisierung besteht aber ganz unabhängig davon.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
Schrompf
Moderator
Beiträge: 4859
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: Linearer Tiefenpuffer

Beitrag von Schrompf »

Stimmt, das ergibt wenig Sinn. Sorry.

Oder war es andersrum? Z wird für's Clippen benutzt und W in den Tiefenpuffer geschrieben? Ich habe damit mal rumgespielt, aber ich erinnere mich nicht mehr, was dabei rauskam.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Linearer Tiefenpuffer

Beitrag von CodingCat »

z/w wird im Normalfall in den Puffer geschrieben, und mir fällt im Moment wenig anderes (vor allem nichts lineares) ein, das im Rahmen der Grafikpipeline überhaupt für Tiefenpufferung brauchbar wäre, ohne dabei im Bildraum massive Interpolationsfehler hervorzurufen. Genau hier wäre ich für weitere Stimmen dankbar.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
Artificial Mind
Establishment
Beiträge: 802
Registriert: 17.12.2007, 17:51
Wohnort: Aachen

Re: Linearer Tiefenpuffer

Beitrag von Artificial Mind »

Wie wäre es mit erst im PixelShader die Tiefe nach linear umzurechnen?
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Linearer Tiefenpuffer

Beitrag von CodingCat »

Ja, möglich, damit hast du dann nur leider kein Early Z Culling mehr. (Letztlich war/ist genau das hardwareseitig unterstützt wohl W-Buffering.) Ich wüsste auch einfach gerne, ob oben verlinkter Artikel schlicht absolut unüberlegt und schlussendlich falsch ist, oder ob ich hier irgendeine wichtige Sache übersehe.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
B.G.Michi
Establishment
Beiträge: 163
Registriert: 07.03.2006, 20:38
Alter Benutzername: B.G.Michi
Kontaktdaten:

Re: Linearer Tiefenpuffer

Beitrag von B.G.Michi »

Guten Morgen
geclippt wird doch nach w und z, siehe hier (bei DepthClipEnable)
mfg
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Linearer Tiefenpuffer

Beitrag von CodingCat »

Naja gut, wenn du nach z clippst, ist w in der Regel sowieso schon positiv, was effektiv mit DepthClipEnable = true reinem z-Clipping gleichkommt. Dennoch interessant, dass diese extra Clippingstufe existiert.

Die ursprüngliche Fragestellung bleibt bestehen. ;)
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
eXile
Establishment
Beiträge: 1136
Registriert: 28.02.2009, 13:27

Re: Linearer Tiefenpuffer

Beitrag von eXile »

Aus diesem Thread:
Humus hat geschrieben:That article is a bunch of crap that has fooled a lot of people, including myself. It just plainly doesn't work.
Zuerst sollte man also zwischen linear im World-Space und linear im Screen-Space unterscheiden:
  • Der z-Buffer in nicht-linear im World-Space, aber linear im Screen-Space
  • Der z/w-Buffer ist linear im World-Space, aber nicht-linear im Screen-Space
Wenn man einen z/w-Buffer korrekt via Pixel-Shader implementiert, fallen Z-Kompression und hierachischer Z-Buffer (und damit Schnelle-Z-Rejection) weg. Aber das ist klar.
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Linearer Tiefenpuffer

Beitrag von CodingCat »

eXile hat geschrieben:Aus diesem Thread:
Humus hat geschrieben:That article is a bunch of crap that has fooled a lot of people, including myself. It just plainly doesn't work.
OK, da bin ich beruhigt.
eXile hat geschrieben:Zuerst sollte man also zwischen linear im World-Space und linear im Screen-Space unterscheiden:
  • Der z-Buffer in nicht-linear im World-Space, aber linear im Screen-Space
  • Der z/w-Buffer ist linear im World-Space, aber nicht-linear im Screen-Space
Jetzt hast du aber jeweils z und z/w vertauscht? z/w ist linear im Screen Space und nicht-linear im World Space, z dagegen linear im World Space und nicht-linear im Screen Space. Genau deshalb funktioniert der Artikel niemals. ;)

Es ist natürlich etwas unglücklich, dass je nach Raum z entweder z/w (nach Projektion) oder z (vor Projektion) entspricht, weswegen DirectX wohl damals den Begriff w-Buffer gewählt hatte, obwohl tatsächlich auch hier die z-Komponente (vor Projektion) entscheidend war, weil w ja weiterhin für eine korrekte Projektion gebraucht wurde.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: Linearer Tiefenpuffer

Beitrag von dot »

eXile hat geschrieben:Wenn man einen z/w-Buffer korrekt via Pixel-Shader implementiert, fallen Z-Kompression und hierachischer Z-Buffer (und damit Schnelle-Z-Rejection) weg. Aber das ist klar.
Die Ordnungsrelation sollte aber erhalten bleiben (wenn auch verkehrt rum), denn auch wenn das Mapping nicht linear ist, so ist es doch stetig monoton, oder?
Du könntest dir also überlegen, die Tiefe im PixelShader wieder mit w zu multiplizieren, um die korrekte lineare Tiefe zu erhalten und dann als Depth auszugeben. Mit D3D11 conservative depth output könntest du so vermutlich tatsächlich ohne Performanceprobleme richtiges w-Buffering implementieren...
Benutzeravatar
eXile
Establishment
Beiträge: 1136
Registriert: 28.02.2009, 13:27

Re: Linearer Tiefenpuffer

Beitrag von eXile »

Das ist korrekt. (Zumindest innerhalb des Viewing-Frustums, aber darum geht es hier ja.) Die Frage ist eher, ob es in Zeiten von Gleitkomma-Depth/Stencil-Targets (namentlich DXGI_FORMAT_D32_FLOAT) Sinn ergibt, überhaupt w-Buffering zu benutzen.
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Linearer Tiefenpuffer

Beitrag von CodingCat »

dot hat geschrieben:
eXile hat geschrieben:Wenn man einen z/w-Buffer korrekt via Pixel-Shader implementiert, fallen Z-Kompression und hierachischer Z-Buffer (und damit Schnelle-Z-Rejection) weg. Aber das ist klar.
Die Ordnungsrelation sollte aber erhalten bleiben (wenn auch verkehrt rum), denn auch wenn das Mapping nicht linear ist, so ist es doch stetig monoton, oder?
Du könntest dir also überlegen, die Tiefe im PixelShader wieder mit w zu multiplizieren, um die korrekte lineare Tiefe zu erhalten und dann als Depth auszugeben. Mit D3D11 conservative depth output könntest du so vermutlich tatsächlich ohne Performanceprobleme richtiges w-Buffering implementieren...
Early Z verlierst du auf jeden Fall, weil die Tiefen vor dem Pixel Shader in ihrer Verteilung grundlegend nicht mehr mit denen nach dem Pixel Shader übereinstimmen. Daran kann auch Conservative Depth nicht viel ändern. Zu Kompression und Hi-Z sagt dieser Blogpost, dass sie ggf. ebenfalls von der Linearität im Bildraum abhängen. Dass Monotonizität prinzipiell ausreicht, ist klar, wie aktuelle GPUs das handhaben, weiß ich nicht. Speziell die Hierarchie nützt ohne Early Z auch nicht wirklich viel?

Derselbe Blogpost beschreibt übrigens auch, wie Gleitkommatiefenpufferung mit nichtlinearer Tiefenverteilung bei richtiger Anwendung (konkret: Invertierung des Z-Buffers) sich gegenseitig soweit aufheben, dass bezüglich Genauigkeit ein guter Kompromiss aus Z- und W-Buffer dabei rauskommt.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: Linearer Tiefenpuffer

Beitrag von dot »

CodingCat hat geschrieben:Early Z verlierst du auf jeden Fall, weil die Tiefen vor dem Pixel Shader in ihrer Verteilung grundlegend nicht mehr mit denen nach dem Pixel Shader übereinstimmen. Daran kann auch Conservative Depth nicht viel ändern.
Ja, das stimmt natürlich, da hab ich jetzt nicht ganz mitgedacht^^
Antworten