Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Do Jul 10, 2025 15:55

Foren-Übersicht » Programmierung » OpenGL
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 16 Beiträge ]  Gehe zu Seite 1, 2  Nächste
Autor Nachricht
 Betreff des Beitrags: z-Prepass und z-Fighting
BeitragVerfasst: Di Feb 18, 2014 13:13 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Aug 14, 2013 21:17
Beiträge: 588
Programmiersprache: C++
Hallo Leute,
in einem Programm habe ich momentan die Situation, dass ich sehr viele Fragmente pro Pixel rendere. Bei teuren Fragmentshadern ist das natürlich eine wesentliche Verschwendung von Rechenzeit. Also dachte ich mir, baue ich halt einen Z-Prepass ein:
Code:
  1. // Z-Prepass
  2. glDepthMask(GL_TRUE);
  3. glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
  4.   // Rendering...
  5.  
  6. // Color pass
  7. glDepthMask(GL_FALSE);
  8. glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  9.   // Rendering...

Im DepthPass habe ich für den Fragmentshader natürlich was triviales genommen:
Code:
  1. #version 330
  2. out vec4 outColor;
  3. void main(void) {  
  4.   outColor = vec4(1.0);
  5. }

Vertex- und ggf. Geometryshader sind hingegen exakt gleich. Leider war das Ergebnis aufgrund von massivem Z-Fighting nicht zu gebrauchen.

Daraufhin habe ich dann die üblichen Tricks versucht:
  • mehr Bits für den Z-Buffer
  • gl_Position im Shader als invariant deklariert. Hier ist mir ehrlich gesagt auch nicht ganz klar, woran der Grafiktreiber erkennt, in welchen Vertexshadern die Positionen exakt gleich berechnet werden sollen. Ich bekomme aber selbst dann Z-Fighting, wenn ich Depth- und Color-Pass mit dem selben Program ausführe.
  • glDepthFunc(GL_LEQUAL) hatte ich sowieso eingestellt
  • glPolygonOffset mit verschiedensten Parametern vor dem Z-Prepass aufrufen (das glEnable/glDisable habe ich nicht vergessen). Neben viel herumprobieren (mit teils extremen Werten) habe ich auch versucht, logische Werte als Parameter anzugeben, wobei ich mich nach dieser Erklärung gerichtet habe (ganz unten, letzter Abschnitt).
  • die ProjectionMatrix mittels gluPerspective so modifizieren, dass glPolygonOffset emuliert wird. Angeblich soll es dazu mal einen Artikel in einem "Game Programming Gems"-Teil gegeben haben. Ich habe einfach mal ohne viel Mathe die Near Clipping Plane hin- und her geschoben.

