Skip to content

Commit

Permalink
Adding support for barndoor parameters on the spotlight. (#350)
Browse files Browse the repository at this point in the history
Fixes #332
  • Loading branch information
sirpalee authored and sebastien.ortega committed Apr 7, 2020
1 parent 429fb72 commit 4b5118f
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 11 deletions.
14 changes: 14 additions & 0 deletions render_delegate/constant_strings.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,19 @@ ASTR(angular);
ASTR(aov_pointer);
ASTR(attribute);
ASTR(auto_transparency_depth);
ASTR(barndoor);
ASTR(barndoor_top_left);
ASTR(barndoor_top_right);
ASTR(barndoor_top_edge);
ASTR(barndoor_right_top);
ASTR(barndoor_right_bottom);
ASTR(barndoor_right_edge);
ASTR(barndoor_bottom_left);
ASTR(barndoor_bottom_right);
ASTR(barndoor_bottom_edge);
ASTR(barndoor_left_top);
ASTR(barndoor_left_bottom);
ASTR(barndoor_left_edge);
ASTR(base);
ASTR(base_color);
ASTR(box_filter);
Expand Down Expand Up @@ -105,6 +118,7 @@ ASTR(enable_progressive_render);
ASTR(fallback);
ASTR(file);
ASTR(filename);
ASTR(filters);
ASTR(flat);
ASTR(format);
ASTR(fov);
Expand Down
97 changes: 86 additions & 11 deletions render_delegate/light.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,24 +34,35 @@
#include <vector>

#include "constant_strings.h"
#include "material.h"
#include "utils.h"

PXR_NAMESPACE_OPEN_SCOPE

namespace {

// These tokens are not exposed in 19.5.
// clang-format off
TF_DEFINE_PRIVATE_TOKENS(
_tokens,
// Shaping parameters are not part of HdTokens in older USD versions
((shapingFocus, "shaping:focus"))
((shapingFocusTint, "shaping:focusTint"))
((shapingConeAngle, "shaping:cone:angle"))
((shapingConeSoftness, "shaping:cone:softness"))
((shapingIesFile, "shaping:ies:file"))
((shapingIesAngleScale, "shaping:ies:angleScale"))
((shapingIesNormalize, "shaping:ies:normalize"))
// Barndoor parameters for Houdini
(barndoorbottom)
(barndoorbottomedge)
(barndoorleft)
(barndoorleftedge)
(barndoorright)
(barndoorrightedge)
(barndoortop)
(barndoortopedge)
);
// clang-format on

struct ParamDesc {
ParamDesc(const char* aname, const TfToken& hname) : arnoldName(aname), hdName(hname) {}
Expand Down Expand Up @@ -136,7 +147,8 @@ AtString getLightType(HdSceneDelegate* delegate, const SdfPath& id)
return hasIesFile() ? str::photometric_light : str::point_light;
}

auto spotLightSync = [](AtNode* light, const AtNodeEntry* nentry, const SdfPath& id, HdSceneDelegate* delegate) {
auto spotLightSync = [](AtNode* light, AtNode** filter, const AtNodeEntry* nentry, const SdfPath& id,
HdSceneDelegate* delegate) {
iterateParams(light, nentry, id, delegate, spotParams);

const auto hdAngle = delegate->GetLightParamValue(id, _tokens->shapingConeAngle).GetWithDefault(180.0f);
Expand All @@ -145,27 +157,82 @@ auto spotLightSync = [](AtNode* light, const AtNodeEntry* nentry, const SdfPath&
const auto penumbra = arnoldAngle * softness;
AiNodeSetFlt(light, str::cone_angle, arnoldAngle);
AiNodeSetFlt(light, str::penumbra_angle, penumbra);
// Barndoor parameters are only exposed in houdini for now.
auto hasBarndoor = false;
auto getBarndoor = [&](const TfToken& name) -> float {
const auto barndoor = AiClamp(delegate->GetLightParamValue(id, name).GetWithDefault(0.0f), 0.0f, 1.0f);
if (barndoor > AI_EPSILON) {
hasBarndoor = true;
}
return barndoor;
};
const auto barndoorbottom = getBarndoor(_tokens->barndoorbottom);
const auto barndoorbottomedge = getBarndoor(_tokens->barndoorbottomedge);
const auto barndoorleft = getBarndoor(_tokens->barndoorleft);
const auto barndoorleftedge = getBarndoor(_tokens->barndoorleftedge);
const auto barndoorright = getBarndoor(_tokens->barndoorright);
const auto barndoorrightedge = getBarndoor(_tokens->barndoorrightedge);
const auto barndoortop = getBarndoor(_tokens->barndoortop);
const auto barndoortopedge = getBarndoor(_tokens->barndoortopedge);
auto createBarndoor = [&]() { *filter = AiNode(str::barndoor); };
if (hasBarndoor) {
// We check if the filter is non-zero and if it's a barndoor
if (*filter == nullptr) {
createBarndoor();
} else if (!AiNodeIs(*filter, str::barndoor)) {
AiNodeDestroy(*filter);
createBarndoor();
}
// The edge parameters behave differently in Arnold vs Houdini.
// For bottom left/right and right top/bottom we have to invert the Houdini value.
AiNodeSetFlt(*filter, str::barndoor_bottom_left, 1.0f - barndoorbottom);
AiNodeSetFlt(*filter, str::barndoor_bottom_right, 1.0f - barndoorbottom);
AiNodeSetFlt(*filter, str::barndoor_bottom_edge, barndoorbottomedge);
AiNodeSetFlt(*filter, str::barndoor_left_top, barndoorleft);
AiNodeSetFlt(*filter, str::barndoor_left_bottom, barndoorleft);
AiNodeSetFlt(*filter, str::barndoor_left_edge, barndoorleftedge);
AiNodeSetFlt(*filter, str::barndoor_right_top, 1.0f - barndoorright);
AiNodeSetFlt(*filter, str::barndoor_right_bottom, 1.0f - barndoorright);
AiNodeSetFlt(*filter, str::barndoor_right_edge, barndoorrightedge);
AiNodeSetFlt(*filter, str::barndoor_top_left, barndoortop);
AiNodeSetFlt(*filter, str::barndoor_top_right, barndoortop);
AiNodeSetFlt(*filter, str::barndoor_top_edge, barndoortopedge);
AiNodeSetPtr(light, str::filters, *filter);
} else {
// We disconnect the filter.
AiNodeSetArray(light, str::filters, AiArray(0, 1, AI_TYPE_NODE));
}
};

auto pointLightSync = [](AtNode* light, const AtNodeEntry* nentry, const SdfPath& id, HdSceneDelegate* delegate) {
auto pointLightSync = [](AtNode* light, AtNode** filter, const AtNodeEntry* nentry, const SdfPath& id,
HdSceneDelegate* delegate) {
TF_UNUSED(filter);
iterateParams(light, nentry, id, delegate, pointParams);
};

auto photometricLightSync = [](AtNode* light, const AtNodeEntry* nentry, const SdfPath& id, HdSceneDelegate* delegate) {
auto photometricLightSync = [](AtNode* light, AtNode** filter, const AtNodeEntry* nentry, const SdfPath& id,
HdSceneDelegate* delegate) {
TF_UNUSED(filter);
iterateParams(light, nentry, id, delegate, photometricParams);
};

// Spot lights are sphere lights with shaping parameters

auto distantLightSync = [](AtNode* light, const AtNodeEntry* nentry, const SdfPath& id, HdSceneDelegate* delegate) {
auto distantLightSync = [](AtNode* light, AtNode** filter, const AtNodeEntry* nentry, const SdfPath& id,
HdSceneDelegate* delegate) {
TF_UNUSED(filter);
iterateParams(light, nentry, id, delegate, distantParams);
};

auto diskLightSync = [](AtNode* light, const AtNodeEntry* nentry, const SdfPath& id, HdSceneDelegate* delegate) {
auto diskLightSync = [](AtNode* light, AtNode** filter, const AtNodeEntry* nentry, const SdfPath& id,
HdSceneDelegate* delegate) {
TF_UNUSED(filter);
iterateParams(light, nentry, id, delegate, diskParams);
};

auto rectLightSync = [](AtNode* light, const AtNodeEntry* nentry, const SdfPath& id, HdSceneDelegate* delegate) {
auto rectLightSync = [](AtNode* light, AtNode** filter, const AtNodeEntry* nentry, const SdfPath& id,
HdSceneDelegate* delegate) {
TF_UNUSED(filter);
float width = 1.0f;
float height = 1.0f;
const auto& widthValue = delegate->GetLightParamValue(id, HdLightTokens->width);
Expand All @@ -187,7 +254,9 @@ auto rectLightSync = [](AtNode* light, const AtNodeEntry* nentry, const SdfPath&
AtVector(width, -height, 0.0f), AtVector(-width, -height, 0.0f)));
};

auto cylinderLightSync = [](AtNode* light, const AtNodeEntry* nentry, const SdfPath& id, HdSceneDelegate* delegate) {
auto cylinderLightSync = [](AtNode* light, AtNode** filter, const AtNodeEntry* nentry, const SdfPath& id,
HdSceneDelegate* delegate) {
TF_UNUSED(filter);
iterateParams(light, nentry, id, delegate, cylinderParams);
float length = 1.0f;
const auto& lengthValue = delegate->GetLightParamValue(id, UsdLuxTokens->length);
Expand All @@ -199,7 +268,9 @@ auto cylinderLightSync = [](AtNode* light, const AtNodeEntry* nentry, const SdfP
AiNodeSetVec(light, "top", 0.0f, length, 0.0f);
};

auto domeLightSync = [](AtNode* light, const AtNodeEntry* nentry, const SdfPath& id, HdSceneDelegate* delegate) {
auto domeLightSync = [](AtNode* light, AtNode** filter, const AtNodeEntry* nentry, const SdfPath& id,
HdSceneDelegate* delegate) {
TF_UNUSED(filter);
const auto& formatValue = delegate->GetLightParamValue(id, UsdLuxTokens->textureFormat);
if (formatValue.IsHolding<TfToken>()) {
const auto& textureFormat = formatValue.UncheckedGet<TfToken>();
Expand All @@ -216,7 +287,7 @@ auto domeLightSync = [](AtNode* light, const AtNodeEntry* nentry, const SdfPath&
/// Utility class to translate Hydra lights for th Render Delegate.
class HdArnoldGenericLight : public HdLight {
public:
using SyncParams = void (*)(AtNode*, const AtNodeEntry*, const SdfPath&, HdSceneDelegate*);
using SyncParams = void (*)(AtNode*, AtNode** filter, const AtNodeEntry*, const SdfPath&, HdSceneDelegate*);

/// Internal constructor for creating HdArnoldGenericLight.
///
Expand Down Expand Up @@ -257,6 +328,7 @@ class HdArnoldGenericLight : public HdLight {
HdArnoldRenderDelegate* _delegate; ///< Pointer to the Render Delegate.
AtNode* _light; ///< Pointer to the Arnold Light.
AtNode* _texture = nullptr; ///< Pointer to the Arnold Texture Shader.
AtNode* _filter = nullptr; ///< Pointer to the Arnold Light filter for barndoor effects.
bool _supportsTexture = false; ///< Value indicating texture support.
};

Expand All @@ -279,6 +351,9 @@ HdArnoldGenericLight::~HdArnoldGenericLight()
if (_texture != nullptr) {
AiNodeDestroy(_texture);
}
if (_filter != nullptr) {
AiNodeDestroy(_filter);
}
}

void HdArnoldGenericLight::Sync(HdSceneDelegate* sceneDelegate, HdRenderParam* renderParam, HdDirtyBits* dirtyBits)
Expand Down Expand Up @@ -320,7 +395,7 @@ void HdArnoldGenericLight::Sync(HdSceneDelegate* sceneDelegate, HdRenderParam* r

AiNodeReset(_light);
iterateParams(_light, nentry, id, sceneDelegate, genericParams);
_syncParams(_light, nentry, id, sceneDelegate);
_syncParams(_light, &_filter, nentry, id, sceneDelegate);
if (_supportsTexture) {
SetupTexture(sceneDelegate->GetLightParamValue(id, HdLightTokens->textureFile));
}
Expand Down

0 comments on commit 4b5118f

Please sign in to comment.