Les films, les jeux et autres productions graphiques en 3D génèrent, stockent et transmettent souvent une grande quantité de données. Ces données peuvent provenir de divers logiciels (tels que l'Unreal Engine, Maya, Houdini ou Blender) du pipeline graphique, chacun possédant sa propre forme exclusive de description de scène.
Le format d'échange Universal Scene Description (USD) est un format open source développé par Pixar pour répondre au besoin d'échanger et d'augmenter de manière robuste et évolutive des scènes 3D arbitraires qui peuvent être composées de nombreuses ressources élémentaires. USD fournit non seulement une riche trousse à outils pour la lecture, l'écriture, la modification et la prévisualisation rapide de la géométrie et de l'ombrage 3D, mais il permet également l'échange de ressources élémentaires (par exemple, des modèles) ou d'animations.
Contrairement à d'autres paquets d'échange, USD permet également l'assemblage et l'organisation de n'importe quel nombre de ressources dans des décors, des scènes et des prises de vue virtuels. Vous pouvez ensuite les transmettre d'une application à une autre et les modifier de manière non destructive (en tant que remplacements), avec une API unique et cohérente, dans un seul graphique de scène.
Pourquoi utiliser USD ?
USD fournit un langage commun pour déplacer des quantités importantes de données entre plusieurs applications 3D. Cela offre une flexibilité lors de la prise de décisions concernant votre pipeline graphique et facilite la collaboration entre plusieurs graphistes 3D (animateurs, graphistes d'éclairage ou d'ombrage, modélisateurs, graphistes d'effets visuels, etc.) à l'aide de méthodes itératives et non destructives.
Prise en charge d'USD dans l'Unreal Engine
L'Unreal Engine fournit une prise en charge d'USD via le panneau Scène USD et les flux de travail Python bidirectionnels.
La fenêtre de scène USD. Cliquez sur l'image pour l'afficher en taille réelle.
Plutôt que de convertir les données USD en ressources Unreal Engine natives telles que des maillages statiques et des matériaux, le flux de travail de scène USD fonctionne de manière native avec vos données USD. Cela accélère l'intégration de vos données USD à l'Unreal Engine, vous donne une vue plus claire de la structure initiale de votre contenu USD et gère les mises à jour en direct lorsque vous apportez des modifications au fichier USD source sur le disque.
La scène USD fournit les fonctionnalités suivantes :
- Représentation des données 3D sous forme de "prims" : maillages statiques, maillages squelettiques, HISM, matériaux, lumières, caméras, variantes, animation et formes de mélange.
- Modification non destructive des attributs.
- Graphique de scène USD et visualisation de la hiérarchie.
- Chargement et déchargement de contenu à l'aide de charges utiles.
- Prise en charge des textures avec les surfaces d'aperçu USD.
- Prise en charge des matériaux avec PreviewSurface et DisplayColor.
- Prise en charge des plug-ins USD tels qu'Alembic et Custom path Resolver.
- Fonctionnalités USD prises en charge à l'exécution. Pour plus d'informations, consultez USD Runtime Support.
- Charge les formats
.usd,.usda,.usdcet.usdz.
Pour plus d'informations générales sur Universal Scene Description, consultez Introduction to USD de Pixar.
Pour plus d'informations sur l'utilisation du flux de travail Python, consultez la section Scripts Python.
Actions prises en charge
Importation dans l'Unreal Engine
Le contenu affiché sur la scène USD (maillages statiques, maillages squelettiques, lumières, végétation et paysages) peut être importé dans l'Unreal Engine à l'aide des méthodes suivantes :
- Utilisation de Fichier > Importer dans le niveau. Ce processus importera à la fois les ressources (maillage statique, maillage squelettique, matériaux, textures, etc.) et les acteurs.
- En utilisant le bouton Ajouter/Importer dans le navigateur de contenu. Ce processus importera uniquement les ressources.
- En glissant-déposant le fichier dans le navigateur de contenu. Ce processus importera uniquement les ressources.
- En utilisant l'option Action > Importer dans l'éditeur de scène USD. Ce processus importera à la fois les ressources et les acteurs. Une fois le processus d'importation terminé, les ressources de la scène USD sont remplacées par de nouveaux acteurs du navigateur de contenu.
Création et modification d'animation
Les animations stockées dans un fichier USD sont accessibles à l'aide de la séquence de niveau associée trouvée dans le panneau Propriétés de l'USDStageActor.
Ouvrez la séquence de niveau en sélectionnant la scène de niveau USD et en double-cliquant sur la séquence dans le panneau Propriétés. Cliquez sur l'image pour l'afficher à taille réelle.
Les animations USD xform sont affichées sous forme de pistes Transformation dans la séquence de niveau. D'autres formes d'animation telles que les floats, les booléens et les os squelettiques sont affichés via la piste Temps. Les données d'animation USD dans l'image ci-dessus sont représentées sous la forme d'une paire clé/valeur à chaque timecode pendant la durée de l'animation.
Via la séquence de niveau générée par la scène USD, vous pouvez lier à un acteur généré sur la scène USD et ajouter une animation supplémentaire via une piste Transformation.
Prise en charge d'USD à l'exécution
L'Unreal Engine prend en charge le chargement de fichiers USD à l'exécution en appelant le nœud Set Root Layer Blueprint sur un acteur de scène USD dans le niveau.
Le nœud Set Root Layer. Cliquez sur l'image pour l'afficher en taille réelle.
Ce nœud crée les ressources requises et génère des acteurs et des composants dans le niveau de la même manière que le mode de gestion du processus dans l'éditeur. Parmi les fonctions Blueprint supplémentaires permettant de contrôler diverses propriétés d'acteur de scène USD figurent :
| Fonction Blueprint | Description |
|---|---|
| Get Generated Assets | Obtient les ressources générées pour un prim dans un chemin de prim donné et les place dans une matrice. Utilise un acteur de scène USD et un chemin de prim comme entrées. |
| Get Generated Components | Obtient les composants générés pour un prim dans un chemin de prim donné. Utilise un acteur de scène USD et un chemin de prim comme entrées. |
| Get Source Prim Path | Obtient le chemin de prim pour un objet donné sur la scène USD. Utilise un acteur de scène USD et une référence d'objet comme entrées. |
| Get Time | Obtient l'horodatage actuel dans l'acteur de scène USD cible. Prend un acteur de scène USD comme cible. |
| Set Initial Load Set | Définit la charge utile initiale à charger. Utilise un acteur de scène USD comme entrée et fournit les options suivantes.
|
| Set Purpose to Load | Définit la finalité initiale à charger. Utilise un acteur de scène USD et un entier comme entrée.
|
| Set Render Context | Définit le contexte de rendu d'une scène USD. Prend un acteur de scène USD comme cible et une référence à un contexte de rendu comme entrée. |
| Set Time | Définit l'horodatage actuel d'une scène USD. Prend un acteur de scène USD comme cible et une valeur float comme entrée. |
Pour plus d'informations sur l'attribut Purpose (finalité) et d'autres termes USD, consultez le Glossaire USD de Pixar.
Ce processus vous permet de créer des applications capables de charger et d'afficher le contenu d'un fichier USD à l'exécution.
Pour activer l'importateur USD à l'exécution, ajoutez la ligne suivante à votre Project.Target.cs fichier situé dans le dossier UE_(version)\Engine\Source, où Project est le nom de votre projet :
GlobalDefinitions.Add("FORCE_ANSI_ALLOCATOR=1");
Par exemple :
public class YourProjectTarget : TargetRules
{
public YourProjectTarget( TargetInfo Target) : base(Target)
{
Type = TargetType.Game;
DefaultBuildSettings = BuildSettingsVersion.V2;
ExtraModuleNames.AddRange( new string[] { "YourProject" } );
GlobalDefinitions.Add("FORCE_ANSI_ALLOCATOR=1");
}
}
Prise en charge de Nvidia MDL
L'Unreal Engine prend en charge les matériaux de surface MDL à l'aide du schéma Nvidia MDL USD. Pour plus d'informations sur Nvidia MDL, consultez l'article USD Shader Attributes de Nvidia.
Prise en charge de la modification multi-utilisateur
La modification multi-utilisateur est prise en charge pour de nombreuses opérations de scène USD, notamment les suivantes :
- Ajout et suppression de prims.
- Renommage de prims.
- Modification des attributs de prim.
- Bascule de visibilité.
- Ouverture, fermeture ou modification de la scène en cours.
Pour activer la prise en charge multi-utilisateur pour votre projet USD, activez le plug-in USD Multi-User synchronization. Pour en savoir plus sur la façon de travailler avec les plug-ins, consultez Working with Plugins
La modification multi-utilisateur USD synchronise la propriété Couche racine de la scène USD pour chaque client, garantissant que tous les utilisateurs disposent des mêmes fichiers USD. Cela s'effectue en demandant à chaque client d'ouvrir la même scène USD localement, en générant des ressources et des composants sur son propre système, puis en synchronisant uniquement les opérations effectuées sur ces ressources.
Lors d'une session de modification multi-utilisateur, il est important que tous les utilisateurs accèdent aux fichiers USD via le même chemin de fichier. Pour garantir que chaque client puisse accéder aux mêmes fichiers, nous recommandons que les fichiers USD cibles soient stockés dans le dossier du projet et gérés à l'aide du contrôle de source.
Pour plus d'informations sur la modification multi-utilisateur dans l'Unreal Engine, consultez Multi-User Editing in Unreal Engine.
Il n'est pas possible d'annuler la suppression de prim pendant une session multi-utilisateur.
Activer le plug-in USD Import
Pour commencer à travailler avec un fichier USD dans l'Unreal Editor, vous devrez activer le plug-in USD Importer dans le menu Plug-ins. Pour en savoir plus sur la façon de travailler avec les plug-ins, consultez Working with Plugins
Une fois l'éditeur redémarré, vous verrez une nouvelle option Scène USD répertoriée sous le menu Fenêtre > Production virtuelle dans l'éditeur de niveau.
Le panneau Placer des acteurs répertorie un nouvel acteur de scène USD à ajouter à votre niveau.
Nouveaux acteurs USD disponibles dans le panneau Placer des acteurs.
Utiliser USD dans l'Unreal Engine
Travailler avec du contenu USD dans l'Unreal Engine commence par l'éditeur de scène USD et l'acteur de scène USD.
Le panneau Scène USD.
| Numéro | Description |
|---|---|
| 1 | Hiérarchie |
| 2 | Propriétés |
| 3 | Couches |
Flux de travail de scène USD
Un acteur de scène USD agit comme un conteneur pour le contenu d'un fichier USD chargé et fournit un soutien aux données dans votre niveau. Les objets de scène 3D chargés à partir du fichier USD et visibles dans le hublot sont entièrement compatibles avec la plupart des autres fonctionnalités Unreal Engine, et vous pouvez les traiter exactement comme les autres acteurs. Vous pouvez ajouter des prims qui référencent le contenu trouvé dans d'autres fichiers USD, y compris des maillages squelettiques animés.
L'enregistrement des modifications apportées à votre scène USD à l'aide du menu Fichier > Enregistrer dans l'éditeur de scène USD réécrit ces modifications dans votre fichier USD.
Pour plus d'informations sur l'utilisation de la scène USD, consultez Démarrage rapide de l'éditeur de scène USD.
L'Unreal Engine ne crée pas automatiquement de textures de lumière pour les ressources chargées sur la scène USD à l'ouverture d'un fichier USD. Cela peut donner lieu à une scène complètement noire lorsque l'éclairage statique est créé.
Scripts Python
Les scripts Python avec USD offrent un moyen flexible d'effectuer une variété d'actions telles que des opérations par lots et des modifications de scènes qui peuvent s'avérer difficiles ou longues à réaliser via l'interface utilisateur. Des opérations telles que le masquage ou la modification des attributs d'un grand nombre de prims peuvent être automatisées rapidement à l'aide d'un script Python flexible lancé à partir du panneau Journal de sortie.
Avant d'utiliser Python, vous devez activer le plug-in Python Editor Script. Pour en savoir plus sur les plug-ins, consultez Working with Plugins.
Vous pouvez ensuite utiliser le journal de sortie situé au bas de l'éditeur de niveau pour exécuter des scripts Python. Vous pouvez également ouvrir le journal de sortie en tant que panneau distinct à partir de Fenêtre > Journal de sortie.
Cliquez sur l'image pour l'afficher à taille réelle.
Pour plus d'informations sur l'utilisation de scripts Python avec l'Unreal Engine, consultez Scripting the Unreal Editor Using Python.
Cas d'utilisation d'un script Python
Lorsque la version USD SDK fournie avec l'Unreal Engine a été mise à niveau vers la version 21.05, la mise à jour a renommé plusieurs attributs dans les schémas de lumière USDLux. Pour résoudre le problème, l'Unreal Engine inclut un script Python qui renomme les attributs de prim USDLux selon la convention de nommage de la version 21.05.
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)
# Nous devons vérifier à chaque fois, car l'ajout d'une modification d'espace de noms qui ne peut pas s'appliquer annulera simplement l'ensemble du lot
if layer.GetAttributeAtPath(path_before):
print(f"Trying to rename '{path_before}' to '{path_after}'")
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:'
# Lumière
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
# Remarque : treatAsPoint ne devant pas avoir le préfixe "inputs", nous l'ignorons
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)
# Traverser manuellement, car nous pouvons basculer entre les variantes, ce qui invaliderait l'itérateur stage.Traverse()
for child in prim.GetChildren():
# par exemple, /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
# Changer les sélections uniquement sur la couche de session
with Usd.EditContext(prim.GetStage(), prim.GetStage().GetSessionLayer()):
for variant_name in varset.GetVariantNames():
varset.SetVariantSelection(variant_name)
# par exemple, /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):
""" Traverses the stage with root layer `stage_root`, updating attributes of light prims to/from USD 21.05.
L'approche ici consiste à traverser la scène composée et à collecter des chemins vers des prims qui sont des lumières UsdLux
(en parcourant les variantes ou non en fonction de l'argument d'entrée), et plus tard à traverser toutes les couches
de la scène et à renommer toutes les spécifications d'attributs de prim de lumière en version 21.05 (en ajoutant le préfixe "inputs:") ou selon
le schéma d'avant-version 21.05 (en supprimant le préfixe 'inputs:').
Nous traversons d'abord la scène composée pour nous assurer que nous modifions exclusivement les attributs de prim de lumière UsdLux,
en évitant de modifier l'attribut "radius" d'une sphère, par exemple.
"""
stage = Usd.Stage.Open(stage_root, Usd.Stage.LoadAll)
layers_to_traverse = stage.GetUsedLayers(True)
# Collecter les prims UsdLux sur la scène composée
light_prim_paths = set()
visited_paths = set()
collect_light_prims(Sdf.Path("/"), stage.GetPseudoRoot(), traverse_variants, light_prim_paths, visited_paths)
print("Collected light prims:")
for l in light_prim_paths:
print(f"\t{l}")
# Traverser toutes les couches et renommer tous les attributs pertinents des prims de lumière
visited_paths = set()
for layer in layers_to_traverse:
# Regrouper toutes les opérations de renommage pour cette couche dans une seule modification d'espace de noms
edit = Sdf.BatchNamespaceEdit()
def visit_path(path):
attr_spec = layer.GetAttributeAtPath(path)
if attr_spec:
prim_path = attr_spec.owner.path
# Ne visitez chaque prim qu'une seule fois, car nous gérerons toutes les propriétés UsdLux en une seule fois
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"Nothing to rename on layer '{layer.identifier}'")
else:
if layer.CanApply(edit):
layer.Apply(edit)
print(f"Applied change to layer '{layer.identifier}'")
else:
print(f"Failed to apply change to layer '{layer.identifier}'")
# Enregistrer toutes les couches
for layer in layers_to_traverse:
if not layer.anonymous:
layer.Save()
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Update light prims to USD 21.05')
parser.add_argument('root_layer_path', type=str,
help='Full path to the root layer of the stage to update e.g. "C:/MyFolder/MyLevel.usda"')
parser.add_argument('--v', '--traverse_variants', dest='traverse_variants', action='store_true',
help='Whether to also flip through every variant in every variant set encountered when looking for light prims')
parser.add_argument('--r', '--reverse', dest='reverse', action='store_true',
help='Optional argument to do the reverse change instead: Rename 21.05 UsdLux light attributes so that they follow the schema from before 21.05')
args = parser.parse_args()
update_lights_on_stage(args.root_layer_path, args.traverse_variants, args.reverse)
Le script se trouve dans les fichiers sources USDImporter situés dans Engine/Plugins/Importers/USDImporter/Content/Python/usd_unreal/update_lights_to_21_05.py.
Suivez ces étapes pour exécuter le script à partir du journal de sortie :
-
Ouvrez le journal de sortie en sélectionnant Fenêtre > Journal de sortie.
-
Cliquez sur le menu déroulant Cmd à gauche du champ de ligne de commande et sélectionnez Python.
-
Entrez ce qui suit dans le champ de ligne de commande :
"C:\Program Files\Epic Games\UE_4.27\Engine\Plugins\Importers\USDImporter\Content\Python\usd_unreal\update_lights_to_21_05.py" "C:/path/to/root_layer.usda""C:/path/to/root_layer.usda"étant le chemin de votre fichier USD.L'exemple ci-dessus contient le chemin par défaut vers l'installation de l'Unreal Engine. Assurez-vous de mettre à jour le chemin si vous n'avez pas installé votre version de l'Unreal Engine à l'emplacement par défaut.
-
Appuyez sur Entrée pour exécuter la commande.