Diesen Artikel haben wir geschrieben, um Ihnen zu helfen zu verstehen, wie die Dinge auf dem Bildschirm dargestellt werden und wie mit Transparenz in BabylonJS umgegangen wird.
Allgemeine Ordnung.
Eine allgemeine Faustregel für das Echtzeit-3D-Rendering ist, dass das Zeichnen mehrerer sich überlappender undurchsichtiger Objekte immer einfacher ist als das Zeichnen nichtdurchsichtiger Objekte. Dies liegt daran, dass opake Objekte mit der Verwendung eines Depth-Buffers kompatibel sind und somit keine bestimmte Reihenfolge bei der Darstellung erforderlich ist.
Ein Depth Buffer ist eine Oberfläche mit den gleichen Abmessungen wie der Bildschirm und enthält für jedes Pixel die folgende Information: wie weit von der Kamera entfernt war das letzte hier gezeichnete Pixel. Mit diesen Informationen können wir so viele Objekte zeichnen, wie wir wollen und immer sicher sein, dass wir nie etwas zeichnen werden, das von einem anderen Objekt verborgen werden sollte. BabylonJS bietet den Zugriff auf diese Informationen mit einem speziellen DepthRenderer-Objekt.
Das Rendern von Objekten ohne Depth Buffer würde den Einsatz einer Old-School-Technik mit der Bezeichnung Painter`s Algorithmus erfordern, welche extrem einfach eingesetzt werden kann: Zeichnen Sie zuerst weitere Objekte. Den Himmel, anschließend den Hintergrund etc. bis hin zu Vordergrundobjekten. Dies ist im Grunde genommen die Anordnung nach der Entfernung von der Kamera (alias Tiefe), und in den meisten Fällen offensichtlich nicht ausreichend.
Das Testen gegen einen Depth Buffer während des Renderns ist eine sehr verbreitete Technik, einfach zu implementieren und leistungsmäßig kostengünstig. Bei nicht-opaken Objekten wird es jedoch komplizierter, da ein Depth Buffer nicht mehr verwendet werden kann (da diese Objekte nicht vollständig verbergen, was hinter ihnen steckt).
Rendering-Auftrag.
Bevor BabylonJS die Meshes auf dem Bildschirm zeichnet, ordnet es sie in die folgenden Kategorien ein, die in der Reihenfolge Ihrer Zeichnung dargestellt werden:
- Depth Pre-Pass Meshes
- Opake Meshes
- Alpha-getestete Meshes
- Alpha blended Meshes nach Tiefe sortiert (=Abstand zur Kamera)
- Sprites (vom SpriteManager verwaltet)
- Partikel (bearbeitet durch das ParticleSystem)
Die letzten beiden Kategorien sind selbsterklärend. Beachten Sie, dass sie immer nach allen anderen Meshes gezeichnet werden und dass sie keinen Depth-Buffer verwenden, der möglicherweise zuvor erstellt wurde. Diese können nicht einfach durch normale Meshes verdeckt werden.
Rendering-Gruppen.
Renderbare Objekte können in Rendering-Gruppen organisiert werden, die als Ebenen fungieren. Ebenen werden in aufsteigender Reihenfolge nach ID gerendert, beginnend mit der Standardebene (die die ID 0 hat). Innerhalb jeder Rendering-Gruppe wird auch die oben genannte „Allgemeine Ordnung“ verwendet.
Um Rendering-Gruppen zu verwenden, müssen Sie lediglich die Eigenschaft .renderingGroupId auf die Objekte setzen, die Sie in andere als die standardmäßige Ebene einfügen möchten.
Diese Eigenschaft existiert auf Meshes, Partikelsystemen und SpriteManagern.
Standardmäßig gibt es insgesamt 4 Rendering-Gruppen, was bedeutet, dass die einzigen gültigen Ids 0, 1, 2 und 3 sind. Dies kann erhöht werden, indem die statische Eigenschaft BABYLON.RenderingManager.MAX_RENDERINGGROUPS auf die gewünschte maximale ID gesetzt wird (z.B. auf 8 gesetzt, um 7 Rendergruppen zu unterstützen).
Alpha-Index.
Meshes haben eine weitere Eigenschaft, die einen Einfluss auf die Rendering-Reihenfolge hat: .alphaIndex
Standardmäßig ist diese Eigenschaft auf Number.MAX_VALUE gesetzt, was der höchste Wert ist, den eine numerische Variable halten kann (etwa 1.79E+308).
Im Gegensatz zu undurchsichtigen und alpha-getesteten Meshes sortiert die BabylonJS-Rendering-Engine alpha-gemischte Meshes nach Tiefe, bevor sie auf dem Bildschirm gezeichnet werden. Die .alphaIndex-Eigenschaft ermöglicht es Ihnen, diese Sortierung zu überschreiben, da ein Mesh, das einen niedrigeren Alpha-Index als ein anderes hat, immer davor gerendert wird, unabhängig von seiner jeweiligen Tiefe.
Um es einfacher auszudrücken: alpha-blended werden zuerst nach Alpha-Index und anschließend nach Tiefe /Entfernung zur Kamera) sortiert).
Beachten Sie, dass diese Eigenschaft nur für alpha-blended Meshes funktioniert und absolut keine Auswirkungen auf opake oder alpha-getestete Meshes hat.
Hinweis: Diese Eigenschaft kann mit dem BabylonJS-Exporter-Plugin manuell auf Meshes in 3ds Max gesetzt werden.
Opak oder transparent?
Wie Ihre Meshes kategorisiert werden, kann für den letzten Aspekt Ihrer Szene sehr wichtig sein. Lassen Sie uns einen genaueren Blick darauf werfen, wie ersten 4 Kategorien definiert sind.
Depth Pre-Pass Meshes.
Depth Pre-Pass Meshes definieren einen zusätzlichen Rendering-Pass für Meshes. Während dieses Durchgangs werden die Meshes nur im Depth Buffer gerendert. Die Depth Pre-Pass Meshes für die Tiefe sind nicht exklusiv. Ein Mesh kann einen tiefen Vorlauf und einen undurchsichtigen oder Alpha-Mischlauf aufweisen. Die Aktivierung des Depth Pre-Pass für ein Mesh, initiiert den Aufruf mesh.material.needDepthPrePass = true. Das Ziel ist es, entweder die Szene zu optimieren, indem man Meshes in den Depth Buffer rendert, um Überziehungen zu reduzieren, oder dazu beizutragen, Probleme beim Sortieren von Alpha-Blending zu reduzieren.
Opake Meshes.
Diese werden am einfachsten zu rendern sein: Ihre Polygone werden vollständig auf dem Bildschirm mit ihren Farben und Texturen gezeichnet. Ein Depth Buffer wird verwendet, um sicherzustellen, dass nichts über etwas gezogen wird, das näher an der Kamera liegt.
Alpha-getestete Meshes.
Wie bei opaken Meshes, nur dass einige Teile dieser Meshes als völlig transparent definiert werden können. Alpha-Text bedeutet, dass jedes Pixel des Mesh entweder opak (und anschließend auf dem Bildschirm und im Depth Buffer gezeichnet) oder transparent sein kann, was bedeutet, dass das Pixel vollständig verworfen wird. Obwohl sehr effizienz, erzeugt diese Art des Renderings in der Regel Aliasing-Grenzen und erlaubt keine glatten Transparenzeffekte.
Ein Pixel gilt als transparent, wenn sein Alpha-Wert < 0,4 ist und nicht opak ist. Dieser Wert ist derzeit fest programmiert.
Alpha blended Meshes.
Diese Meshes haben durchsichtige Teile, die einen Alpha-Wert von 0,0 (völlig transparent) bis 1,0 (völlig undurchsichtig) aufweisen können. Ihre Farbe wird mit dem, was hinter Ihnen liegt, vermischt, um das zu reflektieren. Diese Meshes werden nach Tiefe sortiert, basierend auf dem Zentrum Ihrer begrenzten Kugel. Dies verhindert nicht, dass sich einige Probleme ergeben, wenn sich mehrere Alpha-blended Meshes überlappen.
Beachten Sie auch, dass das Entfernen der Rückseiten für Alpha-blended Meshes so ziemlich obligatorisch ist, da sonst Polygone von der Vorder- und Rückseite der Objekte durcheinander geworfen werden (es sei denn, Sie verwenden einen Depth Pre-Pass).
Alpha-blended Meshes:
- Jedes Mesh, bei der
- die Eigenschaft hasVertexAlpha auf true gesetzt ist (wird automatisch für exportierte Meshes gesetzt, wenn Nodes individuelle Alpha-(Transparenz-)Werte haben)
- oder ein Visibility-Wert < 1 vorliegt.
- Im Falle eines Meshes mit StandardMaterial, wenn es Folgendes hat:
- eine definierte Opazitätstextur,
- einen aktiven Opazitäts -Fresnel-Effekt.
- Im Falle eines anderen Materialtyps, wenn die Funktion .needAlphaBlending() des Materials true zurückgibt.
Alpha getestete Meshes:
- Im Falle eines Meshes mit StandardMaterial, falls vorhanden:
- eine diffuse Textur mit der Eigenschaft .hasAlpha, die auf true gesetzt ist.
- Im Falle eines anderen Materialtyps, wenn die Funktion .needAlphaTesting() des Materials true zurückgibt.
Opake Meshes:
- Jedes Mesh, das nicht in eine der oben genannten Kategorien passt.
Gelegentlich kann es vorkommen, dass einige Ihrer Meshes in die falsche Kategorie fallen, z.B. ein alpha-getestetes Mesh, das unnötigerweise als alpha-blended markiert ist oder ein Mesh, das undurchsichtig bleibt, wenn es das nicht sollte. Dies wird seltsame Störungen verursachen, die manchmal sehr ärgerlich sein können.
Was gemacht werden sollte und was nicht.
- Achten Sie darauf, dass sich Ihre Alpha-blended Meshes nicht schneiden, da dies unweigerlich zu Renderfehlern führt.
- Vermeiden Sie stark gestreckte Alpha-blended Meshes (d.h. große Flächen), da das Zentrum seiner Bounding Sphere für das Depth Sorting verwendet wird, kann dies dazu führen, dass ein Gewebe so weit von der Kamera entfernt, aber tatsächlich näher an viele andere Meshes sortiert wird.
- Verwenden Sie Alpha-Test so oft wie möglich. Dies kann für einen Pixel-Art-Style perfekt aussehen oder wenn die transparenten Teilegrenzen gerade horizontale oder vertikale Linien sind.
- Um gezackte Kanten auf Ihren alphagetesteten Meshes zu beseitigen, verwenden Sie Anti-Aliasing für Ihre Szenen (FxaaPostProcess). Bei der Verwendung von Anti-Aliasing können Sie sogar die integrierte Glättung von WebGL beim Erstellen des Engine-Objekts deaktivieren:
Dies kann Ihnen bei sichtbaren Seams zwischen den Meshes und anderen ähnlichen Problemen helfen:
- Vergessen Sie nicht, dass Aussortieren der Rückseiten mit Alpha-blended Meshes zu aktivieren.
- Verwenden Sie Rendering-Gruppen, um die Reihenfolge, in der Ihre Meshes angezeigt werden, besser zu kontrollieren. Diese sind besonders nützlich, wenn Sie wissen, dass einige Meshes zu 100% über anderen liegen werden (z.B. eine überlagerte Benutzeroberfläche, die über der Szene gezeichnet wurde).
- Die Eigenschaft alphaIndex eines Meshes kann ebenfalls sehr nützlich sein, da sie es Ihnen ermöglicht, das Depth Sorting von alpha-blended Meshes zu überschreiben. Auch diese Eigenschaft leidet nicht unter der gleichen Einschränkung wie die Renderinggruppen (maximal 4 Ebenen) und hat nur Auswirkungen auf alpha-blended Meshes.
- Sie können sich darauf verlassen, dass needDepthPrePass Ihnen hilft, Probleme mit Selbsttransparenz zu lösen.
- Sie können separateCullingPass auf Materialien verwenden, um die Engine zu zwingen, die transparenten Objekte in 2 Durchgängen zu rendern. Zuerst rendern Sie die Rückseiten und anschließend die Vorderseiten. Dies kann bei der Selbsttransparenz sehr hilfreich sein.
- Um sowohl die Kosten für needDepthPrePass als auch für separateCullingPass zu vermeiden, wenn die Summes Ihres Alpha unter 1,0 bleibt, können Sie den AlphaModus des Materials uf Engine.ALPHA_PREMULTIPLIED oder Engine.ALPHA_PREMULTIFIED_PORTERDUFF ändern, was die Notwendigkeit der Bestellung der Dreiecke verhindert.
Damit sind wir mit unserem heutigen Beitrag zum Thema „Transparenz und Rendern von Meshes mithilfe von BabylonJS“ soweit durch. Wenn Sie noch Anregungen oder Fragen haben sollten, hinterlassen Sie uns unten einen Kommentar.
Vielen Dank für Ihren Besuch.