Splatter Decals auf Mesh

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Antworten
Benutzeravatar
Jonathan
Establishment
Beiträge: 1823
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Splatter Decals auf Mesh

Beitrag von Jonathan »

'nabend

Ich arbeite gerade an einem kleinen Zombieumballerspiel, und das braucht natürlich entsprechend Effekte. Blutfontänen kriegt man mit Partikelsystemen ganz gut hin, aber wie würde das Zeug mit der Umgebung interagieren? Sprich, wie mache ich Blutlachen? Und das am besten innerhalb eines Abends?

Das Level ist prinzipiell erst einmal ein Mesh. Bzw. eine Ansammlung von Meshs, die unterschiedliche Materialien und so haben können. Das einfachste Verfahren wäre wohl, ein Decal an der entsprechenden Stelle zu platzieren, d.h. man sucht sich die Normale der Oberfläche, richtet ein Quad entsprechend aus, und rendert es minimal über dem Boden. Das ist leicht. Aber solange der Boden keine Ebene ist, steht das Quad dann irgendwo über oder ragt in den Boden hinein und es sieht gleich doof aus. Bei Hügeligen Terrain würde das quasi permanent passieren.
Mein zweiter Gedanke war, das Quad zu unterteilen und jeden Vertex auf das Gelände zu projizieren (die Flugrichtung wäre ja prinzipiell bekannt). Man will aber natürlich für einen einzelnen Fleck nicht hunderte Vertices haben, also gibt es immer noch super viele Situationen in denen das ganz schlecht funktionieren würde. Etwa, wenn man eine 90 Grad Ecke hat, und die Mitte des Sprites dann einfach diagonal verläuft, weil halt kein Vertex zufällig genau in der Kante gelandet ist.
Die nächst bessere Option wäre, sich tatsächlich die Geometrie des Levels anzusehen. Ich projiziere nur die 4 Eckpunkte, schau mir dann aber an, welche Leveldreiecke ich damit treffe und ob man Quad über die Kanten davon hinausgeht und würde dann entsprechend dynamisch neue Vertices erzeugen. Mit etwas Gefummel sollte ich dann die optimale Auflösung bekommen, aber die Implementierung hört sich kniffelig und langwierig an. Das geht irgendwie ganz stark in Richtung von Boolschen-Operationen und von denen hab ich bisher nur nerviges gehört.
Dann könnte ich auch noch einfach einen Render-To-Texture Ansatz wählen. Ich brauche überhaupt keine Extrageometrie sondern editiere einfach die Leveltexturen. Da man aber verschiedene Submeshes mit verschiedenen Materialien treffen kann und Texturen natürlich wiederverwendet werden können und natürlich auch getiled sein können, ist auch das irgendwie kniffelig. Und letztenendes könnte es einfach dazu führen, dass man eine Menge Texture-Memory verschwendet (letztendlich braucht man ja auf irgendeine Art eine Textur die genau einmal über das gesamte Level geht und entsprechend groß ist).
Insgesamt sind die Lösungen alle nicht toll. Entweder würde man garantiert ständig sehr hässliche Artefakte bekommen, oder es ist ziemlich aufwändig zu entwickeln und selbst dann vielleicht ineffizient.

Eine letzte Idee wäre es vielleicht noch, diese Flecken oder Lachen nicht als eine große Textur darzustellen, sondern quasi auch als Partikel. Die wären deutlich kleiner und würden individuell ins Level projiziert und könnten dann einfache Quads sein, so dass man die Artefakte nicht sieht, solange man nicht zu genau hinschaut. Das Problem wäre natürlich, entsprechend die passende Struktur darein zu bekommen. Es würde dann halt immer irgendwie wie eine Sammlung an kleinen Flecken aussehen und nicht wie ein zusammenhängendes Ganzes.

Tjo, habt ihr noch gute Ideen? Wie gesagt, ich suche insbesondere nach so einer 80/20 Lösung (80 % des Ergebnis mit 20% der Arbeit).
Lieber dumm fragen, als dumm bleiben!
Specialist
Establishment
Beiträge: 121
Registriert: 29.08.2003, 14:22
Kontaktdaten:

Re: Splatter Decals auf Mesh

Beitrag von Specialist »

Ich hatte vor einigen Wochen mal diese Screen Space Decals Umsetzung gesehen.
Vielleicht hilft dir das weiter:

https://de.slideshare.net/blindrenderer ... e-14699854

https://de.slideshare.net/philiphammer/ ... he-surge-2
Benutzeravatar
Jonathan
Establishment
Beiträge: 1823
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: Splatter Decals auf Mesh

Beitrag von Jonathan »

Hm, das sieht interessant aus, danke!

Ich habe dazu noch folgenden Artikel gefunden: https://martindevans.me/game-developmen ... ce-Decals/

Hm, ein Problem ist, dass ich einen Forward-Renderer habe, aktuell habe ich also noch nicht direkt einen Tiefen- und Normalbuffer der Szene (ich schätze, letzteren bräuchte ich, um die Decals entsprechend zu beleuchten?). Aber wenn man die hätte, klingt es tatsächlich nicht so schwer: Statt Quads rendert man eben Würfel und im Shader wird pro Pixel die passende UV-Koordinate berechnet und schon hat man seine passenden Decals. Kniffelig ist vielleicht noch, die passende Würfel-Größe zu finden, ich schätze je unebener der Untergrund ist, desto tiefer müssen die Würfel auch sein um sicherzustellen, dass man alle benötigten Pixel abdeckt.

