Skip to content

Commit

Permalink
Support shader connections to mesh lights (Autodesk#1295)
Browse files Browse the repository at this point in the history
* Support shader connections to mesh lights in the delegate Autodesk#1294

* Add shader connections to mesh lights in the procedural Autodesk#1294
  • Loading branch information
sebastienblor authored Oct 2, 2022
1 parent 097cfaf commit f863e2f
Show file tree
Hide file tree
Showing 11 changed files with 492 additions and 112 deletions.
66 changes: 37 additions & 29 deletions render_delegate/light.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -624,38 +624,12 @@ void HdArnoldGenericLight::Sync(HdSceneDelegate* sceneDelegate, HdRenderParam* r
}
AiNodeSetDisabled(_light, !sceneDelegate->GetVisible(id));

// get the sdf path for the light shader arnold node graph container
SdfPath lightShaderPath;
ArnoldUsdCheckForSdfPathValue(sceneDelegate->GetLightParamValue(id, TfToken("primvars:arnold:shaders")),
[&](const SdfPath& p) { lightShaderPath = p; });
SdfPath lightShaderPath = HdArnoldLight::ComputeLightShaders(sceneDelegate, id, TfToken("primvars:arnold:shaders"), _light);

AtNode *color = nullptr;
std::vector<AtNode *> lightFilters;
HdArnoldRenderDelegate::PathSet pathSet;

if (!lightShaderPath.IsEmpty()) {
if (!lightShaderPath.IsEmpty())
pathSet.insert(lightShaderPath);
const HdArnoldNodeGraph *nodeGraph = HdArnoldNodeGraph::GetNodeGraph(&sceneDelegate->GetRenderIndex(), lightShaderPath);
if (nodeGraph) {
color = nodeGraph->GetTerminal(str::t_color);
if (color) {
// Only certain types of light can be linked
if (AiNodeIs(_light, str::skydome_light) ||
AiNodeIs(_light, str::quad_light) ||
AiNodeIs(_light, str::mesh_light)) {
AiNodeLink(color, str::color, _light);
} else {
AiMsgWarning("%s : Cannot connect shader to light's color for \"%s\"", AiNodeGetName(_light), AiNodeEntryGetName(AiNodeGetNodeEntry(_light)));
}
}

lightFilters = nodeGraph->GetTerminals(_tokens->filtersArray);
if (!lightFilters.empty()) {
AiNodeSetArray(_light, str::filters, AiArrayConvert(static_cast<uint32_t>(lightFilters.size()), 1,
AI_TYPE_NODE, lightFilters.data()));
}
}
}

// If we previously had node graph connected, we need to call TrackDependencies
// even if our list is empty. This is needed to clear the previous dependencies
if (_hasNodeGraphs || !pathSet.empty()) {
Expand Down Expand Up @@ -782,6 +756,40 @@ AtNode* GetLightNode(const HdLight* light)
return static_cast<const HdArnoldGenericLight*>(light)->GetLightNode();
}

SdfPath ComputeLightShaders(HdSceneDelegate* sceneDelegate, const SdfPath &id, const TfToken &attr, AtNode *light )
{
// get the sdf path for the light shader arnold node graph container
SdfPath lightShaderPath;
ArnoldUsdCheckForSdfPathValue(sceneDelegate->GetLightParamValue(id, attr),
[&](const SdfPath& p) { lightShaderPath = p; });

AtNode *color = nullptr;
std::vector<AtNode *> lightFilters;
if (!lightShaderPath.IsEmpty()) {
const HdArnoldNodeGraph *nodeGraph = HdArnoldNodeGraph::GetNodeGraph(&sceneDelegate->GetRenderIndex(), lightShaderPath);
if (nodeGraph) {
color = nodeGraph->GetTerminal(str::t_color);
if (color) {
// Only certain types of light can be linked
if (AiNodeIs(light, str::skydome_light) ||
AiNodeIs(light, str::quad_light) ||
AiNodeIs(light, str::mesh_light)) {
AiNodeLink(color, str::color, light);
} else {
AiMsgWarning("%s : Cannot connect shader to light's color for \"%s\"", AiNodeGetName(light), AiNodeEntryGetName(AiNodeGetNodeEntry(light)));
}
}

lightFilters = nodeGraph->GetTerminals(_tokens->filtersArray);
if (!lightFilters.empty()) {
AiNodeSetArray(light, str::filters, AiArrayConvert(static_cast<uint32_t>(lightFilters.size()), 1,
AI_TYPE_NODE, lightFilters.data()));
}
}
}
return lightShaderPath;
}

} // namespace HdArnoldLight

PXR_NAMESPACE_CLOSE_SCOPE
2 changes: 2 additions & 0 deletions render_delegate/light.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ HdLight* CreateGeometryLight(HdArnoldRenderDelegate* renderDelegate, const SdfPa
/// @return Pointer to the Arnold Light, can be nullptr.
AtNode* GetLightNode(const HdLight* light);

SdfPath ComputeLightShaders(HdSceneDelegate* sceneDelegate, const SdfPath &id, const TfToken &attr, AtNode *light);

} // namespace HdArnoldLight

PXR_NAMESPACE_CLOSE_SCOPE
14 changes: 11 additions & 3 deletions render_delegate/mesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "mesh.h"
#include "light.h"

#include <pxr/base/gf/vec2f.h>
#include <pxr/imaging/pxOsd/tokens.h>
Expand Down Expand Up @@ -363,6 +364,7 @@ void HdArnoldMesh::Sync(
// to trigger the creation of the mesh light
if (primvar.first == str::t_arnold_light)
continue;

std::string primvarStr = primvar.first.GetText();
const static std::string s_lightPrefix = "arnold:light:";
// check if the attribute starts with "arnold:light:"
Expand All @@ -371,9 +373,15 @@ void HdArnoldMesh::Sync(
// we want to read this attribute and set it in the light node. We need to
// modify the attribute name so that we remove the light prefix
primvarStr.erase(7, 6);
HdArnoldSetConstantPrimvar(
_geometryLight, TfToken(primvarStr.c_str()), desc.role, desc.value,
nullptr, nullptr, nullptr);

if (primvarStr == "arnold:shaders") {
HdArnoldLight::ComputeLightShaders(sceneDelegate, id,
TfToken("primvars:arnold:light:shaders"), meshLight);
} else {
HdArnoldSetConstantPrimvar(
_geometryLight, TfToken(primvarStr.c_str()), desc.role, desc.value,
nullptr, nullptr, nullptr);
}
continue;
}
}
Expand Down
7 changes: 7 additions & 0 deletions testsuite/test_1294/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Support shader connections to mesh lights

See #1294

author: sebastien ortega

PARAMS: {'scene':'scene.usda'}
115 changes: 115 additions & 0 deletions testsuite/test_1294/data/scene.usda

Large diffs are not rendered by default.

Loading

0 comments on commit f863e2f

Please sign in to comment.