USD Assets构建指南
概述
本指南的目标是为艺术家和管道提供构建合理且有特色的USD资产的良好起点。它不一定试图提供严格的规范,而是定义一些围绕“最小可行”USD资产构建工具和工作流程的术语和期望。本文件还希望通过提供开始使用USD工作的良好基础来加速对USD资产的一些直觉,而无需预先进行广泛的USD研究或知识。没有什么可以取代体验,但我们希望加速您的体验。
许多工作室、艺术家和作品都希望并需要灵活地构建其资产。提供一些艺术家、技术总监、经理、协调员和开发人员在谈论USD资产时可以使用的核心概念非常重要。对于任何USD管道中的任何资产结构,以下概念和描述应该足够常见。
- Models模型是USD资产。已发布的模型使用零部件或装配体模型类型或基于这些类型的类型。
- Component组件模型是可发布的资产,将其几何形状保留在有效负载后面;它们通常是独立的(除了从全球图书馆引用的material之外)。
- Assembly装配模型是引用零部件或其他装配资产的可发布资产。生成自己的组件的程序集应该负载这些组件并确保正确的模型层次结构。组类型仅用于组织程序集和维护模型层次结构。
- 所有已发布的组件和装配模型都应继承自类基元。
其中一些术语可能在管道和工作流程中具有现有含义。这可能会让艺术家和开发者的讨论和决策变得困难。然而,在不同的工具和工作室中一致地使用这些术语将加快每个参与者的学习曲线。
什么是USD资产?
资产,正如我们在行业中经常使用的术语,是一种以USD为单位的模型。资产一词在不同的工作室/环境/工具中通常意味着不同的事物;例如,几何文件、相关文件的压缩包、动画缓存、纹理贴图和shaders通常都称为资产;甚至USD也使用“资产”作为指向外部非USD文件的属性类型。资产的这些非USD部分可以与USD数据一起存储和版本化,尽管情况可能并非总是如此,但在定义或引用USD模型时,它有助于考虑资产的所有部分。
USD的资产结构通常包含两个考虑因素:原始层次结构和组合/文件组织。
原始层次结构
关于模型层次结构和组合有一些规则,但资产原始层次结构的具体细节是相当开放的。
- 基于组件的类型的祖先必须全部具有基于组或基于组件的类型才能成为正确的模型。
- 诸如material:binding必须以引用基元范围内的基元为目标的关系,否则目标将被清除。
关于组织原语的一些其他建议: - 使用范围来组织基元,以及应避免转换的地方。Xforms 的开销更大,使用 Scopes 可以减少对子 prim 的意外转换。
- 较短的名称可以帮助减少检查原始路径的痛苦,但长度、大小写选择等......取决于个人需求。
- 在 Scope 原语上设置目的更加清晰,因为您不必跟踪各个 gprim 目的。当 Hydra 以USD进行现场工作时,这也更容易消化。
Composition和文件组织
磁盘上USD资产的具体实施细节通常由工作室现有的基础设施驱动。无论是工作室还是个人,在构建资产时都要考虑以下几点:
通常按部门/工作/贡献/内容划分层级
- 有效负载需要外部文件,但除此之外,层分离主要是根据需要组织工作
- 将图层存储为
.usd 的子目录/图层(使用相对路径引用)有助于提高可移植性 组件的各个元素层通常被引用或子层在一起。
- 引用有助于保持意见强度的可预测性,因为每个贡献都是 LIVRPS 中的“R”
- 合理的USD资产的最低限度是 asset.usd 和 Payload.usd
- 强烈建议对“asset.usd”使用“.usd”扩展名,以避免在资产层在ascii 和二进制之间切换时必须重新创作参考路径。将其传递到各个层也可能很有用。
使用子文件夹组织每个资源,尤其是当存在各个图层引用的其他文件或子图层在一起时。
- 即“model”、“lgt”等...
在图层文件夹中,使用文件夹组织USD文件引用的非USD数据会很有帮助
- 即“maps”、“vol”等……
结构的版本控制
USD资产的结构应该灵活,以适应不同的需求或优先事项。利用基元或文件中的元数据,可以编写系统来了解如何灵活地编辑或贡献资产。引用模型可能不需要了解太多,这更多的是帮助艺术家或工具编辑资产。
USD 唯一专门用于帮助版本控制的部分是资产解析器插件。有关编写 AR 插件的其他资源,请参阅更多详细信息。
Component
组件是USD管道中发布的最基本的资产。一个合理的、基本的组件具有以下特征:
- 模型根 prim 上的组件类型
- 有效负载使几何图形可延迟
独立/便携式,不引用外部几何或模型
- 从全球图书馆引用的material是一个常见的例外。
- 从至少一个类 prim 继承,允许将上下文特定的覆盖广播到继承(或“订阅”)同一类的每个资产。
- 根处的变换(“Xformable”)prim,被设置为资源根文件的defaultPrim。
- 组件模型可能有也可能没有 DCC 特定的装备、几何变体等。非USD数据(即装备)通常与资产的核心USD层一起发布,并且通常具有指向这些 sidecar 文件的元数据。
组件内的原语是通过范围来组织的。这有助于避免意外转换不是组件根或子组件的基元。“geo”和“mtl”等较短的名称有助于使调查原始路径变得更容易。然而,总体组织比具体名称更重要。
简单组件
/apple (xform) ← Component Kind
/geo (scope)
/mtl (scope)
/\_\_class\_\_ (class)
/apple (class) ← Inherited by /<component>
Scopes
一个组件至少应该有两个范围:几何形状和material。可能会出于特定目的添加其他范围,但可以合理地假设所有范围都将从这些范围开始。
Geometry
地理范围和图层表示场景中的可见几何图形。任何下游贡献者都将在资产的现有几何结构上叠加他们的工作。
Materials
mtl范围包含组件使用的material和shaders。这些可以在资产中定义,从全局material库引用,或两者的某种组合。请记住,材质层几乎总是对模型的几何形状有意见;至少材质绑定,但诸如新的 UVsets或shaders信号的primvars之类的意见也是可能的。
Purpose
显示目的可用于为 GL 查看器或其他用途策划轻量级表示。如果存在,建议在使用显示目的时在“geo”下命名范围。无需标记每个原语的用途;标记父范围就足够了。不仅每次启动的目的管理都很困难,而且似乎还会导致九头蛇的不稳定。
简单组件 - 有目的范围
/apple (xform) ← Component Kind
/geo (scope)
/proxy (scope) ← Purpose: proxy★
/render (scope) ← Purpose: render★
/mtl (scope)
/\_\_class\_\_ (class)
/apple (class) ← Inherited by /<component>
关于组件场景图结构的其他一些注意事项:
- 在类基元下组织类基元不是必需的,但它可以使基元层次结构中的工作变得更容易
- 材质可以从外部材质库引用,但使用组件定义的材质的任何纹理贴图都应与组件一起存在。
- material可能会以自己的方式变重(原始计数),因此有助于将它们保持在有效载荷后面。如果需要在卸载有效负载的情况下调整material,在这些情况下,资产可以将material移至有效负载之外。
- 变体可用于同一资源的 LOD 或几何体变体。虽然变体集非常灵活,但它有助于定义至少一两个常见/标准变体集(即几何形状和material)。
- 根 prim 上的资产信息元数据可以存储有关资产的更多有用信息
希望基本的组件结构能够为将来的专业组件结构提供良好的基础。
子组件Subcomponents
子组件是存在于组件模型中的 Xformable prims,并且有意以USD形式提供用于转换。建议将子组件放置在枢轴所在的位置,而不是依赖枢轴。这可以避免需要单一类型的 xformOpOrder 约定。
子组件可以嵌套,并且在适用的情况下,每个子组件都可以镜像简单组件的整体结构。为了提高效率,每个子组件内的几何形状和material范围可以被引用到位,并使其可实例化。这对于仅使用刚性变换并严重依赖场景图实例的环境道具可能最有用。
关于嵌套子组件的一个考虑因素:当放大许多实例的较大场景时,如果您的子组件很浅并且没有嵌套,则使用点实例器表示它们的运动可能会更容易,因为每个子组件都可以是原型。
几何子集GeomSubsets
GeomSubsets 非常有用,可以组合网格原点并将其定义为 GeomSubsets。建议使用它们,但是 GeomSubsets 不能像单个网格 prim 那样被激活/隐藏,也不能被转换。如果您有需要调整可见性/激活或调整变换的变体,则需要使用网格prims。
Assembly
装配体是一种已发布的资产,它将其他已发布的零部件或装配体模型聚合在一起。用于对模型进行分组和组织的中间 xform 使用组类型。程序集要么直接实例化对其他模型的引用,要么将这些引用作为原型提供给 PointInstancers。当有效负载弧已经存在于组件模型中时,它们不会提供任何好处;事实上,它们会使装载/卸载阶段变得复杂,并在以USD工作时增加额外的开销。
组装简单
/appleBowl (xform) ← Assembly Kind
/apples (xform) ← Group Kind
/apple1 (reference to apple component)★
/apple2 (reference to apple component)★
/apple3 (reference to apple component)★
/apple4 (reference to apple component)★
/apple5 (reference to apple component)★
/bowl (reference to bowl component)★
/\_\_class\_\_ (class)
/appleBowl (class) ← Inherited by /<assembly>
组件可以覆盖各个组件上的材质,以更好地将各种资产集成在一起。这些案例可以将这些装配级material存储在“mtl”范围中,如下所示:
组装简单 - 使用material
/appleBowl (xform) ← Assembly Kind
/apples (xform) ← Group Kind
/apple1 (reference to apple component)
/apple2 (reference to apple component)
/apple3 (reference to apple component)
/apple4 (reference to apple component)
/apple5 (reference to apple component)
/bowl (reference to bowl component)
/mtl (scope)★
/\_\_class\_\_ (class)
/appleBowl (class) ← Inherited by /<assembly>
虽然装配体通常仅包含对其他模型的引用,但生产通常会提出独特的要求。对于装配体需要生成新几何体的情况,将其发布到其自己的零部件模型并引用回装配体是很尴尬或麻烦的。在这些情况下,新的几何图形应存储在有效负载后面并具有组件类型。
组装简单 - 采用material和新几何形状
/appleBowl (xform) ← Assembly Kind
/apples (xform) ← Group Kind
/apple1 (reference to apple component)
/apple2 (reference to apple component)
/apple3 (reference to apple component)
/apple4 (reference to apple component)
/apple5 (reference to apple component)
/bowl (reference to bowl component)
/geo (scope) ← Component Kind, Payload★
/mtl (scope)
/\_\_class\_\_ (class)
/appleBowl (class) ← Inherited by /<assembly>
组Group
建议不要直接在已发布资产的根上使用种类组。组仅用于帮助装配模型遵守模型层次结构规则。
细节Details
Instancing
实例化资产的最简单方法是在引用到场景时使其可实例化,或者使用 PointInstancer 多次分散模型。在这两种情况下,模型的根基元可用于转换或编辑资源,但当模型仍为实例化时,所有子基元均不可直接编辑。引用的组件通常可在程序集中实例化。PointInstancers 在这两个组件中都很有用,而不仅仅是大型装配体。以下是树的组件示例:
程序集通常将其引用的组件标记为可实例化,尽管这并不总是必需的。这是一个建模注释,但组件模型制作者应该将点实例化器和可实例化基元视为建模者技巧包中的工具。在某些情况下,简单地组合成一个大网格最终可能会更容易/更便宜,但实例化不应仅被视为场景布局。您可能会发现拥有螺栓、叶子或小块食物使用实例很有用。
变体Variants
USD变体集提供了很大的灵活性,这可能会让一开始难以决定要做什么。建议USD资产一开始有两种变体:一种是几何变化,另一种是material。组件可以利用变体集来描述不同的几何形状和/或material组合。组件也可以使用变体来存储不同的布局、材质覆盖等……但为了简单起见,仅通过几何体和/或材质变体集即可获得大量效果。
重要的是模型的变体集可以在资产的根 prim 上访问。即使组件被标记为可实例化,或者负载已卸载,这也允许用户进行变体选择。变体集可能存在于较低的基元中,但通常它们应该可以在模型的根基元上访问以供用户设置。
每个变体单独的文件Separate Files per Variant
变体可以存储在单独的文件中,也可以全部存在于单个层中。将变体保留在一个文件中可以简化文件管理并减少 USD 必须跟踪的层数。另一方面,对于某些工具或管道来说,每个变体的层可能更容易管理。将变体作为层进行管理的能力取决于明确定义的变体集,因为强制执行变体集可以任意更改磁盘上文件的管道将具有挑战性。
除非有理由强制执行其中之一,否则具有打包和解包变体的灵活性将是资产结构可以采用的一种选择。
后备变体选择Fallback Variant Selections
管道功能,允许在没有编写变体选择的情况下自动选择变体。这使得艺术家可以自动根据自己的需求定制不同的作品。
有关更多信息和示例,请参阅Colin Kennedy 的 USD Cookbook 。
除非有理由强制执行其中之一,否则具有打包和解包变体的灵活性将是资产结构可以采用的一种选择。
仅变化模型Variation-Only Models
对于某些管道或作品来说,变体可能是一个不寻常的概念。如果几何/模型变体难以投标/管理等……发布“uber”组件可能会很有用,其变体仅引用单独发布的组件模型。
Payloads
重要的是,将重型几何结构和大量原件保留在有效载荷后面。组件应该有自己的Payloads,而程序集不需要Payloads,因为引用的组件已经有自己的Payloads。一些以镜头为中心的贡献(例如 FX)可能会引入许多新的几何体。这些艺术家和部门需要确保这些新贡献是可卸载的,并且保留模型层次结构,即使它们是在一个镜头中创作的。
嵌套的有效负载会增加性能问题,并增加工具的复杂性。将组件定义为带有有效负载的可发布资产有助于避免嵌套有效负载,并提供一些关于打开卸载场景时可能发生的情况的期望。
Alembic
采用USD的管道往往拥有大量围绕 Alembic 的现有资产和工具。在早期采用期间,您可以直接加载或引用 Alembic 文件,而无需立即将数据转换为 .usdc。与 Alembic 相比,使用 USDC 有优势,但即使某些数据存储为 Alembic,也应该可以构建功能性资产结构。
请参阅Alembic USD 插件了解更多详细信息。
继承和类Inherits and Classes
继承类 prims 是建立USD资产以实现未来灵活性的一种方法。有很多继承方法可用于构建强大的USD资产,但建议模型从一种继承开始。通过继承弧进行编辑的示例可以是变体选择、材质覆盖,甚至新基元。通过继承进行广播覆盖是更改场景图实例的一种方法。
从一个类继承很有用,但对于模型从其他类 prim 继承也可能很有价值。特别是,用于组织资产的组或子组可能是其他类 prim 继承的良好候选者。
专业化的行为与继承类似,但在定义资产时,继承的意见强度通常更适合传播压倒性意见。
绘图模式Draw Mode
USD模型可以使用绘制模式提高视口性能;您甚至可以将绘制模式与卸载的有效负载结合使用。
有 5 个可能的选项:
- origin - 绘制替换的 prim 的模型空间基向量。
- bounds - 绘制替换的 prim 的模型空间边界框。
- cards - 绘制纹理四边形作为替换 prim 的占位符。
- default - 正常绘制USD子树的明确意见。
- inherited - 服从父级。
有关更多详细信息,请参阅UsdGeomModelAPI - 绘制模式。
附加层/贡献者
合并其他部门或学科工作的模型可以遵循material模式并将其层引用到资产的根文件层中。定义对资产的任何独特/新贡献的范围也可能会有所帮助。
例如,对于篝火来说,它具有基于资产的照明和体积效果:
/campfire (xform) ← Component Kind
/fx (scope)
/geo (scope)
/lgt (scope)
/mtl (scope)
/__class__ (class)
/campfire (class) ← Inherited by /<component>
文件和组成
由资产命名并存储在根资产层中的目录也按照资产命名。一些工作室发现他们喜欢根据层是 ascii 还是二进制来使用扩展名,因为它消除了歧义并提供了用户/艺术家的期望文件的“重量”。使用 .usd 的优点,特别是对于根文件来说,是可以在 ascii 和二进制之间进行更改,而不会破坏引用。
基本文件夹
/campfire
campfire.usd
payload.usd
geo.usd
mtl.usd
营火.usd
#usda 1.0
(
defaultPrim = "campfire"
upAxis = "Y"
)
class "__class__"
{
class "campfire"
{
}
}
def Xform "campfire" (
assetInfo = {
asset identifier = @./campfire.usd@
string name = "campfire"
}
prepend inherits = </__class__/campfire>
prepend payload = @./payload.usd@
)
对资产的所有其他层贡献应该是板条箱文件(二进制 .usd 或 .usdc),并以其角色/贡献命名,这些角色/贡献被引用到“有效负载”中。这些额外层的顺序取决于它们的功能以及它们在工作流程时间轴中的位置。一般来说,这些层是相互构建的,以便后来的学科/贡献者可以使用和/或覆盖现有的工作。这就是为什么几何位于底部,然后是material。这就是为什么“照明”通常是为USD资产/镜头做出贡献的最后一层之一。
TODO:
各个层何时应在资产结构中进行子分层和引用?
将相关的非USD文件放置在资产的子目录中可能会有所帮助;每个目录都会描述内容:/campfire
campfire.usd geo.usd
--> /hda <--
--> /maps <--
--> /maya <--mtl.usd payload.usd
任何不进入该“类型”文件的目录的相关文件都可以根据使用这些文件的层按文件夹进行组织。
/campfire
campfire.usd
--> fx.usdc <--
--> /fx <--
geo.usd
--> lgt.usdc <--
--> /lgt <--
/maps
mtl.usd
/vdb
可以将缩略图等其他有用的内容添加到资产中,如下所示:
/campfire
campfire.usd
fx.usd
/fx
geo.usd
lgt.usd
/lgt
/maps
mtl.usd
--> thumbnail.jpg <--
--> README.md <--
/vdb
material
USD 资产必须封装所有几何图形和材质,以便在管道或工作流程中有效引用。材质本身可以从某个全局库中引用,但它们的引用点必须位于资源的根基元下方。
外观开发可能发生在组件或装配体中。为了具体化实例,特别是在较大的装配中,继承的类 prims 可以将材质绑定广播到相关模型。
TODO:
- shaders网络有哪些注意事项?
- 人们如何针对多个渲染委托?仅限 MaterialX?
人群和 UsdSkel
TODO:
- 围绕人群和USD资产结构有哪些考虑?
- UsdSkel 如何影响结构化资产?BG角色的结构与“英雄”模型不同吗?
- 是否有关于 Value Clips 的考虑因素?
物理或其他模式/目的
对于某些用例,可能需要在模型中描述物理现象。如果刚体模拟是唯一的要求,则可以为实例提供物理驱动的交互。
如果物理需求不需要散布模型的 gprim,则为物理基元设置专用范围可能会很有用。
游戏
本文档的大部分内容旨在构建动画和视觉特效的USD资产。本节将概述实时需求需要不同方法的地方。
TODO:
- 双向性
- 同步编辑
LOD细节层次
- 游戏 LOD 通常具有基于摄像机的组件;在没有某种原始适配器的情况下,以USD令人满意地实现这一点可能具有挑战性,因为变体无法动画化。
- 是否有任何游戏引擎按原样使用USD并与之交互,或者它们都转换为其内部格式?
相关工作流程和注意事项
专栏
- Two cases: archival and kitbashing
USD and Digital Backlots - Eliot Smyrl
- ASWF - WGUSD Presentation
- Siggraph 2021 Talk
- Digital Backlots and Libraries are Hard - Davide Pesare
评论和变体
- 是否会创建特定于评论的变体?
自定义模式
- 什么时候需要它们?具体 vs ApiSchema?
命名
- Prims 通常按照 ProperCase 约定命名,并且可能带有数字后缀。示例:
World
或RedMaterial_1
- 属性和关系通常按照驼峰命名法命名。例子:
curveWidth
- 围绕不同惯例的讨论/建议(由工作室和艺术家)
- 公司/工作室/域特定属性的命名空间
盲数据
- 处理未知模式或未定义模式
- 存储在本地格式和USD格式之间转换的 DCC 之间的交换过程中不会丢失它们
- 也许 DCC 特定模式需要考虑一些事情
- 例如,Houdini 有一些 ApiSchema 在 Solaris 之外没有任何功能。因此,除非它们实际上从 USD 文件中删除,否则数据应该持续存在,但保持休眠状态,直到带回 Houdini。
- 即使未检测到插件,架构也应以USD形式保留,因此这一问题很大程度上与USD和 DCC 原生格式之间的转换有关
- 如果在模式不存在时管道可能希望具有替代行为,则还可以定义后备 Prim 类型。
结构示例
资产的表示,可能在实际制作中使用。不一定会遵循本文档的所有建议,但通常会实施最重要的建议,并且研究起来很有用且有趣。
AnimalLogic 的 ALab
蓝天工作室
- Apples (usd-interest)
OpenUSD
- Kitchen Set
- City Set
- UsdSkel Examples