Wobei - den Tiefenbuffer sollte man ja tatsächlich unabhängig vom ersten Pass bekommen können, den braucht man ja sowieso. Und vielleicht könnte man den dann auch gleich verwenden, um mal SSAO zu implementieren. Ich schau mir das mal noch etwas mehr im Detail an, aber insgesamt hört es sich schon nicht schlecht an.
Lieber dumm fragen, als dumm bleiben!
Specialist
Establishment
Beiträge: 121
Registriert: 29.08.2003, 14:22
Kontaktdaten:

Re: Splatter Decals auf Mesh

Beitrag von Specialist »

Ich werde, wenn ich mit dem Rest meiner Engine so weit bin, auf jeden Fall diesen Ansatz verfolgen.
Das scheint mir um einiges eleganter und angenehmer zu implementieren zu sein, als die klassischen Ansätze, bei denen man das Decal-Quad umständlich an der Geometrie ausrichten und clippen muss.
Übrigens, Deferred Renderer lohnt sich.
David
Beiträge: 1
Registriert: 10.07.2004, 15:47
Kontaktdaten:

Re: Splatter Decals auf Mesh

Beitrag von David »

Hier der Highlevel Überblick:

Eine populäre Methode für Decals in einer Forward Pipeline war die unterliegende Geometrie an den vier begrenzenden Ebenen des Decals zu clippen und daraus ein Mesh mit entsprechenden UV Koordinaten zu erzeugen (Quake 3, Doom 3). Das Mesh wird dann als eigenständiges Objekt gerendert (depth offset gegen z-fighting). Die Methode ist alt und funktioniert so ziemlich mit allen APIs/Renderer Designs.

Etwas moderner und mit mehr Features sind die genannten Deferred Decals. Der Ansatz integriert sich hervorragend in eine Deferred Render Pipeline. Die Idee ist, Decals ähnlich wie Lichter in einem vanilla Deferred Renderer zu handhaben. Für das Decal wird ein Proxy gerendert, im Pixelshader wird die Position vom Pixel im Decal-Space konstruiert und das Decal-Material an dieser Stelle gesampled. Das nette ist, das die Materialinformation in den G-Buffer geblendet werden kann, d.h. das Decal kann unterliegende Geometrieeigenschaften verändern (z.B. Pfützen drehen an der Roughness/Albedo, ...).

Den "klassische" Ansatz, der in der Präsentation von Surge 2 erwähnt wird, stammt übrigens noch von mir und ist in etwa wie oben beschrieben umgesetzt. Das Problem mit dem Ansatz ist, das der CPU Overhead relativ hoch ist da für jedes Decal ein Drawcall gepushed wird. Typischerweise mit eigenem State (unterschiedliche Texturen, ...) was im Zweifel das Risiko erhöht das die Context Register auf der GPU voll laufen und der CP stalled (Understanding GPU Context Rolls). Also keine besonders guten Voraussetzungen für rohe Mengen an Decals. Der Ansatz wurde dennoch in einigen Spielen geshipped. Sind Decals en masse notwendig muss gebatched werden. Eine Option das zu umschiffen wäre z.B. einen Textureatlas zu erstellen. Mit Vulkan/DX12 (oder per Extension auch ältere APIs) ist Bindless ein weiterer Ansatz um Decals zu batchen (Bindless Texturing for Deferred Rendering and Decals, Bindles Deferred Decals in The Surge 2).

Prinzipiell könnte man versuchen Deferred Decals in eine Forward Pipeline zu integrieren, ich könnte mir vorstellen, dass das mit Limitationen funktioniert. Das würde allerdings mindestens einen kompletten Early-Z Pass notwendig machen. Ich glaube(tm) UE4 hat eine Option Decal Material Parameter in einen D-Buffer zu rendern, quasi ganz im Sinn wie ein G-Buffer funktioniert. Dieser D-Buffer kann beim rendern von Objekten gelesen werden. Allerdings gibt es Ansätze die deutlich besser skalieren, z.B. in Forward+ Pipelines (Forward Decal Rendering, THE DEVIL IS IN THE DETAILS ID Tech 666). Hier werden Decals wie Lichter in Cluster sortiert und geculled. Beim rendern der Objekte werden die Decals im Cluster einmal der Reihe nach durchlaufen und auf die Geometrie projiziert vor der Beleuchtung.

Generell haben Deferred Decals (wie auch die alte Variante) eine Menge an Fallstricken und Edgecases die zu umschiffen sind. Überlegungen sind z.B.
- Wie sollen Normalen mit den darunterliegenden Normalen der Oberfläche geblendet werden
- "Smearing" an Kanten
- Manuelle Auswahl des Mip-Levels da Gradienten fehlen
- Artefakte an Tiefen-Diskontinuitäten
- Leaken auf Objekte die vom Decal unberührt bleiben sollen (maskieren im Shader oder Stencil)
- Interaktion mit bewegten Objekten oder deformierbaren Objekten

Für LotF hatte ich mal einen (nicht technischen) Artikel für die Making Games geschrieben: Building your own engine, part 3 – Visual effects for the next generation, wo einige der Probleme Bebildert sind. Ein Artikel der einige der Themen technischer behandelt, z.B. hier: Fixing screen-space deferred decals
Benutzeravatar
Schrompf
Moderator
Beiträge: 4392
Registriert: 26.02.2009, 00:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: Splatter Decals auf Mesh

Beitrag von Schrompf »

Schöne Zusammenfassung und intensiv verlinkt! Danke.
Häuptling von Dreamworlds. Baut an was Neuem. Hilft nebenbei nur höchst selten an der Open Asset Import Library mit.
Benutzeravatar
marcgfx
Establishment
Beiträge: 1823
Registriert: 18.10.2010, 23:26

Re: Splatter Decals auf Mesh

Beitrag von marcgfx »

Echt schön die Zusammenfassung. Noch schöner finde ich aber das :)

David
Beiträge: 1
Registriert: 10.07.2004, 15:47

Sehr geil der Einstieg!
Antworten