AYON USD Workflow Guide

This is a draft community guide to serve as starting point for the documentation

This post is a WIP and will be edited in the coming days. You reading this now is not recommended AND :frowning_man: frowned upon (just kidding, feel free to provide early comments or questions.) But note that it may be skipping parts here and there or just plainly suck.

Note: If you’re facing USD workflow specific issues that are not global ‘workflow’ related questions those are best kept for a separate community forum post! So, you may want to report issues you have in a separate topic.

Chapters

TODO Chapters?

  • :notebook_with_decorative_cover: What is USD and why? (TODO)
  • :radio_button: Ayon USD Asset Resolver
  • :robot: Maya Workflow
  • :woman_artist: Blender Workflow
  • :woman_astronaut: Unreal Workflow

For now I’ll skip the What is USD? and Why use USD? and get straight to building assets and shots.

Getting started

Creating an asset

The producer has his :gun: pointing at you and needs the asset now!

When we are referring to the USD asset, we mean the asset with both the model’s geometry and the look’s materials and textures. The USD structure (simplified) then becomes:

asset.usd
  - look.usd
  - model.usd

Where the look is applied over the model inside the asset.

Creating the model

From a Maya, Houdini or Blender perspective

TODO: Add visuals - maybe short video recording

We will want to create our geometry’s contribution to the asset.
For the asset structure it’s critical we work within the asset’s hierarchy so that USD referencing works. (consider that USD mumbo jumbo for now)
As such, we’ll always work within a root group with the current folder (asset)'s name.
Say our character’s folder path is assets/char_hero then the root group is char_hero

We can make a hierarchy like:

char_hero/
    geo/
        body
        pants

And yes, cool heroes wear no shirts. :tshirt: Only pants :jeans: .

When done. We publish that char_hero as USD contribution to the model layer.
The publishing logic will make the layering of the model.usd into the asset.usd for you automatically.

So no we have:

asset.usd
    model.usd

When loading that in, we’ll have our hero wearing pants.
But it needs some :paintbrush::art: paint.

Creating the look

From a Houdini perspective

  1. Reference the asset so we have the model.

Note the word “reference” here. We are usually not “sublayering” the asset USD file

  1. Make sure to add a “layer break”. This special Houdini node breaks off the USD scene above it and from that moment on any changes on the existing hierarchy are just opinions that are overlaid on top of it. This means that when writing out a USD file now we’re not re-exporting the geometry itself, but only any changes we make after the layer break.

  2. Apply your materials to the char_hero/geo meshes and make sure your materials are within char_hero group as well. So usually you end up with:

char_hero/
    geo/
       body   <- material 'char_hero/mtl/body_shader' applied
       pants  <- material 'char_hero/mtl/pants_shader' applied
    mtl/
        body_shader
        pants_shader
  1. Publish as the look product type (which is a USD look in Houdini).

Creating a shot

TODO: Add visuals - maybe short video recording

Houdini perspective

  • Quickly, reference the asset.
  • Throw some lights into the scene.
  • Set up the USD Render Settings.
  • Publish your USD render submission to Husk Standalone

You are now the USD champion - until they ask you about asset variants, LODs, purposes and a layered shot structure, and more. Easy, cowboy!

Running production

TODO: Add more production examples

  • Show usage of variants of models and materials
  • Show overriding materials in Lighting department for a Loaded Asset
  • Show render submissions
  • Show rigged character publishing to shot, with cloth/fur after by FX department

Frequent issues

I do not see my model on loading the asset

On Load warning message "Unresolved Reference Path" shows

Since you’re publishing into the asset structure make sure your data is inside the expected default primitive path for that asset, where the default primitive is always {folder[name]} so your data should be inside /{folder[name]}/... so that the data resides inside the default primitive path.

This is wrong: :warning:

/geo/marble
/materials/material1

This is correct: :trophy:

/char_hero
    /geo/marble
    /materials/material1

You are lacking the default primitive it expects.

What are all these publisher options, like Target Product?

Some technical details explained by @MustafaJafar

USD Publish Settings explained

