Skip to content

Commit

Permalink
Fix OpenVDB fieldName in hydra & assign default volume shader in USD #…
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastienblor authored Feb 19, 2025
1 parent 50589e8 commit c4cd82b
Show file tree
Hide file tree
Showing 11 changed files with 603 additions and 28 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
- [usd#2148](https://github.com/Autodesk/arnold-usd/issues/2248) - Leverage new Shared Arrays API in the render delegate.
- [usd#2227](https://github.com/Autodesk/arnold-usd/issues/2227) - Hydra procedural breaks the Arnold logging settings
- [usd#2228](https://github.com/Autodesk/arnold-usd/issues/2228) - Release usd stage after the hydra procedural translation
- [usd#2240](https://github.com/Autodesk/arnold-usd/issues/2240) - Default volume shader should be assigned in the usd procedural
- [usd#2242](https://github.com/Autodesk/arnold-usd/issues/2242) - Support HDARNOLD_DEBUG_SCENE env var in the hydra procedural

### Bug fixes
Expand All @@ -19,6 +20,7 @@
- [usd#2224](https://github.com/Autodesk/arnold-usd/issues/2224) - Fix warning "HdArnoldDriverMain is already installed"
- [usd#2234](https://github.com/Autodesk/arnold-usd/issues/2234) - Fix warning "Selected hydra renderer doesn't support prim type 'RenderSettings'"
- [usd#2232](https://github.com/Autodesk/arnold-usd/issues/2232) - Fix incorrect husk render of left handed indexed meshes with normals.
- [usd#2239](https://github.com/Autodesk/arnold-usd/issues/2239) - OpenVDB asset with explicit fieldName does not render in hydra

## Pending Feature release

Expand Down
18 changes: 13 additions & 5 deletions libs/render_delegate/volume.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ const HtoAFnSet _GetHtoAFunctionSet()
TF_DEFINE_PRIVATE_TOKENS(_tokens,
(openvdbAsset)
(filePath)
(fieldName)
);
// clang-format on

Expand Down Expand Up @@ -221,7 +222,7 @@ void HdArnoldVolume::Sync(
sceneDelegate->GetRenderIndex().GetSprim(HdPrimTypeTokens->material, materialId));
auto* volumeShader =
material != nullptr ? material->GetVolumeShader() : _renderDelegate->GetFallbackVolumeShader();
_ForEachVolume([&](HdArnoldShape* s) { AiNodeSetPtr(s->GetShape(), str::shader, volumeShader); });
_ForEachVolume([&](HdArnoldShape* s) { if (volumeShader) AiNodeSetPtr(s->GetShape(), str::shader, volumeShader); else AiNodeResetParameter(s->GetShape(), str::shader); });
}

auto transformDirtied = false;
Expand Down Expand Up @@ -295,16 +296,23 @@ void HdArnoldVolume::_CreateVolumes(const SdfPath& id, HdSceneDelegate* sceneDel
if (path.empty()) {
path = assetPath.GetAssetPath();
}
TfToken fieldName = field.fieldName;
const auto fieldNameValue = sceneDelegate->Get(field.fieldId, _tokens->fieldName);
if (fieldNameValue.IsHolding<TfToken>()) {
const TfToken &fieldNameToken = fieldNameValue.UncheckedGet<TfToken>();
if (!fieldNameToken.IsEmpty())
fieldName = fieldNameToken;
}
if (TfStringStartsWith(path, "op:")) {
auto& fields = houVdbs[path];
if (std::find(fields.begin(), fields.end(), field.fieldName) == fields.end()) {
fields.push_back(field.fieldName);
if (std::find(fields.begin(), fields.end(), fieldName) == fields.end()) {
fields.push_back(fieldName);
}
continue;
}
auto& fields = openvdbs[path];
if (std::find(fields.begin(), fields.end(), field.fieldName) == fields.end()) {
fields.push_back(field.fieldName);
if (std::find(fields.begin(), fields.end(), fieldName) == fields.end()) {
fields.push_back(fieldName);
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions libs/translator/reader/read_geometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,10 +203,10 @@ static inline void _ReadGenericShape(const UsdPrim &prim, UsdArnoldReaderContext
// If requested, we can read the material bindings
if (readMaterial) {
int derivedType = AiNodeEntryGetDerivedType(AiNodeGetNodeEntry(node));
// For volumes & procedurals, we do not assign a default shader
// For volumes, we do not assign a default shader
// as it could cause problems in Arnold
ReadMaterialBinding(prim, node, context,
derivedType != AI_NODE_SHAPE_PROCEDURAL && derivedType != AI_NODE_SHAPE_VOLUME);
derivedType != AI_NODE_SHAPE_PROCEDURAL);
}

if (AiNodeIs(node, str::polymesh)) {
Expand Down
44 changes: 27 additions & 17 deletions libs/translator/reader/reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ UsdArnoldReader::UsdArnoldReader(AtUniverse *universe, AtNode *procParent)
_threadCount(1),
_mask(AI_NODE_ALL),
_defaultShader(nullptr),
_defaultVolumeShader(nullptr),
_hasRootPrim(false),
_readStep(READ_NOT_STARTED),
_purpose(UsdGeomTokens->render),
Expand Down Expand Up @@ -819,35 +820,44 @@ void UsdArnoldReader::ClearNodes()
_nodes.clear();
_nodeNames.clear();
_defaultShader = nullptr; // reset defaultShader
_defaultVolumeShader = nullptr;
}

void UsdArnoldReader::CreateViewportRegistry(AtProcViewportMode mode, const AtParamValueMap* params) {
delete _readerRegistry;
_readerRegistry = new UsdArnoldViewportReaderRegistry(mode, params);
}

AtNode *UsdArnoldReader::GetDefaultShader()
AtNode *UsdArnoldReader::GetDefaultShader(bool isVolume)
{
AtNode *node = nullptr;
// Eventually lock the mutex
LockReader();

if (_defaultShader == nullptr) {
// The default shader doesn't exist yet, let's create a standard_surface,
// which base_color is linked to a user_data_rgb that looks up the user data
// called "displayColor". This way, by default geometries that don't have any
// shader assigned will appear as in hydra.
_defaultShader = AiNode(_universe, AtString("standard_surface"), AtString("_default_arnold_shader"), _procParent);
AtNode *userData = AiNode(_universe, AtString("user_data_rgb"), AtString("_default_arnold_shader_color"), _procParent);
_nodes.push_back(_defaultShader);
_nodes.push_back(userData);
AiNodeSetStr(userData, str::attribute, AtString("displayColor"));
AiNodeSetRGB(userData, str::_default, 1.f, 1.f, 1.f); // neutral white shader if no user data is found
AiNodeLink(userData, str::base_color, _defaultShader);
if (isVolume) {
if (_defaultVolumeShader == nullptr) {
// The default volume shader doesn't exist yet, let's create a standard_volume,
_defaultVolumeShader = AiNode(_universe, AtString("standard_volume"), AtString("_fallbackVolume"), _procParent);
_nodes.push_back(_defaultVolumeShader);
}
node = _defaultVolumeShader;
} else {
if (_defaultShader == nullptr) {
// The default shader doesn't exist yet, let's create a standard_surface,
// which base_color is linked to a user_data_rgb that looks up the user data
// called "displayColor". This way, by default geometries that don't have any
// shader assigned will appear as in hydra.
_defaultShader = AiNode(_universe, AtString("standard_surface"), AtString("_default_arnold_shader"), _procParent);
AtNode *userData = AiNode(_universe, AtString("user_data_rgb"), AtString("_default_arnold_shader_color"), _procParent);
_nodes.push_back(_defaultShader);
_nodes.push_back(userData);
AiNodeSetStr(userData, str::attribute, AtString("displayColor"));
AiNodeSetRGB(userData, str::_default, 1.f, 1.f, 1.f); // neutral white shader if no user data is found
AiNodeLink(userData, str::base_color, _defaultShader);
}
node = _defaultShader;
}

UnlockReader();

return _defaultShader;
return node;
}

// Process eventual light links info, and apply them to the
Expand Down
5 changes: 4 additions & 1 deletion libs/translator/reader/reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ class UsdArnoldReader : public ProceduralReader {
bool HasRootPrim() const {return _hasRootPrim;}
const UsdPrim &GetRootPrim() const {return _rootPrim;}

AtNode *GetDefaultShader();
AtNode *GetDefaultShader(bool isVolume = false);

AtNode *LookupNode(const char *name, bool checkParent = true)
{
auto it = _nodeNames.find(std::string(name));
Expand Down Expand Up @@ -222,6 +223,8 @@ class UsdArnoldReader : public ProceduralReader {
std::unordered_map<std::string, UsdCollectionAPI> _shadowLinksMap;

AtNode *_defaultShader;
AtNode *_defaultVolumeShader;


bool _hasRootPrim; // are we reading this stage based on a root primitive
UsdPrim _rootPrim; // eventual root primitive used to traverse the stage
Expand Down
24 changes: 21 additions & 3 deletions libs/translator/reader/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,26 @@ TF_DEFINE_PRIVATE_TOKENS(
((PrimvarsArnoldUvRemap, "primvars:arnold:uv_remap"))
((PrimvarsArnoldDeformKeys, "primvars:arnold:deform_keys"))
((PrimvarsArnoldTransformKeys, "primvars:arnold:transform_keys"))
((PrimvarsArnoldStepSize, "primvars:arnold:step_size"))
);

static inline bool IsVolume(const AtNode* node, const UsdPrim& prim)
{
if (AiNodeIs(node, str::volume))
return true;

if (AiNodeIs(node, str::polymesh)) {
// For mesh nodes, check if an attribute primvars:arnold:step_size exists in the usd primitive
UsdAttribute stepSizeAttr = prim.GetAttribute(_tokens->PrimvarsArnoldStepSize);
if (stepSizeAttr && stepSizeAttr.HasAuthoredValue()) {
VtValue value;
if (stepSizeAttr.Get(&value))
return VtValueGetFloat(value) > AI_EPSILON;
}
}
return false;
}

bool HasConstantPrimvar(UsdArnoldReaderContext &context, const TfToken& name)
{
const std::vector<UsdGeomPrimvar>& primvars = context.GetPrimvars();
Expand Down Expand Up @@ -294,7 +312,7 @@ void ReadMaterialBinding(const UsdPrim &prim, AtNode *node, UsdArnoldReaderConte
context.AddConnection(node, "shader", shaderPrim.GetPath().GetString(),
ArnoldAPIAdapter::CONNECTION_PTR);
} else if (assignDefault) {
AiNodeSetPtr(node, str::shader, context.GetReader()->GetDefaultShader());
AiNodeSetPtr(node, str::shader, context.GetReader()->GetDefaultShader(IsVolume(node, prim)));
}

if (isPolymesh && dispPrim) {
Expand Down Expand Up @@ -333,7 +351,7 @@ void ReadSubsetsMaterialBinding(
if (shaderPrim)
shaderStr = shaderPrim.GetPath().GetString();
else if (assignDefault) {
shaderStr = AiNodeGetName(context.GetReader()->GetDefaultShader());
shaderStr = AiNodeGetName(context.GetReader()->GetDefaultShader(IsVolume(node, prim)));
}
if (shaderStr.empty())
shaderStr = "NULL";
Expand Down Expand Up @@ -387,7 +405,7 @@ void ReadSubsetsMaterialBinding(
if (shaderPrim) {
shaderStr = shaderPrim.GetPath().GetString();
} else if (assignDefault) {
shaderStr = AiNodeGetName(context.GetReader()->GetDefaultShader());
shaderStr = AiNodeGetName(context.GetReader()->GetDefaultShader(IsVolume(node, prim)));
} else {
shaderStr = "NULL";
}
Expand Down
7 changes: 7 additions & 0 deletions testsuite/test_2239/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Read UsdVolume asset with specific fieldName

see #2239

author: sebastien.ortega

PARAMS: {'scene': 'test.usda', 'kick_params': '-frame 14 '}
Loading

0 comments on commit c4cd82b

Please sign in to comment.