bin gerade dabei meine Zeichenroutine etwas zu optimieren. Morgen schau ich mir Frustum Culling an.
Suche noch eine weitere möglichkeit, weiß aber nicht wie man das nennen kann oder welche Technik sich dahinter versteckt. Wenn ein Objekt gezeichnet wird und dieses Objekt überzeichnet andere Objekte, sind diese von der Kamera nicht sichtbar und daher braucht man diese auch nicht zu zeichnen. Wie kann ich aber testen ob ein Objekt von einem anderem Objekt überzeichnet/überdeckt wird?
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
Nennt sich das eventuell Occlusion Culling? Da gibts auf jeden Fall proprietäre OpenGL-Erweiterungen, die dir dabei helfen. Generell hilft dir aber der Tiefenpuffer schon viel, wenn du von vorne nach hinten zeichnest (und du die Geometrie in VBOs o.ä. hast).
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 network • my 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
Registriert: Di Sep 06, 2005 18:34 Beiträge: 362 Wohnort: Hamburg
Das gleiche wollt ich auch grad schreiben, egal … ich schreibs trotzdem
Das geht auch ohne ray tracing. Stichwort Occlusion Culling.
Eine weitere Möglichkeit ist, alle nicht-transparenten Objekte von vorne nach hinten zu zeichnen. D.h. die Objekte zuerst die am nächsten an der Kamera dran liegen. Wenn du dann darauf achtest, dass deine Fragment Shader nicht mit den depth Werten herumpfuschen, wird der Depth Test sehr wahrscheinlich schon vorm Fragment Shader ausgeführt (early z rejection). Das führt dazu, dass verdeckte Objekte direkt nach dem Vertex Shader weggeschmissen werden, was auf der meisten (PC-) Hardware ein großer Vorteil ist.
_________________ Der Mensch hat neben dem Trieb der Fortpflanzung und dem zu essen und zu trinken zwei Leidenschaften: Krach zu machen und nicht zuzuhören. (Kurt Tucholsky)
Schwabbeldiwapp, hier kommt die Grütze. (Der Quästor)
Registriert: Mo Sep 23, 2002 19:27 Beiträge: 5812
Programmiersprache: C++
Das geht wie schon angesprochen über Occlusion Queries (Wikiartikel), mit denen zählt man die Pixel die den Tiefentest bestehen. Bei einem Objekt das komplett verdeckt wird sind dass dann Null und man kann sich das Zeichnen sparen. Sind inzwischen auch im OpenGL-Kern verankert.
Aber auch hier gilt (wie bei allen Optimierungstechniken) : Abwägen ob es nicht evtl. doch sinnvoller ist ein Objekt einfach zu zeichnen, denn Occlusion Queries kosten Performance und stehen erst nach dem Abschluss mit glEndQuery zur Verfügung. Im schlechtesten Falle kostet dass Occlusion Query mehr Performance als das Nichtzeichnen eines Objektes einbringt.
Alternativ kann man hier schon optimieren indem man zuerst einen Depth-Only Pass macht. Sprich zuerst die Tiefenwerte schreiben (ohne in die anderen Puffer zu rendern) und dann später die Szene mit passendem Tiefentest rendern. Z-Only-Passes sind i.d.R. extrem schnell. Das bringt dir evtl. mehr als bestimmte Objekte anhand von Occlusion Queries nicht zu zeichnen.
Registriert: Sa Aug 18, 2007 18:47 Beiträge: 694 Wohnort: Köln
Programmiersprache: Java
Wenn ich Occlusion Queries verwende, wird der Fragment Shader gar nicht mehr ausgeführt, oder?
Würde doch sicher auch reichen, wenn man nur eine BoundingBox des Objekts zeichnet? Ist dann zwar nicht ganz exakt und müsste man dann gegen die Anzahl der Vertices abwägen.
_________________ Es werde Licht. glEnable(GL_LIGHTING); Und es ward Licht.
Zitat aus einem Java Buch: "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off"
Ein übliches Verfahren ist es an Hand des Query-Ergebnisses des vorherigen Frames zu entscheiden was passieren soll: - war das Objekt im letzten Frame unsichtbar, rendere nur eine (unsichtbare) BoundingBox - war das Objekt im letzten Frame sichtbar, rendere das ganze Objekt
Vorteil: Da das Query-Ergebnisse jeweils erst im nächsten Frame benötigt wird entfällt die teure Wartezeit.
Nachteil: Objekte sind erst ein Frame später sichtbar alles sie es eigentlich sein müssten. Da man hierdurch ja deutlich höhere FPS erreichen kann sieht eigentlich niemand. Sollte das trotzdem ein Problem sein kann auch die BoundingBox einfach immer rendern, was aber natürlich Fillrate kostet. Der Occ-Query wird dann immer nur für die BoundingBox durchgeführt. Da die BoundingBox üblicherweise größer ist als das Objekt sieht man dann immer alles zum richtigen Zeitpunkt.
Edit: Mit unsichtbarer BoundingBox ist folgendes gemeint: Der Occ-Query zählt die Pixel die den Z-Test bestehen. Entsprechend rendert man mit einem möglichst einfachen Fragmentshader und deaktiviert das schreiben in Z- und Framebuffer über glDepthMask bzw. glColorMask.
Occlusion Queries ist schon recht langsam. Bei 28 Tausend Objekte dauert das seine Zeit.
Sascha Willems hat geschrieben:
Alternativ kann man hier schon optimieren indem man zuerst einen Depth-Only Pass macht. Sprich zuerst die Tiefenwerte schreiben (ohne in die anderen Puffer zu rendern) und dann später die Szene mit passendem Tiefentest rendern. Z-Only-Passes sind i.d.R. extrem schnell. Das bringt dir evtl. mehr als bestimmte Objekte anhand von Occlusion Queries nicht zu zeichnen.
Zunächst erstellst du dir eine Liste der potentiell sichtbaren Objekte (FrustumCulling)
Diese Liste sortierst du nach Material, Shader, etc.
Dann renderst du diese Liste ein erstes mal. Dabei ersetzt du den Fragmentshader durch einen Trivial-Shader der nur eine Farbe zurück gibt. Das schreiben in den Framebuffer wird dabei deaktiviert via glColorMask. Am Ende hast du also den Z-Buffer in dem Zustand in dem du ihn nach dem rendern der Szene hättest. Solltest du transparente Objekte haben, werden die hier NICHT gerendert.
Dann renderst du die Szene ein zweites mal, jetzt aber ganz normal. Allerdings sollte glDepthFunc auf GL_LEQUAL gesetzt werden.
Dieses Verfahren lohnt sich insbesondere dann, wenn du zwar einfache Geometrie hast (den diese wird ja hier zweimal verarbeitet), aber dafür aufwendige Fragmentshader (z.B. viele Texturen, etc).
Hm, okay. Danke. Shader verwende ich noch nicht, soweit bin ich noch nicht.
Kämpfe gerade noch mit den Occlusion Queries. Habe mir einen Octree gebaut der die Objekte rendert. Habe einen Block von Quadraten 10x10x10 mit einer größe von 1. Wenn ich von vorne drauf schaue, werden fast alle Objekte gezeichnet, wenn ich einmal rum gehe und von hinten drauf schaue, werden nicht mehr alle Objekte gezeichnet. Muss ich da nochwas beachten?
Sorry, ich muss einfach nochmal nachfragen. So ganz verstehe ich nicht was da falsch läuft.
Habe 10 Objekte an den Positionen (0,0,0 / 0,0,-5 / 0,0,-10 ....). Diese render ich von vorne nach hinten. Wenn ich vor dem Obejct stehe, wird auch nur ein Objekt gezeichnet, das funktioniert. Wenn ich aber nach hinten laufe, also Z der Kamera steht auf -51, und schaue dann auf die Objekte werden alle gezeichnet, obwohl auch nur eins gezeichnet werden sollte.
Also muss ich doch meine Objekte immer nach der Kamera sortieren oder? Bzw. von der Kamera Position nach hinten, egal wo ich stehe.
Okay, dann muss ich mein Konzept komplett umstellen. Der octree muss dann anders bearbeitet werden damit das rendern anders abläuft. Zum test sortiere ich gar nichts. Danke für deine hilfe.
Mitglieder in diesem Forum: 0 Mitglieder und 7 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.