I’ll just focus on 4 interesting settings.

  1. target-product which is a user editable text.
  2. target-product_department-name which is a selection from a drop down list. and users/admins can’t change the items in the list.
  3. variant-set-name which is by default is set to {layer} which evaluates to the selected item in the drop down list in Num2
  4. variant-name which is by default is set to {variant} as the arrow in the screenshot points.

Asset Structure

The asset structure is based on:

But, let me summarize the results.

When enabling Asset Contribution + Add as Variant

[!NOTE]
I love how the asset definition is readable!
Any data in the asset defintion are static. They are computed on publishing.
Paths can change when using AYON resolver.
List of departments, layer-ids and order are hardcoded and not exposed yet to settings.

Product: target-product

# USD Asset
{target-product}.usda
  └── Xform {folder[name]}
        ├── inherits __class__/{folder[name]}
        └── payload ./payload.usda  # Relative path

payload.usda
  └── mata data
        └── sublayers
              └── {target-product_department-name}.usda:ARGS:{layer-id}, {order}

Product: target-product_department-name

# USD Asset Layer
{target-product}.usda
  └── Xform {folder[name]}
        ├── Variant Sets -> ["{variant-set-name}"]
        └── Variant Set "{variant-set-name}"
              └── Variant {variant-name}
                    ├── reference -> Published AYON usd product variant file path
                    └── custom data
                          ├── ayon_order
                          └── ayon_uri -> AYON URI for the published AYON USD product variant

Product: AYON-product-variant

# USD product
{AYON-product-variant}.usd
# It can be any hierarchy.

When enabling Asset Contribution without Add as Variant

It still add a variant! I think there might be a bug or I did something wrong…
Also, I’ll update this section once it works on my side.

When disabling Asset Contribution

[!NOTE]
It doesn’t affect the version in the latest published target-product or target-product_department-name.

Product: AYON-product-variant

{AYON-product-variant}.usd
# It can be any usd hierarchy.

We need to manually rename primitive paths the whole time?

We use reference so we can manually enter the primitive path, but i don’t think that should be the way to go, they should all be connected and work without renaming and further input.

You should not need to manually rename all referenced primitive paths for assets

Using the AYON USD Contribution Workflow manual ‘re-assigning’ all the time for assets should be redundant for the majority of the workflow. (Preferably this should never be needed, but some sections like animation from shot layers may still fall outside of that scope.)

  1. Use the AYON USD Contribution workflow where the asset build is built automatically from single product contributions into the root primitive.
  2. Load the usdAsset - avoid using the indidiviual layers, you should not need to load those individually since they are all in the main asset.

Now, in a shot based workflow you’d just load the asset and since e.g. Maya animation caches are not already overlaid over a USD asset structure that is one of the moments where you will need to define the path you’re overlaying to.

That’s usually like:

  1. Reference the usdAsset into your shot’s structure, e.g.
/asset/char_hero

Which may result in e.g. an asset with model and look:

/asset/
    char_hero/
        geo/..
        mtl/..

(The “char_hero” is the prim where you have the reference to the usdAsset)

What you need to make sure to do is that anything you want to layer on top of your asset comes in with the same hierarchy, so an animation cache preferably also has the structure:

char_hero/
    geo/..

With the animated geometry only. That you can then also reference on top of /asset/char_her in the shot structure which makes your referenced asset (that already has materials) move because just the geometries are being overridden.

Keep in mind the layer strength - referencing lower in the hierarchy means a stronger opinion!

It’s usually important to reference on the same root prim of the asset, because as soon as you e.g. reference over asset/char_hero/geo instead your reference is lower in hierarchy than any reference on a higher prim like asset/char_hero and hence will ALWAYS be the stronger opinion.

Additional context

