最近做了些AR/VR的1内容,学了不少三维数据的结构,本节介绍一下USD,由于相关内容相对比较多,一次性的把近期的学习都总结在这里,所以文章相对比较长,本来想分开弄,但他们的关联性比较强,就合并了。并且不会涉及太多的开发相关内容,仅仅是简单的介绍。
简介
现在关于USD的介绍还是比较多了,热度一直未减,但目前据我所知,由于内容太多,文章和文档比较分散,并且官方的专业术语表里面有上百个,每一个的解释相对也是较难以理解的,所以,简单总结相对能比较快速和集中的了解USD的框架以及他的运用。
USD是什么
- 关于usd的介绍,
首先需要了解他是什么,Pixar对他的描述是,在电影和游戏的生产流程中通常会生成、存储和传输大量的三维数据,我们称之为“场景描述”Universal Scene Description (USD)。 - 因为在CG的生产流程中的每一个模块(模型、材质、动画、灯光、特效、渲染)都有自己特定的场景描述形式,来满足模块的特定需求和工作流程,并且任何其他模块都无法读取或编辑。因此它并不会让你做出更好的视觉效果,但能让你在各个DCC之间或者在整个制作团队各个工作流传递数据变得更有效率。
- 总的来说,USD是用来合成场景和解析场景中的数值而运行的引擎,因此,它在不同DCC之间交换和传输数据,也可以直接用做3D场景文件。
USD的性质
- 上述提到的USD的简单介绍:
那么就很容易的知道他的主要特点是能够构建复杂的场景,让艺术家或者各个工作流之间的合作在效率上会有质的提升。那么我们可以了解一下他的基本特性。 - 我们已经知道了USD是一个场景描述文件,从另一个方面来看,CG流程生产里一种协作方案,数据的传递和处理系统。并且用途非常广泛,用于影视,游戏等领域,比如Nvidia,Apple,各个游戏引擎,影视DCC软件都在使用。
USD的概念
这里主要是用一些实例来展示USD的概念。
USD场景描述格式具有.usda人类可读的等效纯文本()。这是一个非常简单的.usda示例
- 表示一个单位的立方体:建立一个.usda的文件,
1 | *#usda 1.0* |
上面的“def
”是用来告诉USD,我们这里定义了一个基础容器(Prim
),这里prim
是USD中的最重要的容器,后续后详细说明。Cube
指代的是prim的类型,这个类型是通过模式(schema
)来进行描述的
后面部分的“box
”就是这个“Cube
”的名字。
在{ }中的定义了立方体的大小,
总结来说:这个usd文件中定义了一个prim并且声明了一个“属性(attribute)”的值的“观点(opinion
)”
它也是一种缓存格式,至于这个格式相对于abc优势,也是比较多的,目前我对USD的了解还不太多,只能以后在看了。
USD的文件后缀
要注意的一点是通常我们说的USD其实不是一个文件的格式,他的主要文件格式如下。
主要是.usd/.usda/.usdc的后缀:
.usd
,这个格式是最通用而最常见的后缀,他又两种储存方式,一种是可读性较强的ASCII
文件,一种是压缩优化过的二进制文件。.usda
,这个格式表示usd文件是可读性较强的ASCII
编码文件.usdc
,这个后缀表示该usd文件被压缩优化过的二进制文件,不具可读性.usdz
,这个是苹果公司基于usd自己研发的格式,优化了流传输等方面的功能,
注意:如果需要打开二进制的usdc文件,想要读取这些二进制的内容,可以借助官方给我们提供的命令行小工具即可:
usdcat命令行用于转换格式
构成USD文件的元素
上述说明了USD的基本概念,下面或详细说明USD的核心元素。
- Primitives (prims)节点
prims是USD的基本“容器”,”Primitive”通常缩写为”prim”。
比如说一个box
。它通常是有类型的。上面的文件中Cube
就是box
的类型。
注意:这个不是Houdini里面说的Primitive不是一个概念,可以把当当成最基本的一个容器,并且,prim是有名称的,可以支持多层级,每个层级包含承载很多类型,比如:灯光,相机,材质等这些都是个prim。访问对应的名称空间就能访问对应的节点。
- Property资产
Property包含了attributes属性, relationships关系。并且是有属性名,属性类型和对应的属性数据。
1.Attributes属性
是用来描述prim的类型值,例如:box的大小
2.Relationships关系
用来在基础容器(Prim)和资产(property)之间建立连接,例如,指定对一个网格对象的shader要使用的材质. - Metadata元素据
它是一种依附在prim,property,甚至是layer上面的额外信息,例如,如果为mesh指定颜色primvar ,则可添加interpolation元数据,该元数据指定渲染器应如何在这些点的颜色之间混合。 - Layers层
一个.usd文件一般会被称为层。就像Photoshop里面的层一样,并且一个层可以表示场景的一个片段,例如,道具,角色,装备等。然后这些Layer最终会被合成一个完整的场景,一个Layer可以有Sublayer,然后构成LayerStack,处于LayerStack上方的节点会覆盖下方的节点。 - Composition arcs合成操作符
是USD提供的一种合成场景的方式,它十分的强大,并且能够帮你解锁一些很酷的工作流程。例如,场景图层可能会reference进包含道具,灯光等图层。这些图层可能reference自己的子层,依此类推。在将各层复合在一起,合并每层中的prims。较高层中的属性将覆盖下面的属性。 - Stage场次
这个可以理解成场景,每个usd文件里都包含一个stage。Stage就是把所有层,从根层向下合成的结果。主要作用是查询场景中的信息和遍历场景。它给到你的是合成好的基础容器(prim),和相应的位置,命名空间以及属性(attribute)的最终值等等。
注意,stage只是结果的名称。“stage文件”和“layer文件”之间没有区别,如果将.usd文件加载为”top-level”文件,它将创建一个新的stage。在另一种情况下,你可以将同一文件作为不同stage的图层引用。 - 合成Composition
是通过写在usd文件中的一系列的操作符号(operators (or “arcs”))来完成的。在运行时,usd的合成引擎运算这些操作符,并最终将合成的场景呈现,每个USD文件都包含完整的“场景”。
USD文件可以将其它USD文件的内容导入为图层,用于将多层合成、叠加到顶层文件创建的整个场景(stage)中的软件。合成允许你从非常小的资产开始构建资产,然后小的资产组合成中等大小的资产,之后中的大小的资产组合成完整的场景。它允许你进行非破坏性的复写(non-destructive override),这样,你就可以在不破坏当前资产的情况下,修改资产的外观,属性等等,
合成器里面有几个合成机制,完整的机制是 Local(最强) - Inherite - Variant - Reference - Payload - Specialists(最弱) - Sublayers, references
USD具有两种“导入”另一个USD的内容的方法:sublayering 是将导入文件的树覆盖在当前树上,而reference是将导入树的内容作为分支附加到现有树上。
你可以将sublayering视为组成整个场景的不同版本,例如:灯光部门的场景版本与最终照明重叠在Layout部门的场景版本中并使用照明,并将其视为场景添加一部分。
- Sub-layering子层
是最简单的合成操作符(composition arc)。子层的作用是:允许你将场景描述合并到其它层上。
具有相同路径的prims和具有相同名称的属性、元数据的opinions将基于opinion strength合并。
当合并每个文件都应构成整个场景一部分时,此功能很有用。例如,组成代表场景布局,道具,角色,特效,灯光的单独图层。
- Referencing引用
Referencing将被Referencing文件并“参考”到当前树中的分支上。可以理解为Maya的参考。
通过引用(reference)合成操作符来将其它层堆栈(layer stack)中的基础图元(prim)引入到我们的场景图中。这就是我们如何用小的资产来构建大的资产的方式。特别地,引用是在不同位置多次加载同一图层文件的唯一方法。因为子分层适用于整个树,所以多次对同一文件进行子分层将无效。 - Payloads有效载荷
引用(Reference)让我们可以通过小的组件组成大的资产集合体。但是,有的时候需要让用户在运行时决定哪些内容要进行合成。负载(payloads)合成操作符提供了我们这种能力,它可以在运行时通过各种API调用选择加载或卸载的引用,但是有可能让USD不加载有效负载,除非特别要求它们。这使您可以控制场景的哪些部分被加载到内存中,从而通过集中精力关注场景的各个部分来减少内存使用和处理时间。 - Activation and visibility激活和可见性
由于USD是专为非破坏性编辑而设计的,因此不允许deleting( 删除) primitives。但是,可以使用新值override(覆盖 ) primitives,或者deactivate(停用 ) primitives,以使它们不起作用。 - Schema
它可以理解为:模式是一组属性attribute的集合,这些属性赋予了基础容器Prim含义。
提供了一个流程的编程环境。这个是开发者才会接触到的东西,通俗理解就是API包, - Opinion观点
每个usd文件(Layer)都会包含着很多的opinion,比如,覆盖被引用文件box中的颜色属性,修改一下大小,那他就是一个新的opinion。 - Variant变体
变体允许用户在单个资产中打包一组备选方案。用户创建在资产中包含“变体(variant)”的“变量集(variant sets)”,然后编写“变量选择(variant selections)”以选择在合成过程中应该具体使用哪个变体。可以将他理解为同个节点(Prim)的不同版本,比如说一个模型可能实际工作时候有很多的迭代版本,那这n个版本可以用变体这个东西来承载,可以很方便的切换。利用少量的物体能创建出更丰富的资产。
USD的发展历程
USD大约是皮克斯开发的第四代“合成场景描述”。在完成《玩具总动员》之后(《玩具总动员》中每个镜头由单个线性程序文件描述),皮克斯研发团队开始在其专有动画系统Marionette(内部叫Menv)的背景下添加和发展参考、分层、编辑和变体的概念。
从《虫虫特工队》开始,在接下来的十部故事片中继续。到2004年,很明显,尽管Marionette已经发展得非常强大,但其有机发展的起源正在成为持续稳定发展和我们利用多核系统等重要工具的能力的障碍。该工作室现在致力于设计和开发叫做Presto的全新第二代动画系统,该系统最初用于《勇敢传说》,在那之后应用了所有功能。
Presto开始着手解决的Marionette的一个问题是,它的各种组合和覆盖3D场景描述的功能并不总是有效地同时工作,因为它们分布在三种不同的格式和“合成引擎”上。Presto提供了统一的第二代场景描述,支持从单个网格到整个模型,环境或镜头的所有粒度的引用、覆盖、变化和其他操作,以单个ascii格式编码并使用一个组合引擎进行评估。
USD项目的一个关键组成部分是开发一种超现代、可扩展的OpenGL渲染架构,称为Hydra。Hydra作为USD项目的一部分,因为它为流程中USD的使用增加了巨大价值,并在我们所有的插件中使用,它还提供了一个基准和参考,用于如何利用USD的多线程进行快速场景加载和成像,以及有效地更新以响应对活动中的UsdStage的动态编辑。然而,Hydra本身就是一款产品,并且已经拥有除USD以外的其他直接前端耦合器(包括Presto、Maya和Katana插件),并且正在超越其原有的OpenGL架构,为其他后端客户端提供服务,例如路径跟踪器。
USD能做什么
主要有以下几点:
- USD是Pixar公司多年技术迭代的结果,它可以帮助你学习到我们的经验和错误。
- USD的直接继承者就是Pixar公司大名鼎鼎的Presto软件:pixar内部的绑定,动画,模拟软件。所以USD构建在很多有天赋的从业人员,几十年的经验上。
- 这也是为什么USD中有很多很复杂的概念:这么多的概念,是为了生产中更好的解决实际问题,希望在后面的学习中,大家也能理解这些概念为什么是这样的。
- USD设计的主要目的是为了生产:电影级质量的数字内容,并且有着很好的拓展性。
它解决了以稳定性性和可扩展的方式,交换资产组成的任意3D场景的需要。
USD构成语义上最强大,最统一的方面是,所有上述运算符都可以以任何组合应用于任何素数,并且构成引擎将以可预测的方式解析结果图。这种对构图弧进行统一处理的另一个理想属性是,构图中的较强层可以均匀地覆盖较弱层中的场景描述 ,而不管是否对较弱层进行了子层,引用,继承等。针对较弱的层覆盖以下内容:
最后,USD提供了一些场景图级别的功能,可以极大地扩展可编码为USD的数据集的类型和规模。最突出的两个是本机素数实例化,用于非常紧凑地编码(和处理)大量参考资产或素数的实例/副本,适用于不需要深度编辑副本的情况。和Value Clips,它们允许一组素数的timeSamples散布在许多文件中,并且进行无损(重新)排序和重新定时。
USD不能做什么
- 没有GUIDSUSD
使用文本的分层名称空间来标识其数据,这意味着它是“名称空间路径”,通过这些名称绑定将覆盖绑定到其定义的素数/属性。因此,当引用资产的内部名称空间发生更改时,先前记录在引用资产中的更高级别的覆盖将下降。解决此问题的一种方法是通过“全局唯一标识符”(GUID)识别数据,然后将替代与与定义的原语相同的GUID关联。在解决名称空间编辑问题时,GUID将其他问题引入到管道中,并可能限制合成的灵活性。在过去的USD迭代中,Pixar在模型/资产粒度上使用了一种GUID形式,在仔细权衡了利弊之后,偶尔进行“名称空间修复”操作的成本超过了一个集合资产的价值值得为资产构造和聚合的简便性以及我们从名称空间路径中获得的可读的ascii资产表示形式作为标识符而付出。 - 不是执行或操纵系统
USD提供了一个轻量级的,优化的场景图,以方便创作和高效提取组成的场景描述。但是,除了提供名称空间层次结构和属性值解析的组成之外,它没有提供其他行为,并且在低内存占用空间,较高延迟数据访问和高内存占用空间,低延迟数据访问,USD的场景图倾斜之间进行权衡前者则更多,而高性能执行引擎则需要后者。
此外,USD添加更多的操纵行为和执行语义,因此,DCC之间成功交换数据将变得更加困难,因为目前供应商之间对于这些行为的含义尚未达成广泛共识。USD及其模式生成工具应适合于在特定应用程序或自定义管道中用于往返绑定数据的编码绑定,并且USD确实提供了客户端可以用来在UsdStage之上构建更广泛的内存中缓存的功能。提供对以USD编码的数据的低延迟访问。但就目前而言,这些主要指令中并未发挥重要作用:在3D内容创建管道中,DCC之间的几何数据和着色数据的可伸缩交换。
USD的使用
在Windows中编译USD
如果直接去下载到的USD其实是未编译的文件,需要自己动手编译,编译 USD是非常难折腾的,各种各样的报错永不断。那么需要做以下准备
编译所需环境
- Git的安装
如果您不熟悉Git,最简单的方法之一就是使用GitHub Desktop GUI。 - 确保网络正常,编译USD的时候需要下载各种依赖。
- Python2.7
注意:
提示:您可能需要手动将Python Scripts目录添加到系统路径。
1 | C:\ Python27 \ Scripts |
需要的安装库
1 | // 可能不需要 |
用git命令获取USD源码:https://github.com/PixarAnimationStudios/USD
例如:
1 | git clone https://github.com/PixarAnimationStudios/USD |
或者点击:选择“ 克隆”或“下载”。保证路径不要有英文意外的其他字符。
准备编译
1 | 运行开始菜单> Visual Studio 2017> VS 2017的x64本机工具命令提示符 |
测试程序包,如果全部命令都成功,可以进行下一步
进入刚刚克隆下来的USD包。python build_scripts \ build_usd.py“ C:\ USD”
- 如果计划使用Autodesk的maya_usd插件,则需要确保您的USD版本包括Boost库,并且不生成Pixar的Maya USD插件。在您的build命令中添加boost参数,并使用-no-maya开关,如下所示:
1 | python build_usd.py --build-args boost,“-with-date_time --with-thread --with-system --with-filesystem” --no-maya“ C:\ USD” |
- 如果需要明确指定要使用python 2运行构建脚本,请使用py -2而不是python。该脚本不会在python 3下运行。
- 最后的参数是您想要安装USD二进制文件的位置。如果需要,您可以在此处指定其他位置。
编译失败的可能性
- 确认您是通过“管理员权限启动命令提示符 ”而不是普通命令行运行的。
- 确认您已安装VS 2017,并且您正在运行与其关联的本机工具命令提示符
- 类似于以下的错误表明您缺少必需的VS安装:
cmake -DCMAKE_INSTALL_PREFIX="C:\USD" -DCMAKE_PREFIX_PATH="C:\USD" -DCMAKE_BUILD_TYPE=Release -G "Visual Studio 15 2017 Win64" "C:\USD\src\zlib-1.2.11"
- *
1 | CMake Error at CMakeLists.txt:4 (project): |
- 如果安装成功按照提示添加环境变量
1 | 按照安装输出末尾的提示,将PYTHONPATH变量添加到系统变量中。 |
编译完成测试
编译完成包的结构
1 | lib\python,是整个USD开发包调包的地方 |
在命令行输入
1 | usdview .\extras\usd\tutorials\convertingLayerFormats\Sphere.usd |
如果显示如下:表示整个过程成功。
如何使用已经编译好的USD
使用编译好的模型是比较省事的,可以使用NVIDIA编译好的,地址为:
usdView的使用
打开这个工具后,列表视图叫PrimView,usd视口也叫StageView,通过继承自QOpenGL.QGLWidget集成到Qt界面里的。
并且整个界面UI是用Qt编写的,官方也提供了完整的源代码,可以根据自己的工作流去扩展或者魔改它,它也支持插件的扩展功能,官方也给了示例。
PrimView视图
PrimView视图里面是多个usd文件合成,这个列表中的每个prim都有着各自对应的prim type类型,比如:Xform,Camera等等。
点击下方的?,会出现一个新的面板。
- 并且对每一个类别进行了说明:
Normal 通常节点,最普通的一种节点。
HasArcs 当前的节点含有某种合成器,只要父节点有合成机制,那么对应的子节点也会同时起作用
Instance 实例节点,表示是一个实例对象。
Master 被实例节点引用的节点,表示实例的原始模型
加粗的字体是某个usd文件里显式定义了该节点,
斜体字表示usd文件里用over关键字修饰的节点,没有实际内容,是个空节点,也叫Orphaned Over,空覆盖不加字体粗细样式的是抽象节点,被定义了class关键字,比较少见。 - PropertyView
上面的每个prim节点选择,都会显示不同的信息。我们可以把下面这些信息看作是上述选择节点的属性列表。这个列表包含了各种各样的信息,数值,名称,类型。
- 其他视图
Value 选中一个对象,点击,右下角的数字value面板就会有对应的点位置数值
Meta Data 显示的是每个prim节点或者属性的元数据。
layer stack和composition是用来表示当前节点的usd文件,可以通过查看layer stack来直观的看到所有的合成,元数据等。
Interpreter
点击window 下面选Interpreter 会弹出新的窗口。
这个是它提供的的一个usdviewApi的模块接口,状态显示,选择功能等等
usdviewApi的方式遍历场景和prim节点,通用的函数如下:
USD在各DCC软件中的用法概述
在maya中的运用
如果要在maya中使用USD,需要获得Autodesk(以前称为Animal Logic)Maya-USD插件,
可以从Autodesk的Maya-USD GitHub软件仓库获取源代码
1 | https://github.com/Autodesk/maya-usd |
然后在命令行运行,一定要在vs2017的窗口中去运行。
1 | python build.py --generator Ninja --build-args=-DCMAKE_MAKE_PROGRAM=ninja.exe --maya-location "C:\Program Files\Autodesk\maya2020" --pxrusd-location c:\USD --devkit-location c:\devkitBase_maya2020 C:\USD_WorkSpace --build-args="-DPXR_STRICT_BUILD_MODE=OFF“ |
如果编译失败,可能的原因:
可以去这里看,或者提问:https://github.com/Autodesk/maya-usd/blob/fix_import_module_macosx/doc/build.md
USD在Unreal中使用
设置虚幻引擎4以导入和导出USD。从4.22开始,此功能是实验性的,需要一些手动处理。需要在
并启用USD Importer插件和Python编辑器脚本插件。
重启UE4
然后点击导入,我们会发现已经支持usd的导入了。
在houdini中的运用
Houdini18的Solaris算是目前功能最全的了。实现了USD的绝大部分的功能,这个的版本变化比较大,引入了这个新的流程。
在houdini中使用的是Solaris,是18新加入的一个新的模块,也就是houdini为USD所提供的工具支持的统称。
Solaris介绍
- Solaris模块在houdini中的主要工作层级是Lop(Light operator)
- 场景图树中的模型层次结构可能
- 在 Lop层级中,Stage指代的是当前正在操作的整个场景,很多术语是对Usd的简化包装。
houdini中的Solaris。是按照USD的逻辑来布局的。
在Nuke中的运用
只能在Nuke12最新版本中使用,并且功能也是非常少,也是在一个实验阶段的。
使用方式和其他导入方式是一样的,直接用ReadGeo导入即可。
参数也是非常少。
在katana中的运用
要在katana中使用USD,需要设置环境变量:
1 | 1PATH=KATANA_ROOT/plugins/Resources/Usd/lib KATANA_RESOURCES=KATANA_ROOT/plugins/Resources/Usd/plugin |
可以保存一个bat文件来启动:
1 | rem -------- USD Specific ------------ |
目前还是在实验阶段,目前官方提供的USD插件还过于简单,只能完成加载文件。在没有TD的情况下,很难体验到它有先进和爽快感。
总结
- 总结一下优点吧:
1.它的结构是树状的分层描述整个场景的数据,管理灵活并且比较自由。让整个场景的结构能做到很清晰。
2.它的分层功能,主要是组织数据,每一个曾所做的事情,都会对你的结果造成影响,如果不要这层,可以去掉。类似于ps的图层管理。通过这种层和层之间的合成机制,实现了非破坏性的编辑。不会影响到其他环节的数据。
3.USD组织文件的形式,是使用了多层嵌套的引用机制,实现了轻量化的存储。带入数据的时候,效率应该是非常高的。
4.基于Hydra渲染的架构,可以对大规模的网格场景进行比较高效的去预览。然后可以通过不同渲染的代理,进行渲染切换。能快速的看到最终渲染近似的效果。
- 来就目前来看一些比较致命的缺陷了:
目前比较全的功能就是houdinil了,可以完全实现基于USD的从资产到装配到灯光渲染的整个过程。
在其他软件的进度来看,要在不借助TD开发的环境下,想最接近的体验USD的生产流程,简单的选择就是使用Houdini18的Solaris来完模型资产发布,动画及特效完成后再由Solaris输出各层的USD文件并与场景其它内容合并发布最终场景USD,Lookdev部分则交由Katana完成,最后Katana加载由Solaris发布最终场景文件来进行材质装配和布光渲染的工作。
USD对Hydra这个GPU渲染构架支持(需要等商业软件跟进),只能完成预览工作,第三方渲染器跟进的速度也比较缓慢。
还有就是对数据来源有明确的责任分工和技术手段保证落实。对资产的制作和管理会有更高的要求。如果有些概念在现有的流程中没有,引入USD时的改造,目前的情况还是非常曲折。。。
参考文献和其他连接
1 | 编译完成的USD库:https://developer.nvidia.com/usd |