Hallo Community
Ich habe mich mal mit dem Thema "mehrere Lichter in einer Szene" auseinandergesetzt und meinen 3D Leveleditor den ich für mein aktuelles Game "Zorn der Könige" (http://www.zdk-online.com) entsprechend erweitert. Als Renderer verwende ich OpenGL und GLSL für die Shader.
Die meisten Tutorials die sich mit Per-Pixel Lightning, Normal Mapping usw. befassen, beleuchten oft ein einziges Objekt mit einer Lichtquelle. Doch eine Szene in einem Game besteht schliesslich aus mehreren Lichtquellen und Objekten.
Googelt man nach diesem Thema, kommt man auf die Technik "Deferred Shading/Lightning". Dies ist ein völlig anderer Ansatz als dem klassischen Forward Shading in OpenGL. Ich habe aber trotzdem eine andere Variante gewählt die ich hier kurz vorstellen möchte.
OpenGL unterstützt nur 8 Lichter, je nach Hardware können auch mehrere Verwendet werden. Ich verwende nun die Technik des Virtual Lightnings, verwende als immer wieder die gleichen Lichter um verschiedene Objekte zu beleuchten. In meiner Implementation verwende ich 4 Lichter.
Zuerst erstelle ich aus der Geometrie und Lichtern in der Szene sogenannte Lichtgruppen. Für jedes Polygon (für komplexe Objekte wird das ganze Objekt berücksichtigt) wird berechnet, welche Lichter in der Szene am nächsten sind. Diese Lichter (max. 4) bilden eine Lichtgruppe. Es können nun mehrere Polygone bzw Objekte existieren die der gleichen Lichtgruppe angehören.
Für das Rendern iteriere ich durch alle Lichtgruppen. Pro Gruppe werden die 4 Lichter entsprechend gesetzt. Jetzt werden alle Geometrien gerendert und werden von den 4 Lichtern der Gruppe beleuchtet.
Vorteil dieser Technik ist die ziemlich einfache Implementation. Shader Code für Normal Maps, Parallax Mapping usw. können einfach übernommen und erweitert werden. Es ist nur ein Renderpass nötig, die Lichter werden nur pro Gruppe neu Platziert.
Der Nachteil ist, grosse Polygon und Objekte werden nicht korrekt beleuchtet, da diese von mehr als 4 Lichtern betroffen sind. Dies kann verhindert werden indem man die Objekte verkleinert. Da die Lichter immer neu Platziert werden, könnte es die Performance beeinträchtigen.
Die Technik ist nichts neues doch funktioniert in meinem Editor schon ziemlich gut. Beim erstellen von Levels werde ich feststellen wo die Grenzen dieser Technik sind. Doch um "schnell mal" eine Szene mit mehreren Lichtern zu beleuchten ist dies sicher eine gute Alternative zum Deferred Shading.
Hier noch der GLSL Shader Code:
http://www.deltasoftgames.ch/dev/multi-lights.v
http://www.deltasoftgames.ch/dev/multi-lights.f
Szene im Editor mit total 8 Lichtern, virtualisiert mit 4 Lichtern. Zu beachten ist hier dass der Boden in mehrere Polygone aufgeteilt ist, mit einem grossen Polygon für den Boden würde dies nicht funktionieren.
Mehrere Lichter in einer 3D Szene
- dot
- Establishment
- Beiträge: 1745
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: Mehrere Lichter in einer 3D Szene
Cool :)
Das was du da machst geht schon ziemlich in Richtung dessen, was bei vielen besseren Forward-Renderern wirklich gemacht wird. Was man zusätzlich noch machen könnte wäre, die Lichter generell nach ihrer "Wichtigkeit" für das Objekt zu sortieren und entsprechend unwichtige Lichtquellen, die nahe genug beieinanderliegen, zu einer zusammenzufassen. Lichter die weiter weg sind können z.b. überhaupt kompakt über eine spherical-harmonics-basierte Approximation gemacht werden. Ansonsten heißt das Stichwort bei Forward-Rendering Multipass. Also die Szene z.B. mal mit den ersten 8 Lichtern rendern und dann mit den nächsten, und alles eben additiv zusammenblenden. Generell sind sehr viele Lichtquellen aber eben ein Problem für Forward-Rendering, genau darum wurde ja Deferred-Rendering erfunden. Das hat dafür aber wieder seine eigenen Probleme (Multisampling, Transparenz, ...). Und man sollte die Probleme des Forward-Renderers mit einem Z-Prepass und z.B. durch geschickte Nutzung der Stream-Output-Stage nicht so schlecht beherrschen können. Und ansonsten kann man beide Techniken natürlich auch kombinieren...
Das was du da machst geht schon ziemlich in Richtung dessen, was bei vielen besseren Forward-Renderern wirklich gemacht wird. Was man zusätzlich noch machen könnte wäre, die Lichter generell nach ihrer "Wichtigkeit" für das Objekt zu sortieren und entsprechend unwichtige Lichtquellen, die nahe genug beieinanderliegen, zu einer zusammenzufassen. Lichter die weiter weg sind können z.b. überhaupt kompakt über eine spherical-harmonics-basierte Approximation gemacht werden. Ansonsten heißt das Stichwort bei Forward-Rendering Multipass. Also die Szene z.B. mal mit den ersten 8 Lichtern rendern und dann mit den nächsten, und alles eben additiv zusammenblenden. Generell sind sehr viele Lichtquellen aber eben ein Problem für Forward-Rendering, genau darum wurde ja Deferred-Rendering erfunden. Das hat dafür aber wieder seine eigenen Probleme (Multisampling, Transparenz, ...). Und man sollte die Probleme des Forward-Renderers mit einem Z-Prepass und z.B. durch geschickte Nutzung der Stream-Output-Stage nicht so schlecht beherrschen können. Und ansonsten kann man beide Techniken natürlich auch kombinieren...
Re: Mehrere Lichter in einer 3D Szene
Das mit der "Wichtigkeit" der Lichter finde ich einen guten Tipp, danke. Es kann durchaus vorkommen dass zwei Lichter nahe genug sind bzw. der Betrachter zu weit entfernt, so dass die Lichter mehr oder weniger das gleiche beleuchten. Dies könnte dann von einem einzigen Licht beleuchtet werden und man hat ein weiteres Licht zu Verfügung.
Viele Artikel weisen auf das Multipass-Rendering an, wie geschildert, die Szene mehrmals rendern und additiv blenden. Ich habe dies versucht zu vermeiden indem ich Lichtgruppen erzeuge, so kann ich die ganze Szene in einem Pass rendern. Der Nachteil liegt hierbei eben, dass ein Objekt/Polygon nur von max. vier Lichtern beleuchtet werden kann (bei Nutzung aller Lichter sind es acht). Mit geschickter positionierung der Lichter und Aufteilung der Geometrie kann man die Szene trotzdem sauber beleuchten.
Viele Artikel weisen auf das Multipass-Rendering an, wie geschildert, die Szene mehrmals rendern und additiv blenden. Ich habe dies versucht zu vermeiden indem ich Lichtgruppen erzeuge, so kann ich die ganze Szene in einem Pass rendern. Der Nachteil liegt hierbei eben, dass ein Objekt/Polygon nur von max. vier Lichtern beleuchtet werden kann (bei Nutzung aller Lichter sind es acht). Mit geschickter positionierung der Lichter und Aufteilung der Geometrie kann man die Szene trotzdem sauber beleuchten.
- dot
- Establishment
- Beiträge: 1745
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: Mehrere Lichter in einer 3D Szene
Wobei man beim Zusammenfassen auch auf die Unterschiede z.B. in der Farbe oder überhaupt der Art der Lichter achten muss.LPVOID_CH hat geschrieben:Das mit der "Wichtigkeit" der Lichter finde ich einen guten Tipp, danke. Es kann durchaus vorkommen dass zwei Lichter nahe genug sind bzw. der Betrachter zu weit entfernt, so dass die Lichter mehr oder weniger das gleiche beleuchten. Dies könnte dann von einem einzigen Licht beleuchtet werden und man hat ein weiteres Licht zu Verfügung.
Naja, man kann ja wie gesagt beides kombinieren, also eben erst Techniken wie deine anwenden um die Anzahl der Lichtquellen möglichst zu reduzieren und dann die Lichtquellen die da übrig bleiben mit einem Multipassverfahren rendern (hindert dich ja niemand dran da mit 4 Lichtern pro Pass zu arbeiten, das wär sogar ziemlich empfehlenswert).LPVOID_CH hat geschrieben:Viele Artikel weisen auf das Multipass-Rendering an, wie geschildert, die Szene mehrmals rendern und additiv blenden. Ich habe dies versucht zu vermeiden indem ich Lichtgruppen erzeuge, so kann ich die ganze Szene in einem Pass rendern. Der Nachteil liegt hierbei eben, dass ein Objekt/Polygon nur von max. vier Lichtern beleuchtet werden kann (bei Nutzung aller Lichter sind es acht). Mit geschickter positionierung der Lichter und Aufteilung der Geometrie kann man die Szene trotzdem sauber beleuchten.
Re: Mehrere Lichter in einer 3D Szene
Schöne Idee und Erklärung. Beim Zusammenfassen ist nicht unbedingt die Nähe, sondern die Richtung der Lichtquellen aus Sicht der Geometrie maßgebend (Skalarprodukt geht gegen 1 für maximale Richtungsgleichheit) - so kann man bei einer Lichtgruppe evtl. auch weit entfernte Lichtquellen, die aus derselben Richtung kommen, zu einer zusammenfassen. Farben kann man mischen.