Filme, Spiele und andere 3D Grafikproduktionen erzeugen, speichern und senden oft eine große Datenmenge. Diese Daten können aus verschiedener Software (etwa Unreal Engine, Maya, Houdini oder Blender) innerhalb der Kunst-Pipeline stammen, die jeweils über ihre eigene proprietäre Form der Szenenbeschreibung verfügen.
Das Austauschformat Universal Scene Description (USD) ist ein Open-Source-Format, das von Pixar entwickelt wurde, um die Notwendigkeit zu erfüllen, beliebige 3D-Szenen, die aus vielen elementaren Assets bestehen können, robust und skalierbar auszutauschen und zu ergänzen. USD bietet nicht nur einen umfangreichen Werkzeugsatz zum Lesen, Schreiben, Bearbeiten und für die schnelle Vorschau von 3D-Geometrie und Schattierung, sondern ermöglicht auch den Austausch grundlegender Assets (zum Beispiel Modelle) oder Animationen.
Im Gegensatz zu anderen Austauschpaketen ermöglicht USD auch die Zusammenstellung und Organisation einer beliebigen Anzahl von Assets in virtuellen Sets, Szenen und Aufnahmen. Sie können diese dann von Anwendung zu Anwendung senden und sie (als Überschreibungen) mit einer einzigen, konsistenten API in einem einzigen Szenendiagramm nicht-destruktiv bearbeiten.
Warum USD verwenden?
USD bietet eine gemeinsame Sprache für den Bewegung großer Datenmengen zwischen verschiedenen 3D-Anwendungen. Das bietet Flexibilität bei Entscheidungen über Ihre Kunst-Pipeline und erleichtert die Zusammenarbeit mehrerer 3D Artists (Animatoren, Beleuchtung oder Schattierungs-Artisten, Modellierer, FX-Künstler und mehr) mithilfe iterativer und nicht-destruktiver Methoden.
USD-Support in Unreal Engine
Unreal Engine bietet USD-Support über das Panel USD Stage und bidirektionale Python-Workflows.
Das Fenster „USD Stage“. Klicken Sie auf das Bild, um es in voller Größe zu sehen.
Anstatt USD-Daten in native Unreal Engine-Assets wie Statisches Meshs und Materialien zu konvertieren, arbeitet der USD-Bühnen-Workflow nativ mit Ihren USD-Daten. Dadurch werden Ihre USD-Daten schneller in Unreal Engine übertragen, Sie erhalten einen klareren Überblick über die ursprüngliche Struktur Ihres USD-Inhalts und können Live-Updates verarbeiten, während Sie Änderungen an der USD-Quelldatei auf der Festplatte vornehmen.
Die USD-Bühne bietet Ihnen folgende Funktionalität:
- Repräsentiert 3D-Daten als „Prims“: Statisches Meshs, Skelett-Meshs, HISM, Materialien, Lichter, Kameras, Varianten, Animation und Blendshapes.
- Nicht-destruktive Attributbearbeitung.
- USD-Szenendiagramm und Hierarchievisualisierung.
- Inhalt mit Nutzlasten laden und entladen.
- Support für Texturen mit USD-Vorschauoberflächen.
- Support für Materialien mit PreviewSurface und DisplayColor.
- Support für USD-Plugins wie Alembic und Custom Path Resolver.
- Zur Laufzeit unterstützte USD-Funktionen. Weitere Informationen finden Sie unter USD-Laufzeit-Support.
- Lädt die Formate „.usd“, „.usda“, „.usdc“ und „.usdz“.
Weitere allgemeine Informationen zu „Universal Scene Description“ finden Sie unter Introduction to USD von Pixar.
Weitere Informationen zur Arbeit mit dem Python-Workflow finden Sie unter Python-Scripting
Unterstützte Aktionen
Import in Unreal Engine
Inhalte, die auf der USD-Bühne angezeigt werden (Statisches Meshs, Skelett-Meshs, Lichter, Vegetation und Landschaften), können mit folgenden Methoden in Unreal Engine importiert werden:
- Mithilfe von File > Import Into Level. Bei diesem Vorgang werden sowohl Assets (Statisches Mesh, Skelett-Mesh, Materialien, Texturen usw.) als auch Actors importiert.
- Über die Schaltfläche Add/Import im Inhaltsbrowser. Dieser Vorgang importiert nur Assets.
- Ziehen und ablegen der Datei im Inhaltsbrowser. Dieser Vorgang importiert nur Assets.
- Über die Option Action > Import im USD-Bühneneditor. Bei diesem Prozess werden sowohl Assets als auch Actors importiert. Nach Abschluss des Importvorgangs werden Assets auf der USD-Bühne durch neue Actors aus Ihrem Inhaltsbrowser ersetzt.
Erstellen und Bearbeiten von Animationen
Auf Animationen, die in einer USD-Datei gespeichert sind, können Sie über die assoziierte Level-Sequenz zugreifen, die im Panel Properties* des USDStageActor** zu finden ist.
Öffnen Sie die Level-Sequenz, indem Sie die USD-Level-Bühne auswählen und im Panel „Properties“ auf die Sequenz doppelklicken. Bild für Großansicht anklicken.
USD-xform-Animationen werden als Transform-Tracks innerhalb der Level-Sequenz angezeigt. Andere Animation wie Floats, boolesche Variablen und Skelett-Bones werden über den Time-Track angezeigt. Die USD-Animationsdaten im obigen Bild werden für die Dauer der Animation bei jedem Zeitcode als Schlüssel-/Wertepaar dargestellt.
Über die von der USD -Bühne Level-Sequenz können Sie sich an einen Actor binden, der auf der USD-Bühne gespawnt wird, und über einen Transform-Track zusätzliche Animation hinzufügen.
USD-Laufzeit-Support
Unreal Engine unterstützt das Laden von USD-Dateien zur Laufzeit durch Abruf des Knotens „Set Root Layer Blueprint“ auf einem USD-Bühnen-Actor innerhalb des Levels.
Der Knoten „Set Root Layer“. Klicken Sie auf das Bild, um es in voller Größe zu sehen.
Dieser Knoten erstellt die benötigten Assets und spawnt Actors und Komponenten im Level, ähnlich wie der Prozess im Editor gehandhabt wird. Zu den zusätzlichen Blueprint-Funktionen zur Steuerung verschiedener USD-Bühnen-Actor-Eigenschaften gehören:
| Blueprint-Funktion | Beschreibung |
|---|---|
| Get Generated Assets | Holt die Assets, die für eine Prim innerhalb eines bestimmten Prim-Pfads generiert wurden, und platziert sie in einem Array. Verwendet einen USD-Bühnen-Actor und einen Prim-Pfad als Inputs. |
| Get Generated Components | Holt die Komponente, die für eine Prim innerhalb eines bestimmten Prim-Pfads generiert wurde. Verwendet einen USD-Bühnen-Actor und einen Prim-Pfad als Inputs. |
| Get Source Prim Path | Holt den Prim-Pfad für ein bestimmtes Objekt auf der USD-Bühne. Verwendet einen USD-Bühnen-Actor und eine Objekt-Referenz als Inputs. |
| Get Time | Holt den aktuellen Zeitstempel im Ziel-USD-Bühnen-Actor. Nimmt einen USD-Bühnen-Actor als Ziel. |
| Set Initial Load Set | Legt die anfängliche zu ladende Nutzlast fest. Verwendet einen USD-Bühnen-Actor als Input und bietet folgende Optionen.
|
| Set Purpose to Load | Legt den anfänglich zu ladenden Zweck fest. Verwendet einen USD-Bühnen-Actor und einen Ganzzahl als Input.
|
| Set Render Context | Legt den Render-Kontext auf eine USD-Bühne fest. Nimmt einen USD-Bühnen-Actor als Ziel und eine Referenz zu einem Render-Kontext als Input. |
| Set Time | Legt den aktuellen Zeitstempel einer USD-Bühne fest. Nimmt einen USD-Bühnen-Actor als Ziel und einen Float-Wert als Input. |
Weitere Informationen zum Attribut „Purpose“ und anderen USD-Begriffen finden Sie im USD-Glossar von Pixar.
Mit diesem Prozess können Sie Anwendungen erstellen, die Inhalte einer USD-Datei zur Laufzeit laden und anzeigen.
Um den USD-Importeur zur Laufzeit zu aktivieren, fügen Sie die folgende Zeile zu Ihrer Projekt.Target.cs-Datei aus dem Ordner UE_(Version)\Engine\Source, wobei „Projekt“ der Name Ihres Projekts ist:
GlobalDefinitions.Add("FORCE_ANSI_ALLOCATOR=1");
Zum Beispiel:
public class YourProjectTarget : TargetRules
{
public YourProjectTarget( TargetInfo Target) : base(Target)
{
Type = TargetType.Game;
DefaultBuildSettings = BuildSettingsVersion.V2;
ExtraModuleNames.AddRange( new string[] { "YourProjekt" } );
GlobalDefinitions.Add("FORCE_ANSI_ALLOCATOR=1");
}
}
Nvidia MDL-Support
Unreal Engine unterstützt MDL-Oberflächenmaterialien mittels des Nvidia MDL-USD-Schemas. Weitere Informationen zu Nvidia MDL finden Sie auf NVIDIAs USD Shader Attributes.
Support für Multi-User-Bearbeitung
Multinutzer-Bearbeitung wird von vielen USD-Bühnen-Operationen unterstützt, darunter die folgenden:
- Hinzufügen und Entfernen von Prims.
- Prims umbenennen.
- Prim-Attribute bearbeiten.
- Umschalten der Sichtbarkeit.
- Öffnen, Schließen oder Ändern der aktuellen Bühne.
Um den Multinutzer-Support für Ihr USD-Projekt zu aktivieren, aktivieren Sie das Plugin USD Multi-User synchronization. Weitere Informationen zur Arbeit mit Plugins finden Sie unter Working with Plugins
Die USD-Multinutzer-Bearbeitung synchronisiert die Eigenschaft Root Layer der USD-Bühne für jeden Client, um sicherzustellen, dass alle Nutzer die gleichen USD-Dateien haben. Dies wird dadurch erreicht, dass jeder Client dieselbe USD-Bühne lokal öffnet, Assets und Komponenten auf seinem eigenen System spawnt und dann nur die an diesen Assets durchgeführten Vorgänge synchronisiert.
Während einer Multinutzer-Bearbeitungssitzung ist es wichtig, dass alle Nutzer über denselben Dateipfad auf die USD-Dateien zugreifen. Um sicherzustellen, dass jeder Client auf dieselben Dateien zugreifen kann, empfehlen wir, die Ziel-USD-Dateien im Projektordner zu speichern und mithilfe der Quellkontrolle zu verwalten.
Weitere Informationen zur Multinutzer-Bearbeitung in Unreal Engine finden Sie unter Multi-User Editing in Unreal Engine
Es ist nicht möglich, die Löschung von Prims während einer Multinutzer-Sitzung rückgängig zu machen.
Aktivieren des „USD Import Plugin“
Um mit einer USD-Datei im Unreal Editor zu arbeiten, müssen Sie das Plugin USD Importer im Menü Plugins aktivieren. Weitere Informationen zur Arbeit mit Plugins finden Sie unter Working with Plugins
Nach dem Neustart des Editors sehen Sie die neue Option USD Stage, die im Menü Window > Virtual Production im Level-Editor aufgeführt ist.
Das Panel Place Actors listet einen neuen USD-Bühnen-Actor auf, den Sie Ihrem Level hinzufügen können.
Neue USD-Actors im Place-Actors-Panel verfügbar
Verwenden von USD in Unreal Engine
Die Arbeit mit USD-Inhalten in Unreal Engine beginnt mit dem USD-Bühneneditor und dem USD-Bühnen-Actor.
Das USD-Bühnen-Panel.
| Nummer | Beschreibung |
|---|---|
| 1 | Hierarchie |
| 2 | Eigenschaften |
| 3 | Ebenen |
USD-Bühnen-Workflow
Ein USD-Bühnen-Actor agiert als Container für die Inhalte einer geladenen USD-Datei und bietet einen Anker für diese Daten in Ihrem Level. Die 3D-Szenenobjekte, die aus der USD-Datei geladen und im Viewport angezeigt werden, sind vollständig kompatibel mit den meisten anderen Funktionen von Unreal Engine und können wie andere Actors behandelt werden. Sie können weitere Prims hinzufügen, die auf Inhalte in anderen USD-Dateien referenzieren, darunter animierte Skelett-Meshs.
Wenn Sie Änderungen an Ihrer USD-Bühne über das Menü File > Save im USD-Bühneneditor speichern, werden diese Änderungen in Ihre USD-Datei zurückgeschrieben.
Weitere Informationen zur Arbeit mit der USD-Bühne finden Sie unter Schnellstart für den USD-Bühneneditor
Unreal Engine erstellt nicht automatisch Light-Maps für Assets, die auf der USD-Bühne geladen wurden, wenn eine USD-Datei geöffnet wird. Das kann zu einer komplett schwarzen Szene führen, wenn statische Beleuchtung aufgebaut wird.
Python-Scripting
Python-Scripting mit USD bietet Ihnen eine flexible Möglichkeit, eine Reihe von Aktionen wie Batch-Operationen und Szenenbearbeitungen durchzuführen, die über die Benutzeroberfläche schwierig oder zeitaufwendig sein könnten. Operationen wie das Verstecken oder Bearbeiten der Attribute von vielen Prims können Sie schnell automatisieren, indem Sie ein flexibles Python-Script aus dem Output-Log-Panel starten.
Bevor Sie Python verwenden können, müssen Sie das Plugin Python Editor Script aktivieren. Weitere Informationen zu Plugins finden Sie unter Working with Plugins.
Sie können anschließend das Output-Log verwenden, das sich am unteren Rand des Level-Editors befindet, um Python-Scripts auszuführen. Sie können auch das Output-Log als eigenes Panel über Window > Output-Log öffnen.
Bild für Großansicht anklicken.
Weitere Informationen zur Verwendung von Python-Scripting mit Unreal Engine finden Sie unter Scripting the Unreal Editor Using Python.
Anwendungsfall für die Nutzung eines Python-Scripts
Als die mit Unreal Engine ausgelieferte USD SDK-Version auf 21.05 aktualisiert wurde, wurden durch das Update mehrere Attribute innerhalb der USDLux Light-Schemas umbenannt. Um das Problem zu lösen, enthält Unreal Engine ein Python-Script, das USDLux-Prim-Attribute entsprechend der Benennungskonvention aus 21.05 umbenennt.
from pxr import Usd, Sdf, UsdLux
import argparse
def rename_spec(layer, edit, prim_path, attribute, prefix_before, prefix_after):
path_before = prim_path.AppendProperty(prefix_before + attribute)
path_after = prim_path.AppendProperty(prefix_after + attribute)
# Wir müssen jedes Mal prüfen, weil das Hinzufügen einer Namespace-Bearbeitung, die nicht angewendet werden kann, nur den gesamten Batch abbricht
if layer.GetAttributeAtPath(path_before):
print(f"Versuche '{path_before}' in '{path_after}' umzubenennen")
edit.Add(path_before, path_after)
def rename_specs(layer, edit, prim_path, reverse=False):
prefix_before = 'inputs:' if reverse else ''
prefix_after = '' if reverse else 'inputs:'
# Licht
rename_spec(layer, edit, prim_path, 'intensity', prefix_before, prefix_after)
rename_spec(layer, edit, prim_path, 'exposure', prefix_before, prefix_after)
rename_spec(layer, edit, prim_path, 'diffuse', prefix_before, prefix_after)
rename_spec(layer, edit, prim_path, 'specular', prefix_before, prefix_after)
rename_spec(layer, edit, prim_path, 'normalize', prefix_before, prefix_after)
rename_spec(layer, edit, prim_path, 'color', prefix_before, prefix_after)
rename_spec(layer, edit, prim_path, 'enableColorTemperature', prefix_before, prefix_after)
rename_spec(layer, edit, prim_path, 'colorTemperature', prefix_before, prefix_after)
# ShapingAPI
rename_spec(layer, edit, prim_path, 'shaping:focus', prefix_before, prefix_after)
rename_spec(layer, edit, prim_path, 'shaping:focusTint', prefix_before, prefix_after)
rename_spec(layer, edit, prim_path, 'shaping:cone:angle', prefix_before, prefix_after)
rename_spec(layer, edit, prim_path, 'shaping:cone:softness', prefix_before, prefix_after)
rename_spec(layer, edit, prim_path, 'shaping:ies:file', prefix_before, prefix_after)
rename_spec(layer, edit, prim_path, 'shaping:ies:angleScale', prefix_before, prefix_after)
rename_spec(layer, edit, prim_path, 'shaping:ies:normalize', prefix_before, prefix_after)
# ShadowAPI
rename_spec(layer, edit, prim_path, 'shadow:enable', prefix_before, prefix_after)
rename_spec(layer, edit, prim_path, 'shadow:color', prefix_before, prefix_after)
rename_spec(layer, edit, prim_path, 'shadow:distance', prefix_before, prefix_after)
rename_spec(layer, edit, prim_path, 'shadow:falloff', prefix_before, prefix_after)
rename_spec(layer, edit, prim_path, 'shadow:falloffGamma', prefix_before, prefix_after)
# DistantLight
rename_spec(layer, edit, prim_path, 'angle', prefix_before, prefix_after)
# DiskLight, SphereLight, CylinderLight
# Hinweis: treatAsPoint sollte nicht das Präfix „inputs:“ haben, also ignorieren wir es
rename_spec(layer, edit, prim_path, 'radius', prefix_before, prefix_after)
# RectLight
rename_spec(layer, edit, prim_path, 'width', prefix_before, prefix_after)
rename_spec(layer, edit, prim_path, 'height', prefix_before, prefix_after)
# CylinderLight
rename_spec(layer, edit, prim_path, 'length', prefix_before, prefix_after)
# RectLight, DomeLight
rename_spec(layer, edit, prim_path, 'texture:file', prefix_before, prefix_after)
# DomeLight
rename_spec(layer, edit, prim_path, 'texture:format', prefix_before, prefix_after)
def collect_light_prims(prim_path, prim, traverse_variants, light_prim_paths, visited_paths):
if not prim:
return
if prim_path in visited_paths:
return
visited_paths.add(prim_path)
# Manuell fortbewegen, weil wir zwischen Varianten wechseln können, was den stage.Traverse()-Iterator der Bühne ungültig machen würde
for child in prim.GetChildren():
# z. B. /Root/Prim/Child
child_path = prim_path.AppendChild(child.GetName())
if UsdLux.Light(child):
light_prim_paths.add(child_path)
traversed_grandchildren = False
if traverse_variants:
varsets = child.GetVariantSets()
for varset_name in varsets.GetNames():
varset = varsets.GetVariantSet(varset_name)
original_selection = varset.GetVariantSelection() if varset.HasAuthoredVariantSelection() else None
# Auswahlen nur auf der Sitzungsebene umschalten
with Usd.EditContext(prim.GetStage(), prim.GetStage().GetSessionLayer()):
for variant_name in varset.GetVariantNames():
varset.SetVariantSelection(variant_name)
# z. B. /Root/Prim/Child{VarName=Var}
varchild_path = child_path.AppendVariantSelection(varset_name, variant_name)
collect_light_prims(varchild_path, child, traverse_variants, light_prim_paths, visited_paths)
traversed_grandchildren = True
if original_selection:
varset.SetVariantSelection(original_selection)
else:
varset.ClearVariantSelection()
if not traversed_grandchildren:
collect_light_prims(child_path, child, traverse_variants, light_prim_paths, visited_paths)
def update_lights_on_stage(stage_root, traverse_variants=False, reverse=False):
""" Durchläuft die Bühne mit der Stammebene `stage_root` und aktualisiert die Attribute der Licht-Prims zu/von USD 21.05.
Der Ansatz hier umfasst das Durchqueren der zusammengestellten Bühne und das Sammeln von Pfaden zu Prims, die UsdLux-Lichter sind
(Durchblättern der Varianten oder nicht, je nach Input-Argument) und später Durchlaufen aller Ebenen der Bühne
und Umbenennen aller Spezifikationen der Licht-Prim-Attribute in 21.05 (durch Hinzufügen des Präfixes „inputs:“) oder in
das Schema vor 21.05 (durch Entfernen des Präfixes „inputs:“).
Wir durchlaufen zuerst die Kompositionsphase, um sicherzustellen, dass wir ausschließlich UsdLux-Lichtprim-Attribute ändern
und beispielsweise Änderungen am „Radius“-Attribut einer Kugel vermeiden.
"""
stage = Usd.Stage.Open(stage_root, Usd.Stage.LoadAll)
layers_to_traverse = stage.GetUsedLayers(True)
# UsdLux-Prims auf der zusammengestellten Bühne sammeln
light_prim_paths = set()
visited_paths = set()
collect_light_prims(Sdf.Path("/"), stage.GetPseudoRoot(), traverse_variants, light_prim_paths, visited_paths)
print("Gesammelte Licht-Prims:")
for l in light_prim_paths:
print(f"\t{l}")
# Durchläuft alle Ebenen und benennt alle relevanten Attribute von Licht-Prims um
visited_paths = set()
for layer in layers_to_traverse:
# Batch aller Umbenennungsoperationen für diese Ebene in einer einzigen Namensraumbearbeitung
edit = Sdf.BatchNamespaceEdit()
def visit_path(path):
attr_spec = layer.GetAttributeAtPath(path)
if attr_spec:
prim_path = attr_spec.owner.path
# Jede Prim nur einmal besuchen, da wir alle UsdLux-Eigenschaften auf einmal bearbeiten
if prim_path in visited_paths:
return
visited_paths.add(prim_path)
if prim_path in light_prim_paths:
rename_specs(layer, edit, prim_path, reverse)
layer.Traverse("/", visit_path)
if len(edit.edits) == 0:
print(f"Nichts zum Umbenennen auf Ebene '{Ebene.identifier}'")
else:
if layer.CanApply(edit):
layer.Apply(edit)
print(f"Angewendete Änderung an Ebene '{Ebene.identifier}'")
else:
print(f"Die Änderung konnte nicht auf die Ebene „{layer.identifier}“ angewendet werden.'")
# Alle Ebenen Speichern
for layer in layers_to_traverse:
if not layer.anonymous:
layer.Save()
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Aktualisierung der Licht-Prims auf USD 21.05')
parser.add_argument('root_layer_path', type=str,
help='Vollständiger Pfad zur Stamm-Ebene der Bühne, die aktualisiert werden soll, z. B. "C:/MyFolder/MyLevel.usda"')
parser.add_argument('--v', '--traverse_variants', dest='traverse_variants', action='store_true',
help='Gibt an, ob auch jede Variante in jedem Variantensatz durchgeblättert werden soll, wenn nach Licht-Prims gesucht wird')
parser.add_argument('--r', '--reverse', dest='reverse', action='store_true',
help='Optionales Argument, um stattdessen die umgekehrte Änderung vorzunehmen: Die 21.05 UsdLux-Lichtattribute umbenennen, sodass sie dem Schema von vor 21.05 folgen')
args = parser.parse_args()
update_lights_on_stage(args.root_layer_path, args.traverse_variants, args.reverse)
Das Script finden Sie in den USDImporter Quelle unter Engine/Plugins/Importers/USDImporter/Content/Python/usd_unreal/update_lights_to_21_05.py.
Folgen Sie diesen Schritten, um das Script über das Output-Log auszuführen:
-
Öffnen Sie das Output-Log, indem Sie Window > Output-Log auswählen.
-
Klicken Sie auf die Dropdown-Liste Cmd links neben dem Befehlszeilenfeld und wählen Sie Python aus.
-
Geben Sie in das Befehlszeilenfeld Folgendes ein:
"C:\Program Files\Epic Games\UE_4.27\Engine\Plugins\Importers\USDImporter\Content\Python\usd_unreal\update_lights_to_21_05.py" "C:/Pfad/zu/root_layer.usda"Dabei ist „C:/Pfad/zu/root_layer.usda“ der Pfad zu Ihrer USD-Datei.
Das obige Beispiel enthält den Standardpfad zu Ihrer Installation von Unreal Engine. Aktualisieren Sie unbedingt den Pfad, wenn Sie Ihre Version von Unreal Engine nicht am Standardspeicherort installiert haben.
-
Drücken Sie die Eingabetaste, um den Befehl auszuführen.