What’s next?

  • Improving the UX of the workflow - get it into artist’s hands, receive feedback and improve to simplify and streamline the approach.
  • Support a dedicated Ayon USD Asset Resolver to use AYON entity URIs to be resolved with runtime, with support caching and pinning - ayon-usd-resolver
    • And easily make it accessible to studios (ready-to-go builds and downloads from Addon Market, etc.)
  • Providing dedicated Ayon USD editing tools to manage existing USD assets and shots and their contributions, as part of the ayon-usd plug-in.
  • Multi-shot workflows, e.g. in Houdini
  • Providing easy access to USD viewers from e.g. standalone Loader to “view” your published USD shots and assets quickly
  • Publish from Maya RIGs directly to USD layers over a USD asset (preferably even by starting from a USD asset to begin with and swapping to the animation rig from it)
3 Likes

Ayon USD Contribution Workflow

A recent PR implemented a special AYON USD Contribution Workflow.

What is it?

The AYON USD Contribution Workflow allows to create small contribution publishes from DCCs with USD export support to directly add your publish into an asset’s model or look variants or a shot’s department layers. Automatically building up the USD structure for you.

Traditionally each department or artist would generate multiple products that downstream departments would load individually. For example, a lighting department may load each character animation product, each FX product individually.

So there would be some scattered products like:

  • pointcacheMain
  • pointcacheFX_building
  • animationChar01

However, USD can reference and layer non-destructively which means we can safely merge these together at any point. Also making it easy for multiple departments to stack their own opinions and changes onto the departments before you.

This is where the USD Asset Contribution workflow automates this for you.

With the USD Contribution enabled :white_check_mark: on the USD publish instances this means it will automatically add your product into the department layer for the Asset or Shot.

  • usdShot
    • usdShot_animation
      • animationChar01
      • pointcacheMain
    • usdShot_fx
      • pointcacheFX_building

TL:DR :see_no_evil:

With AYON’s USD Contribution each product publish adds up into the target USD asset or USD shot. :tada:

Configuring the USD Contribution

Examples in publisher UI:

Asset contribution to usdAsset for the Look department layer:

image

Shot contribution to usdShot for the FX department layer:

image

Note:

  • Currently it’s a manual process to target usdShot instead of usdAsset for shot contributions. It’s on the planning to improve that workflow! This is notably a common mistake to forget changing that, so be aware!

Disabling USD contribution workflow

If you just disable the USD Contribution > Enable checkbox you will write out just the USD file using the host’s export methods without any automated layering into another product - as such, disabling that means that all the settings underneath it do nothing at all. (They should appear greyed out, but unfortunately it’s a limitation of the publisher UI that it can’t currently)


TODO (Add explanations):

  • How to define the layer strength

Add as variant - or not?

In most cases:

  • an asset contribution is a variant.
  • a shot contribution is not a variant.
Add as variant ENABLED

When enabling Add as variant it means your single contribution will be added as a variant in a variant set on the asset’s root primitive (the default prim). As such, multiple variant contributions to the same department layer (and same variant set) are not active at the same time, but they are switchable variants. So you can for example:

  • Publish a model main variant
  • Publish a model damaged variant

Now in the USD asset on the root primitive you may have a variant set model that contains your modelMain and modelDamaged variants that downstream departments can switch between in your asset.

Add as variant DISABLED

With Add as variant disabled each contribution to a single department layer is just added as essentially another layer - meaning that the contributions inside a single department layer are all live at the same time.

You can for example:

  • Publish a FX shockwave
  • Publish a FX building destruction

Both to the FX department layer - one isn’t necessarily ‘in front of’ the other they are both just unordered contributions in that layer, present at the same time.

So loading the shot with the FX layer will show both the shockwave and building destruction - you’re not picking between the two.

Houdini Workflow

Loading an asset or shot

Via AYON Load Asset LOP node and Sublayer LOP node and Reference LOP node.

TODO

  • Explain that you usually:
    • Reference the usdAsset
    • Sublayer the usdShot
Loading an asset

Whether you’re loading the asset because you’re working on the asset build itself, like look or grooms, OR you are assembling a scene defines what primitive path you load them as.

You would usually always reference the asset. That is the usdAsset product - not the separate layers or contributions.

Asset Build

When working on the asset build, the asset name requires to remain constant and be in a root prim with the folder name. A trick is to set the Primitive Path to:

