Device which generates USD output from intercepted ANARI API calls to, optionally with Omniverse support.
This project can be used purely to output USD files to local disk without any further run- or buildtime dependencies, and does therefore not require the use of Omniverse if not desired. If Omniverse output is enabled, it can be configured to transfer USD data to an Omniverse service of choice.
On Windows and Linux this library builds against: - ANARI SDK (corresponding to git tagged version of this repo) at https://github.com/KhronosGroup/ANARI-SDK - USD version 23.xx or 24.xx, with (if enabled) OpenVDB 10 or 11.
USD can be built/installed in any of the following ways (depending on desired capabilities):
- Get prebuilt USD and optional Omniverse packages according to Downloading the Omniverse libraries
- Build USD from source (https://github.com/PixarAnimationStudios/USD/), optionally with OpenVDB support according to Building USD Manually
- For release/debug versions, observe the directory structure guidelines in Debug Builds section
- (Experimental) Automatic installation of USD as part of the superbuild, see superbuild/README.md
Note that on Linux, GCC only guarantees forward ABI-compatibility, so libraries downloaded from external sources built with newer versions of GCC than the USD device may not link to it properly.
From this directory, run mkdir _build && cd _build, after which there are two ways to build the USD Device:
- Regular build: Directly run
(c)cmake(-gui)on the root directory.- Example of release configuration with Omniverse support, without OpenVDB:
ccmake .. -D "USD_DEVICE_USE_OMNIVERSE=ON" -D "ANARI_ROOT_DIR=<anari_install_path>" -D "USD_ROOT_DIR=<usd_install_path>" -D "OMNIUSDRESOLVER_ROOT_DIR=<omni_usd_resolver_install_path>" -D "OMNICLIENT_ROOT_DIR=<omni_client_install_path>" -D "Python3_ROOT_DIR=<python_install_path>" -D "Python3_FIND_STRATEGY_LOCATION=ON" -D "CMAKE_POSITION_INDEPENDENT_CODE=ON" -D "CMAKE_BUILD_TYPE=Release" -D "CMAKE_INSTALL_PREFIX=<install_path>" - If you want all dependencies to be installed alongside the USD device's binaries, add
-D "INSTALL_ANARI_DEPS=ON" -D "INSTALL_ANARI_COMPILE_DEPS=ON" -D "INSTALL_USD_DEPS=ON" -D "INSTALL_OMNIVERSE_DEPS=ON" - If you also want to generate the example executables, add
-D "USD_DEVICE_BUILD_EXAMPLES=ON". They can be executed standalone if the dependencies from the previous step are installed.
- Example of release configuration with Omniverse support, without OpenVDB:
- (Experimental) Superbuild: run
(c)cmake(-gui)on the../superbuildsubdir, for detailed instructions seesuperbuild/README.md.
After configuring and generating any of the above builds, run cmake --build . --config [Release|Debug] --target install to build and install.
- Library and device names are both
usd - All device-specific parameters are prefixed with
usd:: - See
usd_device_features.jsonfor parameter names and descriptions - Examples in
examples/anariTutorial_usd(_time).c
More details about specific parameters and unsupported features follow below.
Specific ANARIDevice object parameters:
- Set
usd::serialize.locationstring to the output location on disk,usd::serialize.outputBinarybool for binary or text output. These parameters are immutable (after firstanariCommit). - Alternatively,
usd::serialize.locationwill also try theANARI_USD_SERIALIZE_LOCATIONenvironment variable. If neither are specified, it will default to"./"and emit a warning. - Parameter
usd::serialize.hostNamehas to be used to specify the server name (if Omniverse support is available) and optional port for Omniverse connections. This parameter is immutable. - Use
usd::timeto set a global timestep for USD output. All parameters and references from parent to child ANARI objects will be converted into USD for this particular global timestep, with the optional exception of "timed objects" (see below). The value of this parameter can be changed at any time, but make sure to callanariCommiton the device after setting it.
Specific ANARI scene object parameters (World, Instancer, Group, Surface, Geometry, Volume, Spatialfield, Material, Sampler, Light):
- Each ANARI scene object has a
nameparameter as scenegraph identifier (over time). Upon setting this name, a formatted version is stored in theusd::nameproperty (with corresponding.sizeas uint64). AfteranariRenderFrame(or, if theusd::writeAtCommitdevice parameter is enabled, afteranariCommitfor some objects), its full USD primpath can be retrieved by querying theusd::primPathproperty (with corresponding.sizeas uint64). - Changes to data are actually saved to USD output when
anariRenderFrame()is called. - If ANARI objects of a certain
nameare not referenced from within any committed timestep, their internal data is cleaned up when callinganariDeviceSetParam(d, "usd::garbageCollect", ANARI_VOID_POINTER, 0). This is advised after everyanariRenderFrame()or a subfrequency thereof. - If there is a desire to remove individual objects from USD, use the parameter
usd::removePrim. It will throw a warning if the object is still referenced by any other objects.
Specific ANARI timed object parameters (Geometry, Material, Spatialfield, Sampler):
- A
usd::timeparameter to define the time at whichcommit()will add the data to the scenegraph object indicated byusd::name, regardless of the global timestep set for the ANARIDevice object. The effect of setting this parameter is that the parent objects referencing these "timed objects" will keep a USD-based time-mapping per global timestep. This way, a child reference defined at a particular global timestep will point to the data output of the child object at itsusd::time, thereby avoiding data duplication. This parameter is applied like any other parameter duringanariCommit.
For Surface and Volume:
- A
usd::isInstanceableparameter is defined to allow the user to write theinstanceablemetadata to the corresponding USD output prim.
ANARIDevice object parameters:
- Device parameter
usd::sceneStageallows the user to provide a pre-constructed stage, into which the USD output will be constructed. For correct operation, make sure thatanariSetParameterforusd::sceneStagetakes aUsdStage*(ie. thememargument is directly ofUsdStage*type) withANARI_VOID_POINTERas type enumeration. This parameter is immutable. - Device parameter
usd::enableSavingof typeANARI_BOOL(defaultON) allows the user to explicitly control whether USD output is written out to disk, or kept in memory. Assets that are not stored in USD format, such as MDL materials, texture images and volumes, will always be written to disk regardless of the value of this parameter. In order for no files to be written at all, additionally pass the special string"void"tousd::serialize.location. This parameter can be changed at any time and applies immediately. - Device parameter
usd::serialize.newSessionof typeANARI_BOOL(defaultON) allows the user to explicitly control whether a new empty session directory has to be created for USD output, or whether the last written session and its USD files have to be reopened, after which the device will continue (over-)writing the existing files. In the latter case, existing prims will be changed to match the contents of any committed ANARI objects that go by their corresponding name, but other already existing prims within the USD files will be left untouched. This parameter is immutable. - Device parameters
usd::output.<x>, which give control over what or how certain objects are converted to USD, to increase compatibility with certain renderers or reduce clutter in the resulting USD graph. All of them are immutable. Permissible values for<x>are:material: Whether material objects are included in the outputpreviewsurfaceshader: Whether previewsurface shader prims are output for material objectsmdlshader: Whether mdl shader prims are output for material objects
- Device parameter
usd::writeAtCommitcontrols whether writing to USD will happen immediately at theanariCommitcall, or atanariRenderFrame(default). The potential advantage of the former is that one has more granular control over USD processing time. Note that if this parameter is set, the ANARIDevice (specifically itsusd::time) should be committed before any other object in the scene. This parameter can be changed at any time and applies immediately. - For Geometry objects, the
primitive/vertex.attribute<x>parameters are typically output as primvars namedattribute<x>on the USD prim. However, custom names are supported by using theusd::attribute<x>.nameparameter on the Geometry object, which will directly correspond to the name of the primvar output. So make sure these names are not clashing with in-built USD primvar names (eg. by prefixing the attribute names) and that any sampler/material attribute bindings are directly set to that name as well.
ANARI scene objects:
- Use individual bits of the
usd::timeVaryingparameter to control which exact ANARI object parameters should vary over time, and which ones should store only one value over all timesteps. Parameters that are possibly timevarying can be gathered fromusd_device_features.json, by looking at theusd::timeVarying.<parametername>parameter names. For certain parameters referring to ANARI object references (such as geometries/volumes/materials/samplers), the value of their referenced timestep can be set with the parameterusd:time.<parametername>. All these parameters can be changed at any time and are applied like any other parameter duringanariCommit.
- Geometries:
- all fixed point color array types will be normalized to float, double will be type-cast
- Cones/Cylinders/Glyphs do not support the
capsparameter, or thevertex.capattribute - For triangles and quads, the
vertex.tangentattribute is not supported
- Volumes and SpatialFields:
unitDistancehas no effectfilterhas no effect
- Materials:
- Setting a parameter to an attribute string will only produce valid output if the parameter value and connected attribute array type are an exact match, unless:
- A float4/float3 attribute is bound to a float3/color input.
- Attribute strings
primitiveId,worldPositionandworldNormalare unsupported - Beyond the parameters already present in the matte material, the physicallyBased material only supports
emissive,metallic,roughnessandior
- Setting a parameter to an attribute string will only produce valid output if the parameter value and connected attribute array type are an exact match, unless:
- Samplers:
- setting
inAttributewill only produce valid output if the parameter value type and connected attribute array type are an exact match - Attribute strings
primitiveId,worldPositionandworldNormalare unsupported - the
<in/out>Transformand<in/out>Offsetparameters
- setting
- Lights:
- unsupported for now
- Properties:
boundsproperty not queryable (World, Instance, etc.)
If you have separate release and debug versions of USD, (or standalone OpenVDB, Blosc, Zlib), make sure the /lib and /include directories of the respective installations exist within /release and /debug directories, ie. for USD: <USD_ROOT_DIR>/release and <USD_ROOT_DIR>/debug.
- Clone the Connect Sample on Github: https://github.com/NVIDIA-Omniverse/connect-samples
- Make sure you check out a tag using a supported USD version for this USD device: inspect the
deps/target-deps.packman.xmlfile, and make sure that theomni_connect_sdkentry contains a major version of thepxr-<version>substring corresponding to what is listed at the top of thisREADME.md. - Build the connect sample by running
repo.sh/.bat buildin its folder - Locate the
usd,omni_usd_resolver,omni_client_libraryandpythonfolders in the_build/target-depssubfolder - The location of the previous four subfolders respectively can directly be set as
USD_ROOT_DIR,OMNIUSDRESOLVER_ROOT_DIR,OMNICLIENT_ROOT_DIR,Python3_ROOT_DIRin the ANARI CMake (superbuild) configuration, as demonstrated in Building the ANARI USD device.
- The environment variable BOOST_ROOT should not be set
- On Linux:
- Zlib has to either be installed on a system level or built from source (with
-fPICadded toCMAKE_CXX_FLAGS)- Run, for a particular value of
<zlib_install_dir>:export CMAKE_ZLIB_ARGS="-D ZLIB_ROOT=<zlib_install_dir>
- Run, for a particular value of
- If using Anaconda:
- The pyside2 and pyopengl package has to be included in the environment
- Make sure a Python include directory without
msuffix exists (create a symbolic link if necessary)
- Run, for a particular value of
<config>:export LD_LIBRARY_PATH=<USD_ROOT_DIR>/<config>/lib:$LD_LIBRARY_PATH
- Zlib has to either be installed on a system level or built from source (with
- On Windows:
- Make sure
pyside2-uic.exefrom your Python./Scriptsdirectory is in thePATH - only for debug builds: In pyconfig.h all
pragma comment(lib,"pythonXX.lib")statements should change topragma comment(lib,"pythonXX_d.lib"). They can be changed back after building USD.
- Make sure
- Build and install USD by running the buildscript
python <usd_source_dir>/build_scripts/build_usd.py <USD_ROOT_DIR>/<config>(whereUSD_ROOT_DIRis the desired installation location)- Add
--debug(v21.08-) or--build-variant debug(v21.11+) for debug builds - For OpenVDB on Windows, run in a developer command prompt and add the following flags:
--openvdb --build-args openvdb,"-DCMAKE_CXX_FLAGS=\"-D__TBB_NO_IMPLICIT_LINKAGE /EHsc\""- OpenVDB's FindIlmBase.cmake might be broken for debug builds; make sure that the
_dsuffix is removed from<USD_ROOT_DIR>/<config>/lib/Half-X_X_d.liband<USD_ROOT_DIR>/<config>/bin/Half-X_X_d.dllafter running the build once, then run it again.
- OpenVDB's FindIlmBase.cmake might be broken for debug builds; make sure that the
- For OpenVDB on Linux, add the following flags:
--openvdb --build-args openvdb,"-D CMAKE_CXX_FLAGS:STRING=-fPIC $CMAKE_ZLIB_ARGS" blosc,"-D CMAKE_C_FLAGS:STRING=-fPIC -D CMAKE_CXX_FLAGS:STRING=-fPIC" openexr,"$CMAKE_ZLIB_ARGS"
- Add