Build against OpenUSD 25.11 built from source with Python 3.12, OCIO 2.2.1,
OpenVDB, Ptex and Embree, replacing the 25.05/py311 mix.
Build system:
- CMAKE_PREFIX_PATH -> third_party/OpenUSD-v25.11; HDARNOLD_ROOT ->
hdArnold-v25.11. hdEmbree is bundled in the USD build now, so
HDEMBREE_USD_ROOT is no longer needed.
- FindOpenUSD: drop usd_ndr (ndr was merged into sdr in 25.11).
- hdArnold plugin renames: ndrArnold -> nodeRegistryArnold, plus the new
usdImagingArnold plugin.
- Glob the version-suffixed OpenColorIO_*.dll instead of hardcoding 2_1.
- Drop the python311.dll workaround; USD and Cycles now share Python 3.12.
- Cycles: deploy OpenColorIO_2_5.dll (needed by its bundled OpenImageIO) and
stop the debug-DLL filter from eating IlmThread.dll -- the regex `d[.]dll$`
also matched legitimate Release DLLs.
Runtime fixes:
- cullStyle now defaults to Nothing, matching usdview (viewSettingsDataModel
cullBackfaces=False). BackUnlessDoubleSided drops back faces on geometry
that isn't authored doubleSided, which hdEmbree applies to occlusion rays
too, so interiors shaded as single-sided.
- Set HDARNOLD_osl_includepath (and PXR_MTLX_STDLIB_SEARCH_PATHS) in main.cpp
before the plugin DLL pre-load. hdArnold compiles MaterialX via generated
OSL that begins with #include "mx_funcs.h"; without an include path Arnold
fails with "fatal error: 'mx_funcs.h' file not found". It must be set before
any plugin loads because TF_DEFINE_ENV_SETTING caches the value when
hdArnold.dll registers its settings.
- Deploy the MaterialX standard library next to the executable.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Move the imgui-node-editor subset the build actually compiles from
third_party/imgui-node-editor to src/ui/NodeEditor (version-controlled,
MIT LICENSE included). FindImguiNodeEditor.cmake points at the new
location; CMakeLists excludes src/ui/NodeEditor from UI_SOURCES so it
isn't compiled twice.
Material editor presets: a Presets menu (disabled with no open material)
builds a UsdPreviewSurface + UsdUVTexture graph fed by an st primvar
reader, or a MaterialX standard_surface + image graph fed by a texcoord
node. Each is one idempotent, undoable command that re-normalizes layout.
Create Material becomes an icon button. New nodes route through
FindFreeCanvasSpot so a creation never lands on top of an existing node
(overlapping nodes fight over the editor hit test and become undraggable).
Shader-ball preview: pick a previewable output (terminal or 3/4-component
color-like) instead of always the first output, so scalar-only nodes keep
the whole-material preview rather than failing Storm codegen. Per-shape
camera frame-fit margins and auto-clip framing.
Fixes: DeletePrimCommand::Undo recreates missing destination ancestors
before SdfCopySpec (parent material may have been deleted after the
command ran). ConfigWindowsMoveFromTitleBarOnly stops a content-area drag
in the node canvas from moving the whole Material Editor window.
Temporary (marked for removal once the node-editor drag regression is
diagnosed): main.cpp mirrors LOG_INFO to %APPDATA%\UsdLayerManager\
debug.log; a g_AxNodeEditorDebugLog hook in the vendored editor plus a
[NodeGraph] event-trace block in RenderNodeGraphCanvas dump click/drag/
selection/position-save state.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Preview geometry dropdown: Sphere / Cube / Cylinder (native prims),
Teapot and Hair (bundled resources/preview/*.usdc - teapot tessellated
from the Newell patch data with the Blinn 1.3x height correction, hair
as 220 procedural B-spline strands), and Cloud Volume (UsdVolVolume
over the OpenVDB bunny_cloud sample, downloaded at CMake configure and
gitignored like the HDRIs). Shapes live under one scope with the
material bound on it; switching activates one shape and reframes the
camera. Missing assets drop out of the dropdown. usdVol added to the
USD link set. The camera starts in a Maya-style 3/4 view.
Node property values switch from Input* fields back to draggable
controls (Ctrl+click to type): live-apply while dragging, one undo
command on release.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Browser column lists all scene materials plus a searchable create-node
list; Show Graph (or double-click) loads a material into the node-graph
work area. The graph shows the entire network including MaterialX
(.mtlx) node graphs, resolving connections through NodeGraph boundaries
via UsdShadeUtils::GetValueProducingAttributes, with layered auto-layout
for nodes lacking authored uiPosition. Canvas navigates viewport-style
(Alt+MMB pan / Alt+RMB zoom) and TAB opens a Nuke-style search popup.
Selecting a node shows a typed property editor (live-apply, one undo
command per edit) and previews that node's output on the shader ball.
The preview renders through its own Hydra engine into a scratch stage
that composes the material via a reference to the source root layer (so
referenced .mtlx materials work), re-renders until progressive delegates
(Arnold/Cycles/Embree) converge, and lights with HDR dome presets
(External/Room/Interior/Sunset; CC0 Poly Haven EXRs fetched at CMake
configure). texture:format is authored latlong explicitly - left
automatic, hdArnold falls back to Arnold's angular fisheye default -
and hdCycles gets a -90 X pole rotation to match Storm's +Y-pole
sampling.
Mutations go through new ICommand subclasses (create shader node,
connect/disconnect attrs). imgui-node-editor is vendored (gitignored)
with a local one-line patch: c_ScrollButtonIndex 1->2 for MMB pan.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Hydra's HdxColorCorrectionTask rendered prims black in OCIO mode and could
corrupt the GlfDrawTarget bind stack on failure (skipping Unbind), blacking
out every later frame including sRGB. Replace it with our own GL post-process:
the scene renders linear (RGBA16F) and is corrected by a fullscreen shader --
linear->sRGB encode, or OCIO via the OCIO 2.1 GPU API (GpuShaderDesc plus
uploaded 1D/3D LUT textures). OCIO build failures fall back to sRGB (never
black) and USD diagnostics are routed to the app log.
- core: ViewportColorCorrector + ApplyViewportColorCorrection in UsdSceneRenderer
- utils: OcioConfigParser enumerates displays/views/colorspaces/looks from $OCIO
- ui: gear-menu OCIO controls (ViewportTile) + per-viewport persistence (ViewportPanel)
- Application: point $OCIO at the bundled ACES 1.2 config
- CMake: link/copy OpenColorIO, download ACES 1.2 config; plus hdCycles build
config (disable OpenVDB/Embree, fix TBB/OpenSubdiv/Imath dirs, exclude CRT DLLs)
- main: pre-flight plugin DLL load check to skip plugins with missing deps
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Two independent fixes for the install layout:
1. Cycles bundles old MSVC CRT DLLs (MSVCP140 v14.34, VCRUNTIME140 v14.34)
that are placed in install/bin/ via the CYCLES_INSTALL_DIR copy. These take
precedence over System32 on the DLL search path. sycl8.dll (built with newer
VS2022 CRT v14.42) calls functions that don't exist in the old version, causing
ERROR_DLL_INIT_FAILED (1114) when hdCycles.dll loads embree4 -> sycl8. Fix:
exclude MSVCP140*.dll, VCRUNTIME140*.dll, ucrtbase*.dll, api-ms-win-*.dll from
the install(DIRECTORY cycles_install/) rule. The system VC++ Redistributable
satisfies these at runtime.
2. usd_python.dll (the OpenUSD Python bindings DLL) was compiled against Python
3.11 while our build targets Python 3.12. Add auto-detection of python311.dll
from common install paths and deploy it to both the build output and install/bin/
so the dependency chain hdCycles->usd_python->python311 is satisfied.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
plugin/usd without a trailing slash made CMake install the directory
itself under bin/usd/, landing plugins at bin/usd/usd/hdStorm/ etc.
(one level too deep). Adding the trailing slash installs the contents
directly into bin/usd/, matching the build-directory layout that
POST_BUILD produces via copy_directory.
Also removed the now-redundant install(FILES hdStorm.dll DESTINATION bin)
which was placing the DLL in the exe root instead of bin/usd/ where
plugInfo.json's LibraryPath expects it.
hdEmbree, hdArnold, and hdCycles install rules were already correct
(they explicitly target bin/usd/); this change makes the base USD
plugin/usd contents consistent with them.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- TimelinePanel: Playblast button opens modal with output dir (native
folder picker via IFileOpenDialog), custom resolution (HD/FHD/4K
presets), frame range, and movie export toggle
- UsdSceneRenderer: CaptureFrame() reads pixels from resolved MSAA FBO;
Render() stores last dimensions for off-screen re-render at capture res
- MovieEncoder: streams RGBA frames directly into MP4 using libavcodec/
libswscale (H.264, tries libx264 → nvenc → qsv → amf → openh264)
- Application: CapturePlayblastFrame() re-renders at capture resolution
each frame; opens/writes/closes MovieEncoder inline with the render loop
- FileDialog: BrowseFolder() using Vista-style IFileOpenDialog (COM)
- CMake: FindFFmpeg.cmake locates prebuilt BtbN GPL shared package in
third_party/ffmpeg; links and copies DLLs for main and test targets
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
install(DIRECTORY) disallows OPTIONAL together with FILES_MATCHING, which
broke reconfigure. The directory is always present here (produced by the
CyclesBuild step), so OPTIONAL was unnecessary.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Build Cycles from third_party/cycles via ExternalProject (WITH_CYCLES=ON)
- Deploy hdCycles.dll + plugin metadata to usd/ alongside hdEmbree/hdArnold
- Copy Cycles runtime deps (embree4, openvdb, OIDN, sycl, imath, etc.) via
a cmake -P script that globs at build time, excluding CRT DLLs to avoid
MSVCP140 version conflicts
- Deploy tbb12.dll explicitly from the precompiled lib tree (required by
openvdb/embree4 but absent from the install output)
- Bake all renderer paths into CMakePresets.json default preset
(WITH_CYCLES, HDARNOLD_ROOT -> E:/library/hdArnold, ARNOLD_LOCATION,
HDEMBREE_USD_ROOT) so a fresh configure needs no manual -D flags
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds HDARNOLD_ROOT and ARNOLD_LOCATION cache variables to detect and deploy
the arnold-usd Hydra render delegate (hdArnold.dll, ndrArnold.dll) built from
arnold-usd Arnold-7.4.0.0 against MtoA 5.5.0. DLLs land in usd/ alongside
their plugInfo metadata dirs so LibraryPath ../hdArnold.dll resolves correctly.
ai.dll is copied to the exe root for Windows DLL search resolution.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
plugInfo.json declares LibraryPath '../hdEmbree.dll', relative to usd/hdEmbree/,
so the DLL must live at usd/hdEmbree.dll. The previous POST_BUILD copied it to
the exe root, causing the module-not-found error at load time.
Fix: copy hdEmbree.dll into usd/ for POST_BUILD and install(). embree3.dll
stays in the exe root where Windows DLL search finds it as a dependency.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The previous approach assumed hdEmbree lived inside OpenUSD_ROOT_DIR, which
only works when USD itself was built with PXR_ENABLE_EMBREE_PLUGIN=ON.
This change adds HDEMBREE_USD_ROOT to point at a separate USD build that
includes hdEmbree (e.g. E:/USD_v25.05_embree), while the main USD install
remains at OpenUSD_ROOT_DIR. Fixes three bugs from the prior commit:
- Detection now resolves _hdembree_root from HDEMBREE_USD_ROOT first
- hdEmbree.dll path corrected: it lives at plugin/usd/hdEmbree.dll, not
inside the plugin/usd/hdEmbree/ metadata subdirectory
- DLL glob changed from tbb12.dll (Embree 4) to embree*.dll only; tbb*.dll
is deliberately excluded to avoid conflicts with the main USD install
- POST_BUILD now also deploys the hdEmbree/ metadata dir to usd/hdEmbree/
- install() deploys the hdEmbree/ metadata dir alongside hdEmbree.dll
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When the USD installation contains plugin/usd/hdEmbree/ (i.e. USD was built
with PXR_ENABLE_EMBREE_PLUGIN=ON), the build system now:
- Detects OPENUSD_HAS_EMBREE and logs status in the CMake configure output
- POST_BUILD: copies Embree runtime DLLs to the exe directory (looks in USD lib/
first, or EMBREE_LOCATION cache variable if DLLs live in a separate SDK dir)
- install(): deploys hdEmbree.dll and Embree DLLs alongside other runtime DLLs
- Adds EMBREE_LOCATION CACHE PATH for pointing at an external Embree SDK bin/
No app code changes needed: UsdImagingGLEngine::GetRendererPlugins() already
enumerates all registered Hydra plugins, and the per-viewport renderer dropdown
already lists them. HdEmbree will appear automatically once the plugin is present.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>