/`strsplit(chs("folder_path"), "/", -1)`

So that it’s always the folder name of the loaded content (this works only with the Ayon Load Asset LOP)

Shot Assembly

For scene assembly, like doing bigger scene layouts or even just loading assets into a shot. Since these are also for “shot” workflows (you’re building a shot layer) and these sublayer in the different apartments you don’t need a single root primitive, you can layout your scene hierarchy any way you want.

Assembly Prop (asset scene assembly)

TODO

Document how one could make an asset which is essentially an assembly of other assets. This would still require one root prim (a default primitive) and in large part behaves like Asset Build, but just containing child references of other assets.

Layer Break

Via Layer Break LOP node

TODO

Explain layer break

Mute Layers

Via Configure Stage LOP node → Mute Layers

Muting layers allow you to mute for example your own department layer in a loaded USD asset or shot. This way you avoid that your Houdini Solaris graph after publishing and updating already has your generated data loaded back in at the start of the graph.

Imagine you load a USD Shot containing the layers:

  • layout
  • animation

Now you’re working in lighting and write out your contribution.
The USD shot now has:

  • layout
  • animation
  • lighting

As such, your USD scene is now already loading back in what you wrote out last time - which is if you were to remove e.g. a light from Solaris graph it would still be there, because it’s already being loaded in. So, layer muting is what you need here. You basically ensure that you mute your OWN layer so that you don’t include that while you’re working.

Note: The state of muting layers is never written into a USD file - it’s a run-time effect only on your composed USD stage. As such, you can not e.g. write out the opinion from one layer that another layer must be muted from now on. So, you can’t save layer muting into USD files. You can however write new opinions onto the prims or hide/deactivate prims you don’t want - which will be opinions that you can write out and then effect downstream departments.

TODO

  • Layer Mute your current department, HOW and WHY?
  • Add Mute Layers LOP example.

Implicit versus Explicit Layer Save Paths

This is Houdini-specific and not necessarily a USD feature. Houdini can generate in-memory sublayers or references to USD files that does not exist on disk yet - these are so called anonymous layers that Houdini gives an “implicit save path”.

When exporting your USD file (e.g. USD ROP) these implicit layers will be written out from your Houdini scene in addition to the USD file path your set on the USD ROP node.

Publishing with explicit anonymous layers :white_check_mark:

What does the publisher do with these anomymous layers?

Any anonymous layers generated in your current USD layer being exported can directly be published along. The ayon-houdini USD publishing logic detects these anonymous layers that will additionally be saved out, generates publish instances for them dynamically. It suffixes the Explicit Save Path’s filename to the product name generating additonal products, like {product_name}_{explict_save_filename}

So it is totally fine to generate more layers at once and have them published - this will work with and without the Contribution Workflow.

However, there may be many cases where you do essentially not want this extra layer. For example, a SOP import by default generates that additional sublayer, but you may just want to write out that SOP data completely into the resulting USD file - not in an extra sublayer USD file that is layered into a USD file.


TODO

  • Explain Implicit Layer Save Paths and the USD ROP settings for flattening
  • Houdini USD Rop: Flatten All Layers

I’ve added table of contents to the post if you don’t mind :wink:

USD Knowledge References

Introductional Guides

:point_up: Very good introduction to USD concepts in a slightly simplified and practical way

:point_up: More technical guide going over USD with the API as guideway. Also introduces a lot of “workflow optimizations” tips with a focus on Houdini Solaris and Python

Some Pixar tutorials (these are bit more dated)

:point_up: Decent guided tutorials by Pixar - even though they may reflect dated knowledge they are still relevant.

Guides by Apple

USD Pipeline Stories

USD and Houdini

In general, SideFX does not express any opinions on how things should work but rather their focus is on providing the right tools.

:point_up: Guides for Houdini Artists

API Documentation

Developer Guides

They contain some nice samples

2 Likes

USD Asset Structure Guidelines

Example assets

The ALab data set is the Animal Logic interpretation and implementation of real world production and pipeline concepts in USD.

1 Like