本文翻译自《Siggraph 2019 USD Introduction and Overview》
这里是一个Pixar公司在生产流程中使用的软件的粗略总览,给大家一个总体的认知:这些技术应用在哪个环节或者软件中。
当你看到Hydra的时候,你可以认为OpenSubdiv也在这里使用过是少一次。当然所有的蓝色箭头意味着:USD作为中间文件在流程中进行流转。
这里展示的是1个单位大小的立方体,用来展示USD中的一些概念
这个文件是一个.usda文件。这里要说明的是:这里看到的是一个伴随着USD发布的文件格式(.usda文件格式是一种ASCII,可读的文件格式)。而我们说的USD并不是一个文件格式
这里“def”是USD的说明符(specifier):用来告诉USD,我们这里定义了一个基础容器(Prim),这里prim是USD中的最重要的容器,是primary的缩写。它可以包含其他prim,创建命名空间层级结构。后面我们能够看到更多的说明符(specifier),例如:“over”和“class”。
这里的“Cube”指代的是prim的类型。这个类型是通过模式(schema)来进行描述的。后面有更多有关模式(schema)的介绍。
“box”就是这个“Cube”的名字。
下一行中,我们定义了这个立方体的大小。我们定义了一个“属性(attribute)”。其中一个“属性(attribute)”中包括:类型,名称,数值。
总结来说:这个usd文件中定义了一个prim并且声明了一个“属性(attribute)”的值的“观点(opinion)”
下面,我们用一个更加通用的网格物体来说明usd。通过这个新的文件,我们可以展示更多的有关usd的概念。下面你会看到usd支持的类型,包括数组类型。
- 顶点和索引数组
- 颜色数组
- 我们将其称之为一个“box.usda”文件
- 它一般也被称之为层(layer),就像Photoshop里面的层一样。
我们这里用:world文件中的2个引用(reference),来展示合成(composition arcs)。这是USD的核心概念,后面会有更详细的介绍。
现在我们有2个box了。但是这个两个box重叠到了一起。所以我们需要移动一下他们。
通过上面绿色的文本,我们移动了2个box。绿色的文本代表了:对于2个物体该移动多少的观点(opinion)。但是目前他们都是灰色的——我们想修改下它们的颜色。
这里,绿色的文本代表着该文件的观点(opinion):覆盖被引用文件box中的颜色属性。
当我们将文件中的所有引用(reference),合成(composition arcs),覆写(override),全部解析之后,我们就得到了一个舞台(stage)。这个解析过程通过USD的接口来完成。
现在我们可以尝试回答问题:什么是USD?
- USD是一个用来合成场景和解析场景中数值的运行时引擎;
- 它可以用来在不同应用之间(maya,houdini等)交换和传输数据,也可以直接用做3D场景文件。
- 它的特性:构建复杂的场景;让艺术家或者工作室之间的合作变得简单。
我们为什么选择USD?
- USD是Pixar公司多年技术迭代的结果,它可以帮助你学习到我们的经验和错误。
- USD的直接继承者就是Pixar公司大名鼎鼎的Presto软件:pixar内部的绑定,动画,模拟软件。所以USD构建在很多有天赋的从业人员,几十年的经验上。
- 这也是为什么USD中有很多很复杂的概念:这么多的概念,是为了生产中更好的解决实际问题,希望在后面的学习中,大家也能理解这些概念为什么是这样的。
- USD设计的主要目的是为了生产:电影级质量的数字内容,并且有着很好的拓展性。
下面我们介绍一下:构成USD文件的元素
首先我们有一个基础容器(Prim),比如说一个box。它通常是有类型的。上面的文件中Cube就是box的类型。
下面的一个元素是:资产(property)。之前也介绍过。
- 资产包括属性(attribute),比如说box的大小。
- 然后是:关系(relationship),用来在基础容器(Prim)和资产(property)之间建立连接
然后是元数据(metadata):是一种依附在prim,property,甚至是layer上面的额外信息。黄颜色的方框展示的是颜色的插值方式。
层(Layer)是基础容器(Prim)和资产(property)的容器,其中的元素要按照层级结构组织好。层(Layer)就是USD合成引擎所用来合成和引用的对象。
合成(Composition arcs):是USD提供的一种合成场景的方式,它十分的强大,并且能够帮你解锁一些很酷的工作流程。
最后,舞台(Stage)就是把所有层,从根层向下合成的结果。舞台的主要作用是查询场景中的信息和遍历场景。它给到你的是合成好的基础容器(prim),和相应的位置,命名空间以及属性(attribute)的最终值等等。
另一件值得注意的是:基础容器(Prim)和资产(property)是有命名空间(namespace)的对象。
- 在USD中,他们是通过“SdfPath”来实现的。这里展示了2个例子。第一个xformOrder属性的路径,第二个展示的是box2的路径。
- Sdf是USD和Hydra API的主要组件(代码层面上)。
另外一个重点内容是:模式(Schema),它可以理解为:模式是一组属性attribute的集合,这些属性赋予了基础容器Prim含义。
- USD并不知道基础容器(Prim)和资产(property)代表着什么,他需要模式(Schema)来赋予其含义。例如:如果一个prim表示一个网格物体或者立方体,那么它的模式将定义里面到底用了哪些属性。
- 有一些范围不在模式(Schema)的讨论范围内,比如说绑定。这是因为USD要解决的是文件交换的问题,而绑定并不适合在2个软件之间进行交换。但对于USD的技术角度来说,其实是可以自己创建一个rigging的schema的。
这里就是目前USD支持的schema,官方偶尔也会添加新的扩展,比如说最近给骨骼动画模式中添加了blend shape的支持。
这里是这些schema实现上对应的库,我们引用的时候采用库的名字,例如UsdGeom。
USD生态有着非常好的扩展性。我们的库中给了丰富的插件接口用于实现相应组件的插件。
文件格式插件:使得USD可以识别引用更多的文件类型。例如让USD支持abc,vdb文件的引用就是通过文件格式插件来完成的。
另一个扩展USD的方式是:对资产的路径解析这里做文章。例如支持的路径的形式不是一个绝对路径,而是一个shotgun tank路径等等。
它的主要作用是:把你的pipeline中的资产路径解析成一个可以识别并且打开的路径。如图所示。
之前我们讨论过模式(schema),其实我们以可以写自己的模式。
例如,有些工作室想要头发的模式(Hair schema)。这部分后面Matt的文章中会有更详细的介绍。
下面就是跳转到Hydra渲染框架中了。后面其他文章中将会对Hydra进行详细的介绍。
但是Hydra的设计架构使得我们可以写一个插件来解析你自己的场景文件。这个叫做场景代理(Scene Delegate)
也可以写一个插件支持自己的渲染器。这个叫做渲染代理(Render Delegate)。
最后,你可以写一个USD Imageing插件来预览你自定义的模式。
这就是USD,高度的扩展性和定制性。
这里是USD官方提供的网址。很多有用的信息可以在上面查到。比如说这个usd-interest的google论坛,上面的提问很多。
从GitHub上面拿到代码之后,你会看到源码中如下的目录结构。下面我们介绍下每个含义。
- 系统的最底层在base目录中。这里包含的库有:基础方程工具库,插件系统,Vt(实现了USD中使用的基础类型)。
- 下一个组件是:usd,它包括usd的核心代码。包括基础容器和资产的实现,合成引擎,和一些核心模式的实现。这里就是实现file format插件和自定义模式的位置
- Imaging就是Hydra渲染框架的核心位置。这里就是场景代理和渲染代理插件的位置,包括usd中内置的高性能视口渲染器Storm。
- 在最上层就是UsdImaging,它主要包括Hydra USD的场景代理。比如说usdview就在这一层,usdview就是用来预览usd文件的一个应用程序。包括之前说的prim adapter插件中使用的API也是封装在这一层的。
最后,我们看一下:例如“displayColor”这个变量如何在USD库中被一步一步的解析并展示出来的。假设我们的渲染系统需要这个displaceColor。
- 首先假设这个变量存储与USD的二进制文件中(.usdc),那么usdc文件的插件将去抓取这个变量的数值。
- 这个值将被打包在VtValue中。请注意:usdc文件非常高效,基本上是零拷贝,这里用到的所有的数组也都是写时拷贝。
- 下一步,sdf就是那个能够知道所有层(Layer)和基础容器(Prim)以及资产(Property)的库文件。
- 所有的层将通过pcp进行合成,pcp就是里面的合成引擎,并最终输出解析后的值。
- usd是里面的最低级的API,它提供UsdStage,pirm和property的API。
- usdGeom是一个模式库,提供了具体资产(property)的意义。
- 下一步是,USD Hydra的场景代理,这个是通过usdImaging来访问的。
- usdImaging是通过Hydra来进行访问的,Hydra的代码在hd中。
- 最后一步是:渲染代理,我们这个例子中用的是GL渲染器:Storm Renderer。这部分主要在hdSt。
- 之后,这个红色的像素就被渲染了出来。
这上面的过程看上去很复杂,但是其实USD设计考虑了有关性能包括GPU内存,你看到了,这里其实只有一次内存拷贝。设计中有关每个模块的职责和关注点也被充分解耦。