Leider hat das alles nicht geklappt. :(
Was ist denn eigentlich der übliche Weg, mehrere Passes der selben Geometrie ohne Z-Fighting zu rendern? Oder verwenden hier alle Deferred Shading, um gerade diesem Problem aus dem Weg zu gehen? :wink:

Vielen Dank schonmal für eure Hilfe!

_________________
So aktivierst du Syntaxhighlighting im Forum: [code=pascal ][/code], [code=cpp ][/code], [code=java ][/code] oder [code=glsl ][/code] (ohne die Leerzeichen)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: z-Prepass und z-Fighting
BeitragVerfasst: Di Feb 18, 2014 18:05 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Nov 08, 2010 18:41
Beiträge: 769
Programmiersprache: Gestern
Hi,

klingt danach als würdest du auch deinen pre-pass mit GL_LEQUAL rendern. Hier müsstest du GL_LESS benutzen.

_________________
Meine Homepage


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: z-Prepass und z-Fighting
BeitragVerfasst: Di Feb 18, 2014 19:23 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Aug 14, 2013 21:17
Beiträge: 588
Programmiersprache: C++
Ja, ich verwende in beiden Passes GL_LEQUAL. Dies sollte auch meiner Meinung nach in Ordnung sein. Schließlich ist der einzige Effekt, den GL_LEQUAL im Vergleich zu GL_LESS hat, dass in einige Pixel während des Tiefenpasses mehrfach der selbe Wert geschrieben wird. Habe es gerade auch nochmal ausprobiert: GL_LESS für den Z-Pass ändert nichts.

_________________
So aktivierst du Syntaxhighlighting im Forum: [code=pascal ][/code], [code=cpp ][/code], [code=java ][/code] oder [code=glsl ][/code] (ohne die Leerzeichen)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: z-Prepass und z-Fighting
BeitragVerfasst: Di Feb 18, 2014 20:10 
Offline
DGL Member

Registriert: Do Dez 29, 2011 19:40
Beiträge: 421
Wohnort: Deutschland, Bayern
Programmiersprache: C++, C, D, C# VB.Net
Also ich würde mich unabhänig von dem Problem mal mit Dingen in Richtung des Deferred Shadings beschäftigen. Der Z-Prepass verdoppelt mal eben die Anzahl Drawcalls und ist damit eine recht aufwendige Lösung. Ich weiß nicht, ob du das wirklich willst. (Kommt aber natürlich auf den Fall an.)

Eigentlich gibt es keinen Grund, warum hier Z-Fighting auftreten müsste.
Ich würde an deiner Stelle man das Verhältnis der Near-/Farplane überprüfen und ggf. dann anpassen. Erfahrungsgemäß ist das der häufigste Fehler.

Bei "GL_LESS" müsste eigentlich gar nichts mehr zu sehen sein, weil im Z-Buffer ja die kleinsten Werte stehen. Der "GL_LESS"-Test sollte deshalb immer schief gehen. Ich würde das eher mal mit "GL_EQUAL" bzw. Andere zum Überprüfen verwenden. "GL_EQUAL" müsste das gleiche Ergebnis wie "GL_LEQUAL" liefern. "GL_LESS" hingegen nicht. Wenn du sagst, es ändert sich nichts, dann stimmt noch etwas anderes mit dem Z-Buffer nicht.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: z-Prepass und z-Fighting
BeitragVerfasst: Di Feb 18, 2014 22:12 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Aug 14, 2013 21:17
Beiträge: 588
Programmiersprache: C++
OpenglerF hat geschrieben:
Also ich würde mich unabhänig von dem Problem mal mit Dingen in Richtung des Deferred Shadings beschäftigen. Der Z-Prepass verdoppelt mal eben die Anzahl Drawcalls und ist damit eine recht aufwendige Lösung.
Momentan sind nicht die DrawCalls das Problem, sondern ein teurer Fragmentshader, der zu oft aufgerufen wird, sowie unter Umständen die Speicherbandbreite. Die Sparsamkeit mit API-Calls wird meiner Meinung nach sowieso etwas überbewertet. Derzeit habe ich weniger als 100 pro Frame - davon ca. 10-20% DrawCalls. Neulich habe ich mit apitrace einen kommerziellen OpenGL-Titel untersucht. Ergebnis: >30000 (dreißigtausend) API-Aufrufe pro Frame, darunter auch jede Menge deprecated Zeug wie Fullscreen-Quads im Immediate Mode und vieles, von dem ich lange weg bin. Aber das Spiel läuft trotzdem größtenteils flüssig.

Deferred Shading mache ich vielleicht irgendwann demnächst mal, weil es nebenbei auch schöne neue Möglichkeiten bietet, wie z.B. Screenspace Reflections. Aber derzeit glaube ich, dass ein Z-Prepass die passendere Lösung wäre (wenn er denn funktionieren würde), zumal Deferred Shading neue Probleme mit sich bringt (Multisampling) und z.B. transparente Objekte sowieso weiterhin forward gerendert werden müssten.

OpenglerF hat geschrieben:
Ich würde an deiner Stelle man das Verhältnis der Near-/Farplane überprüfen und ggf. dann anpassen. Erfahrungsgemäß ist das der häufigste Fehler.
Selbst wenn ich das Verhältnis Far/Near auf 10 reduziere sehe ich massives Z-Fighting (bei 24 Bits für den Depthbuffer).

OpenglerF hat geschrieben:
Bei "GL_LESS" müsste eigentlich gar nichts mehr zu sehen sein, weil im Z-Buffer ja die kleinsten Werte stehen.
Ich hab mich wohl nicht deutlich genug ausgedrückt. Wenn ich GL_LESS für den Z-Pass und weiterhin GL_LEQUAL für den Color-Pass nehme, ist keine Änderung gegenüber GL_LEQUAL in beiden Passes zu sehen. Im Color-Pass hat GL_EQUAL wie erwartet die gleiche Wirkung wie GL_LEQUAL.

_________________
So aktivierst du Syntaxhighlighting im Forum: [code=pascal ][/code], [code=cpp ][/code], [code=java ][/code] oder [code=glsl ][/code] (ohne die Leerzeichen)


Zuletzt geändert von glAwesome am Di Feb 18, 2014 22:57, insgesamt 1-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: z-Prepass und z-Fighting
BeitragVerfasst: Di Feb 18, 2014 22:17 
Offline
DGL Member

Registriert: Do Dez 29, 2011 19:40
Beiträge: 421
Wohnort: Deutschland, Bayern
Programmiersprache: C++, C, D, C# VB.Net
Zitat:
Selbst wenn ich das Verhältnis Far/Near auf 10 reduziere sehe ich massives Z-Fighting (bei 24 Bits für den Depthbuffer).

Das kann halt gar nicht sein.
Hast du mal ein Bild?

Außerdem:
Z-Prepassing verändert an der Genauigkeit des Depthbuffers nichts, deshalb kann es alleine dadurch auch nicht mehr oder weniger Z-Fighting geben.

Möglicherweise ist die Geometry beim Prepass eine Andere als beim Rendern?


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: z-Prepass und z-Fighting
BeitragVerfasst: Di Feb 18, 2014 22:46 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Aug 14, 2013 21:17
Beiträge: 588
Programmiersprache: C++
Ich habe drei Bilder angehängt, wo man den Unterschied deutlich sieht. Der blaue Hintergrund ist halt einfach die Hintergrundfarbe (glClearColor). Das weiße ist die Geometrie, denn ich verwende sowohl beim Z-Prepass als auch beim Color-Pass den selben Fragment- und Vertexshader. Den Fragmentshader habe oben schon gepostet. Ein Geometryshader ist in diesem Beispiel nicht dabei. Es werden haargenau die gleichen Vertices gerendert, aber trotzdem schlägt der Z-Test bei einigen Fragmenten im Color-Pass fehl, wenn vorher der z-Pass aktiviert war.


Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.

_________________
So aktivierst du Syntaxhighlighting im Forum: [code=pascal ][/code], [code=cpp ][/code], [code=java ][/code] oder [code=glsl ][/code] (ohne die Leerzeichen)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: z-Prepass und z-Fighting
BeitragVerfasst: Di Feb 18, 2014 23:06 
Offline
DGL Member

Registriert: Do Dez 29, 2011 19:40
Beiträge: 421
Wohnort: Deutschland, Bayern
Programmiersprache: C++, C, D, C# VB.Net
Ist das wirklich Z-Fighting?
Deine Bilder lassen sich für mich sehr schwer einordenen, nachdem alles in der gleichen Farbe ist.
Irgendwie sieht mir das eher nach Genauigkeitsproblemen beim Vergleich aus. Möglicherweise irgendwo numerische Ungenauigkeiten bei Gleitkommazahlen.
Ich würde mal "GL_LEQUAL" beim Rendern anstellen und ein kleines Z-Offset beim Prepass hinzufügen.

Die Depthmask würde ich dann auch generell weglassen.
Wenn der Offset "großzügig" gewählt ist, kommen sonst möglicherweise in einer echten Szene ein paar falsche Fragmente durch.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: z-Prepass und z-Fighting
BeitragVerfasst: Di Feb 18, 2014 23:15 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Aug 14, 2013 21:17
Beiträge: 588
Programmiersprache: C++
Ich werd' bekloppt. Ich habe nun das
Code:
  1. glDepthMask(GL_FALSE);
am Anfang des Color-Passes auskommentiert und siehe da: Es funktioniert! :D
Ich verstehe nur nicht, warum... :?: :?: :?: Warum sollte das Schreiben in den Tiefenpuffer während des Color-Passes erlaubt sein?

OpenglerF hat geschrieben:
Irgendwie sieht mir das eher nach Genauigkeitsproblemen beim Vergleich aus. Möglicherweise irgendwo numerische Ungenauigkeiten bei Gleitkommazahlen.
Nennt man nicht genau das Z-Fighting?

_________________
So aktivierst du Syntaxhighlighting im Forum: [code=pascal ][/code], [code=cpp ][/code], [code=java ][/code] oder [code=glsl ][/code] (ohne die Leerzeichen)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: z-Prepass und z-Fighting
BeitragVerfasst: Di Feb 18, 2014 23:51 
Offline
DGL Member

Registriert: Do Dez 29, 2011 19:40
Beiträge: 421
Wohnort: Deutschland, Bayern
Programmiersprache: C++, C, D, C# VB.Net
Zitat:
Warum sollte das Schreiben in den Tiefenpuffer während des Color-Passes erlaubt sein?

Die Frage ist für mich eher, warum es nicht erlaubt sein sollte... :wink:
Das das Problem ausgelöst hat, wundert mich aber doch.

Zitat:
Nennt man nicht genau das Z-Fighting?

Unter Z-Fighting versteht man, wenn mehrere Fragmente in unterschiedlicher Tiefe den gleichen Z-Wert zugeordnet bekommen. Dann ist die Zeichenreihenfolge nicht mehr durch den Z-Buffer definiert und es kommt zu den charakteristischen Zacken am Rand.
Bei war aber die Genauigkeit des Z-Buffers absolut ausreichend: Nur durch numerische Ungenauigkeiten haben Fragmente die eigentlich in der gleichen Tiefe liegen, teilweise unterschiedliche Z-Werte zugeordnet bekommen. (So habe ich das zumindest gedeutet.)

Ich würde die jetzige Lösung übrigens gründlich auf anderen Grafikkarten testen.
Möglicherweise nehmen es manche Hersteller auch nicht so genau mit der Genauigkeit und es kommt wieder zu Darstellungsschwierigkeiten.
Dann braucht es doch noch ein "Sicherheitoffset", damit die Werte nicht genau exakt übereinstimmen müssen.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: z-Prepass und z-Fighting
BeitragVerfasst: Mi Feb 19, 2014 15:33 
Offline
DGL Member
Benutzeravatar

Registriert: Do Sep 02, 2004 19:42
Beiträge: 4158
Programmiersprache: FreePascal, C++
OpenglerF hat geschrieben:
Zitat:
Nennt man nicht genau das Z-Fighting?

Unter Z-Fighting versteht man, wenn mehrere Fragmente in unterschiedlicher Tiefe den gleichen Z-Wert zugeordnet bekommen. Dann ist die Zeichenreihenfolge nicht mehr durch den Z-Buffer definiert und es kommt zu den charakteristischen Zacken am Rand.
Bei war aber die Genauigkeit des Z-Buffers absolut ausreichend: Nur durch numerische Ungenauigkeiten haben Fragmente die eigentlich in der gleichen Tiefe liegen, teilweise unterschiedliche Z-Werte zugeordnet bekommen. (So habe ich das zumindest gedeutet.)


Das ist äquivalent, führt zum gleichen Phänomen und ist ununterscheidbar von der Anwendungsseite. Ob nun die Numerik rauscht oder die Quantisierung in den Bits vom Z-Buffer ist egal, es kommt zum Fighting.

grüße

_________________
If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung.
current projects: ManiacLab; aioxmpp
zombofant networkmy photostream
„Writing code is like writing poetry“ - source unknown


„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: z-Prepass und z-Fighting
BeitragVerfasst: Mi Feb 19, 2014 15:52 
Offline
DGL Member

Registriert: Do Dez 29, 2011 19:40
Beiträge: 421
Wohnort: Deutschland, Bayern
Programmiersprache: C++, C, D, C# VB.Net
Naja, das ist doch deutlich unterscheidbar.
Z-Fighting tritt nämlich immer dann auf, wenn Fragmente nahe hintereinander in Z-Richtung liegen.
Ein Ungenauigkeitsproblem kann prinzipiell immer auftreten, auch bei nur einen einzigen Polygon.

"Z-Fighting" ist doch als "Z-Kampf" zu übersetzen, also wenn mehrere Fragmente "um das Vorrecht kämpfen", am Ende auf den Bildschirm zu kommen. Das liegt aber nicht mehr vor.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: z-Prepass und z-Fighting
BeitragVerfasst: Mi Feb 19, 2014 16:21 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Aug 14, 2013 21:17
Beiträge: 588
Programmiersprache: C++
OpenglerF hat geschrieben:
Die Frage ist für mich eher, warum es nicht erlaubt sein sollte... :wink:
Naja, theoretisch spart es etwas Bandbreite, wenn man sich das Überschreiben von sowieso gleichen Werten spart. Den z-Prepass macht man ja, damit es schneller läuft.
Edit: Wobei, wenn man den Z-Pass mit Offset durchführt, ist es natürlich sinnvoll, das Schreiben in den Z-Buffer zu erlauben.

OpenglerF hat geschrieben:
"Z-Fighting" ist doch als "Z-Kampf" zu übersetzen, also wenn mehrere Fragmente "um das Vorrecht kämpfen", am Ende auf den Bildschirm zu kommen.
Aber das tun sie doch hier auch. Nur, dass das eine Fragment nicht in den Farbpuffer, sondern nur in den Depthbuffer geschrieben wurde.

_________________
So aktivierst du Syntaxhighlighting im Forum: [code=pascal ][/code], [code=cpp ][/code], [code=java ][/code] oder [code=glsl ][/code] (ohne die Leerzeichen)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: z-Prepass und z-Fighting
BeitragVerfasst: Mi Feb 19, 2014 17:18 
Offline
DGL Member

Registriert: Do Dez 29, 2011 19:40
Beiträge: 421
Wohnort: Deutschland, Bayern
Programmiersprache: C++, C, D, C# VB.Net
Zitat:
Naja, theoretisch spart es etwas Bandbreite

Theoretisch eben.
In der Praxis kommt kann ich mir gut vorstellen, dass der Treiber darauf nicht optimiert ist.

Zitat:
Aber das tun sie doch hier auch. Nur, dass das eine Fragment nicht in den Farbpuffer, sondern nur in den Depthbuffer geschrieben wurde.

Nein, wenn das Problem durch Genauigkeit ausgelöst wird.
Dann sind beim zweiten Pass einfach bei den gleichen Polygonen die Z-Werte minimal größer als beim Ersten.
Da Kämpft also nichts, sondern es wird einfach an einigen Stellen nicht gerendert.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: z-Prepass und z-Fighting
BeitragVerfasst: Do Feb 20, 2014 00:43 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Nov 30, 2011 21:41
Beiträge: 136
Wohnort: Bad Vilbel
Programmiersprache: Delphi 7
Hallo,

ich habe bei mir in der Engine auch einen Z-Pass eingebaut, und ich kann ohne Probleme glDepthMask(false); vor dem Rendern der eigentlichen Szene aufrufen (ich arbeite ohne Offset). Mich würde mal interessieren, wovon dieses Problem dann eigentlich abhängig ist? (Treiber / Grafikkarte an sich / ...)

Mein Engine habe ich auch auf diversen anderen Rechner getestet, Z-Fighting habe ich da niemals bemerkt, obwohl jede weitere Graka an meinen Shadern genörgelt hat^^.

P.S. ich habe sogar mit GL_EQUAL als DepthFunc gearbeitet und trotzdem keine Probleme bei mir bemerkt.


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 16 Beiträge ]  Gehe zu Seite 1, 2  Nächste
Foren-Übersicht » Programmierung » OpenGL


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 8 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.010s | 16 Queries | GZIP : On ]