Skip to content

Commit

Permalink
Support light primvars (Autodesk#1949)
Browse files Browse the repository at this point in the history
* Support primvars as user data in lights Autodesk#1939

* Support light primvars in the delegate Autodesk#1939

* Also support primvars on custom procedurals
  • Loading branch information
sebastienblor authored Jun 27, 2024
1 parent f3002b6 commit 5e7998d
Show file tree
Hide file tree
Showing 8 changed files with 179 additions and 5 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@

### Feature
- [usd#1814](https://github.com/Autodesk/arnold-usd/issues/1814) - Support skinning on USD curves and points
- [usd#1939](https://github.com/Autodesk/arnold-usd/issues/1939) - Support primvars as user data on lights
- [usd#1950](https://github.com/Autodesk/arnold-usd/issues/1950) - Avoid creating a render delegate in batch mode when ARNOLD_FORCE_ARBORT_ON_LICENSE_FAIL is set and the license isn't found.
- [usd#1918](https://github.com/Autodesk/arnold-usd/issues/1918) - Use batch render sessions for husk renders


### Bug fixes
- [usd#1861](https://github.com/Autodesk/arnold-usd/issues/1861) - Fix BasisCurves disappearing on interactive updates
- [usd#1927](https://github.com/Autodesk/arnold-usd/issues/1927) - Fix procedural updates during iteractive changes of non-leaf primitives
Expand Down
31 changes: 30 additions & 1 deletion libs/render_delegate/light.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,25 @@ void iterateParams(
}
}

void readUserData(
AtNode* light, const SdfPath& id, HdSceneDelegate* delegate, HdArnoldRenderDelegate* renderDelegate)
{
HdArnoldPrimvarMap primvars;
std::vector<HdInterpolation> interpolations = {HdInterpolationConstant};
HdDirtyBits dirtyBits = HdChangeTracker::Clean; // this value doesn't seem to be used in HdArnoldGetPrimvars
HdArnoldGetPrimvars(delegate, id, dirtyBits, false, primvars, &interpolations);
for (const auto &p : primvars) {
// Get the parameter name, removing the arnold:prefix if any
std::string paramName(TfStringStartsWith(p.first.GetString(), str::arnold) ? p.first.GetString().substr(7) : p.first.GetString());
const auto* pentry = AiNodeEntryLookUpParameter(AiNodeGetNodeEntry(light), AtString(paramName.c_str()));
if (pentry) {
HdArnoldSetParameter(light, pentry, p.second.value, renderDelegate);
} else {
HdArnoldSetConstantPrimvar(light, TfToken(paramName), p.second.role, p.second.value, nullptr,
nullptr, nullptr, renderDelegate);
}
}
}
AtString getLightType(HdSceneDelegate* delegate, const SdfPath& id)
{
auto isDefault = [&](const TfToken& paramName, float defaultVal) -> bool {
Expand Down Expand Up @@ -291,6 +310,7 @@ auto spotLightSync = [](AtNode* light, AtNode** filter, const AtNodeEntry* nentr
// We disconnect the filter.
AiNodeSetArray(light, str::filters, AiArray(0, 1, AI_TYPE_NODE));
}
readUserData(light, id, sceneDelegate, renderDelegate);
};

auto pointLightSync = [](AtNode* light, AtNode** filter, const AtNodeEntry* nentry, const SdfPath& id,
Expand All @@ -307,12 +327,14 @@ auto pointLightSync = [](AtNode* light, AtNode** filter, const AtNodeEntry* nent
} else {
iterateParams(light, nentry, id, sceneDelegate, renderDelegate, pointParams);
}
readUserData(light, id, sceneDelegate, renderDelegate);
};

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

// Spot lights are sphere lights with shaping parameters
Expand All @@ -321,6 +343,7 @@ auto distantLightSync = [](AtNode* light, AtNode** filter, const AtNodeEntry* ne
HdSceneDelegate* sceneDelegate, HdArnoldRenderDelegate* renderDelegate) {
TF_UNUSED(filter);
iterateParams(light, nentry, id, sceneDelegate, renderDelegate, distantParams);
readUserData(light, id, sceneDelegate, renderDelegate);
// For distant lights, we want to ignore the normalize attribute, as it's not behaving
// as expected in arnold (see #1191)
AiNodeResetParameter(light, str::normalize);
Expand All @@ -330,6 +353,7 @@ auto diskLightSync = [](AtNode* light, AtNode** filter, const AtNodeEntry* nentr
HdSceneDelegate* sceneDelegate, HdArnoldRenderDelegate* renderDelegate) {
TF_UNUSED(filter);
iterateParams(light, nentry, id, sceneDelegate, renderDelegate, diskParams);
readUserData(light, id, sceneDelegate, renderDelegate);
};

auto rectLightSync = [](AtNode* light, AtNode** filter, const AtNodeEntry* nentry, const SdfPath& id,
Expand Down Expand Up @@ -362,6 +386,8 @@ auto rectLightSync = [](AtNode* light, AtNode** filter, const AtNodeEntry* nentr
AiArray(
4, 1, AI_TYPE_VECTOR, AtVector(width, -height, 0.0f), AtVector(-width, -height, 0.0f),
AtVector(-width, height, 0.0f), AtVector(width, height, 0.0f)));

readUserData(light, id, sceneDelegate, renderDelegate);
};

auto geometryLightSync = [](AtNode* light, AtNode** filter, const AtNodeEntry* nentry, const SdfPath& id,
Expand All @@ -376,7 +402,8 @@ auto geometryLightSync = [](AtNode* light, AtNode** filter, const AtNodeEntry* n
if (mesh != nullptr && !AiNodeIs(mesh, str::polymesh))
mesh = nullptr;
AiNodeSetPtr(light, str::mesh,(void*) mesh);
}
}
readUserData(light, id, sceneDelegate, renderDelegate);
};

auto cylinderLightSync = [](AtNode* light, AtNode** filter, const AtNodeEntry* nentry, const SdfPath& id,
Expand All @@ -395,6 +422,7 @@ auto cylinderLightSync = [](AtNode* light, AtNode** filter, const AtNodeEntry* n
length /= 2.0f;
AiNodeSetVec(light, str::bottom, -length, 0.0f, 0.0f);
AiNodeSetVec(light, str::top, length, 0.0f, 0.0f);
readUserData(light, id, sceneDelegate, renderDelegate);
};

auto domeLightSync = [](AtNode* light, AtNode** filter, const AtNodeEntry* nentry, const SdfPath& id,
Expand All @@ -415,6 +443,7 @@ auto domeLightSync = [](AtNode* light, AtNode** filter, const AtNodeEntry* nentr
AiNodeSetStr(light, str::format, str::angular); // default value
}
}
readUserData(light, id, sceneDelegate, renderDelegate);
};

/// Utility class to translate Hydra lights for th Render Delegate.
Expand Down
4 changes: 2 additions & 2 deletions libs/render_delegate/procedural_custom.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ void HdArnoldProceduralCustom::Sync(HdSceneDelegate *delegate,
//ConvertPrimvarToBuiltinParameter(_node, TfToken(paramName.c_str()), p.second.value, &_visibilityFlags, &_sidednessFlags, nullptr);
HdArnoldSetParameter(_node, pentry, p.second.value, _renderDelegate);
} else {
// TODO: Should we declare the primvars in that case ?? they are not known by the node but might be used by shaders
// if (HdArnoldDeclare(node, TfToken(paramName), const TfToken& scope, const TfToken& type)) {}
HdArnoldSetConstantPrimvar(_node, TfToken(paramName), p.second.role, p.second.value, nullptr,
nullptr, nullptr, _renderDelegate);
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions libs/translator/reader/read_light.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ AtNode* UsdArnoldReadDistantLight::Read(const UsdPrim &prim, UsdArnoldReaderCont
_ReadLightCommon(prim, node, time);
ReadMatrix(prim, node, time, context);
ReadArnoldParameters(prim, context, node, time, "primvars:arnold");
ReadPrimvars(prim, node, time, context);

// Check the primitive visibility, set the intensity to 0 if it's meant to be hidden
if (!context.GetPrimVisibility(prim, time.frame))
Expand Down Expand Up @@ -369,6 +370,7 @@ AtNode* UsdArnoldReadDomeLight::Read(const UsdPrim &prim, UsdArnoldReaderContext

ReadMatrix(prim, node, time, context);
ReadArnoldParameters(prim, context, node, time, "primvars:arnold");
ReadPrimvars(prim, node, time, context);

// Check the primitive visibility, set the intensity to 0 if it's meant to be hidden
if (!context.GetPrimVisibility(prim, time.frame))
Expand Down Expand Up @@ -401,6 +403,7 @@ AtNode* UsdArnoldReadDiskLight::Read(const UsdPrim &prim, UsdArnoldReaderContext

ReadMatrix(prim, node, time, context);
ReadArnoldParameters(prim, context, node, time, "primvars:arnold");
ReadPrimvars(prim, node, time, context);

// Check the primitive visibility, set the intensity to 0 if it's meant to be hidden
if (!context.GetPrimVisibility(prim, time.frame))
Expand Down Expand Up @@ -441,6 +444,7 @@ AtNode* UsdArnoldReadSphereLight::Read(const UsdPrim &prim, UsdArnoldReaderConte

ReadMatrix(prim, node, time, context);
ReadArnoldParameters(prim, context, node, time, "primvars:arnold");
ReadPrimvars(prim, node, time, context);

// Check the primitive visibility, set the intensity to 0 if it's meant to be hidden
if (!context.GetPrimVisibility(prim, time.frame))
Expand Down Expand Up @@ -513,6 +517,7 @@ AtNode* UsdArnoldReadRectLight::Read(const UsdPrim &prim, UsdArnoldReaderContext

ReadMatrix(prim, node, time, context);
ReadArnoldParameters(prim, context, node, time, "primvars:arnold");
ReadPrimvars(prim, node, time, context);

// Check the primitive visibility, set the intensity to 0 if it's meant to be hidden
if (!context.GetPrimVisibility(prim, time.frame))
Expand Down Expand Up @@ -548,6 +553,7 @@ AtNode* UsdArnoldReadCylinderLight::Read(const UsdPrim &prim, UsdArnoldReaderCon
}
ReadMatrix(prim, node, time, context);
ReadArnoldParameters(prim, context, node, time, "primvars:arnold");
ReadPrimvars(prim, node, time, context);
_ReadLightLinks(prim, node, context);
ReadLightShaders(prim, prim.GetAttribute(_tokens->PrimvarsArnoldShaders), node, context);
return node;
Expand Down Expand Up @@ -600,6 +606,7 @@ AtNode* UsdArnoldReadGeometryLight::Read(const UsdPrim &prim, UsdArnoldReaderCon

ReadMatrix(prim, node, time, context);
ReadArnoldParameters(prim, context, node, time, "primvars:arnold");
ReadPrimvars(prim, node, time, context);

// Check the primitive visibility, set the intensity to 0 if it's meant to be hidden
if (!context.GetPrimVisibility(prim, time.frame))
Expand Down
2 changes: 1 addition & 1 deletion testsuite/groups
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ darwin:
#######################
# Tests that can be run in hydra mode

hydra: test_0000 test_0001 test_0002 test_0003 test_0004 test_0005 test_0006 test_0007 test_0008 test_0009 test_0010 test_0011 test_0012 test_0014 test_0016 test_0017 test_0018 test_0019 test_0020 test_0021 test_0022 test_0023 test_0024 test_0025 test_0026 test_0027 test_0028 test_0029 test_0030 test_0031 test_0032 test_0033 test_0034 test_0037 test_0038 test_0041 test_0046 test_0048 test_0049 test_0050 test_0051 test_0052 test_0055 test_0056 test_0057 test_0058 test_0059 test_0060 test_0062 test_0064 test_0066 test_0067 test_0068 test_0071 test_0072 test_0073 test_0074 test_0077 test_0080 test_0081 test_0082 test_0083 test_0084 test_0086 test_0087 test_0088 test_0091 test_0093 test_0094 test_0097 test_0099 test_0104 test_0105 test_0107 test_0108 test_0110 test_0112 test_0113 test_0114 test_0115 test_0117 test_0120 test_0121 test_0122 test_0123 test_0125 test_0126 test_0127 test_0128 test_0129 test_0130 test_0132 test_0133 test_0135 test_0139 test_0140 test_0141 test_0142 test_0143 test_0144 test_0145 test_0148 test_0149 test_0150 test_0151 test_0158 test_0159 test_0160 test_0161 test_0162 test_0163 test_0164 test_0165 test_0166 test_0168 test_0169 test_0170 test_0171 test_0172 test_0173 test_0174 test_0175 test_0177 test_0178 test_0180 test_0183 test_0184 test_0186 test_0187 test_0188 test_0189 test_0191 test_0194 test_0195 test_0196 test_0197 test_0198 test_0200 test_0201 test_0202 test_0204 test_0205 test_0206 test_0207 test_0215 test_0216 test_0217 test_0219 test_0220 test_0221 test_0222 test_0223 test_0225 test_0227 test_0228 test_0229 test_0230 test_0231 test_0232 test_0233 test_0234 test_0238 test_0239 test_0240 test_0242 test_0243 test_0244 test_0245 test_0299 test_0316 test_0739 test_1181 test_1204 test_1209 test_1223 test_1225 test_1238 test_1245 test_1262 test_1294 test_1309 test_1311 test_1313 test_1329 test_1333 test_1334 test_1346 test_1354 test_1416 test_1420 test_1426 test_1427.1 test_1427.2 test_1427.3 test_1430 test_1433 test_1435 test_1438 test_1442 test_1457 test_1486 test_1499 test_1524 test_1525 test_1530 test_1535 test_1538 test_1546 test_1547.1 test_1547.2 test_1550 test_1567 test_1588 test_1590 test_1593 test_1607 test_1613 test_1625 test_1632 test_1635 test_1654 test_1657 test_1678 test_1705 test_1718 test_1726 test_1730 test_1735 test_1769 test_1772 test_1776 test_1814 test_1868 test_1873 test_1878 test_1881 test_1894 test_1906 test_1923 test_1940 test_14028
hydra: test_0000 test_0001 test_0002 test_0003 test_0004 test_0005 test_0006 test_0007 test_0008 test_0009 test_0010 test_0011 test_0012 test_0014 test_0016 test_0017 test_0018 test_0019 test_0020 test_0021 test_0022 test_0023 test_0024 test_0025 test_0026 test_0027 test_0028 test_0029 test_0030 test_0031 test_0032 test_0033 test_0034 test_0037 test_0038 test_0041 test_0046 test_0048 test_0049 test_0050 test_0051 test_0052 test_0055 test_0056 test_0057 test_0058 test_0059 test_0060 test_0062 test_0064 test_0066 test_0067 test_0068 test_0071 test_0072 test_0073 test_0074 test_0077 test_0080 test_0081 test_0082 test_0083 test_0084 test_0086 test_0087 test_0088 test_0091 test_0093 test_0094 test_0097 test_0099 test_0104 test_0105 test_0107 test_0108 test_0110 test_0112 test_0113 test_0114 test_0115 test_0117 test_0120 test_0121 test_0122 test_0123 test_0125 test_0126 test_0127 test_0128 test_0129 test_0130 test_0132 test_0133 test_0135 test_0139 test_0140 test_0141 test_0142 test_0143 test_0144 test_0145 test_0148 test_0149 test_0150 test_0151 test_0158 test_0159 test_0160 test_0161 test_0162 test_0163 test_0164 test_0165 test_0166 test_0168 test_0169 test_0170 test_0171 test_0172 test_0173 test_0174 test_0175 test_0177 test_0178 test_0180 test_0183 test_0184 test_0186 test_0187 test_0188 test_0189 test_0191 test_0194 test_0195 test_0196 test_0197 test_0198 test_0200 test_0201 test_0202 test_0204 test_0205 test_0206 test_0207 test_0215 test_0216 test_0217 test_0219 test_0220 test_0221 test_0222 test_0223 test_0225 test_0227 test_0228 test_0229 test_0230 test_0231 test_0232 test_0233 test_0234 test_0238 test_0239 test_0240 test_0242 test_0243 test_0244 test_0245 test_0299 test_0316 test_0739 test_1181 test_1204 test_1209 test_1223 test_1225 test_1238 test_1245 test_1262 test_1294 test_1309 test_1311 test_1313 test_1329 test_1333 test_1334 test_1346 test_1354 test_1416 test_1420 test_1426 test_1427.1 test_1427.2 test_1427.3 test_1430 test_1433 test_1435 test_1438 test_1442 test_1457 test_1486 test_1499 test_1524 test_1525 test_1530 test_1535 test_1538 test_1546 test_1547.1 test_1547.2 test_1550 test_1567 test_1588 test_1590 test_1593 test_1607 test_1613 test_1625 test_1632 test_1635 test_1654 test_1657 test_1678 test_1705 test_1718 test_1726 test_1730 test_1735 test_1769 test_1772 test_1776 test_1814 test_1868 test_1873 test_1878 test_1881 test_1894 test_1906 test_1923 test_1939 test_1940 test_14028

# Tests in this group will never be executed (you can use it to temporarily disable some tests and/or groups)
ignore:
Expand Down
6 changes: 6 additions & 0 deletions testsuite/test_1939/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Support user data in lights

see #1939

author: sebastien.ortega

55 changes: 55 additions & 0 deletions testsuite/test_1939/data/scene.usda
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#usda 1.0
(
endTimeCode = 1
framesPerSecond = 24
metersPerUnit = 1
startTimeCode = 1
timeCodesPerSecond = 24
upAxis = "Y"
)

def DomeLight "dome"
{
int primvars:one_value = 1
float primvars:two_value = 2.0
color3f primvars:color_value = (0, 0, 1)
float primvars:arnold:intensity = 0.5
}
def DistantLight "distant"
{
int primvars:one_value = 1
float primvars:two_value = 2.0
color3f primvars:color_value = (0, 0, 1)
float primvars:arnold:intensity = 0.5
}

def DiskLight "disk"
{
int primvars:one_value = 1
float primvars:two_value = 2.0
color3f primvars:color_value = (0, 0, 1)
float primvars:arnold:intensity = 0.5
}
def CylinderLight "cylinder"
{
int primvars:one_value = 1
float primvars:two_value = 2.0
color3f primvars:color_value = (0, 0, 1)
float primvars:arnold:intensity = 0.5
}
def RectLight "rect"
{
int primvars:one_value = 1
float primvars:two_value = 2.0
color3f primvars:color_value = (0, 0, 1)
float primvars:arnold:intensity = 0.5
}

def SphereLight "sphere"
{
int primvars:one_value = 1
float primvars:two_value = 2.0
color3f primvars:color_value = (0, 0, 1)
float primvars:arnold:intensity = 0.5
}

77 changes: 77 additions & 0 deletions testsuite/test_1939/data/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#include <ai.h>

#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>

bool CheckUserData(const char *name)
{
AtNode *node = AiNodeLookUpByName(nullptr, AtString(name));
if (node == nullptr)
return false;

const AtString s_intAttr("one_value");
const AtString s_fltAttr("two_value");
const AtString s_colorAttr("color_value");
const AtString s_intensityAttr("intensity");

if (!AiNodeLookUpUserParameter (node, s_intAttr))
return false;
int intVal = AiNodeGetInt(node, s_intAttr);
if (intVal != 1)
return false;

if (!AiNodeLookUpUserParameter (node, s_fltAttr))
return false;
float fltVal = AiNodeGetFlt(node, s_fltAttr);
if (fltVal != 2)
return false;

if (!AiNodeLookUpUserParameter (node, s_colorAttr))
return false;
AtRGB colorVal = AiNodeGetRGB(node, s_colorAttr);
static AtRGB blue(0.f, 0.f, 1.f);
if (colorVal != blue)
return false;

float intensity = AiNodeGetFlt(node, s_intensityAttr);
if (intensity != 0.5f)
return false;


return true;
}

int main(int argc, char **argv)
{
AiBegin();
AiMsgSetConsoleFlags(nullptr, AI_LOG_ALL);
AtParamValueMap* params = AiParamValueMap();
AiSceneLoad(nullptr, "scene.usda", nullptr);
AiSceneWrite(nullptr, "scene.ass", params);
AiParamValueMapDestroy(params);
AiEnd();

AiBegin();
AiSceneLoad(nullptr, "scene.ass", nullptr);

bool success = true;
AtNode *dome = AiNodeLookUpByName(nullptr, AtString("/dome"));

success &= CheckUserData("/dome");
success &= CheckUserData("/distant");
success &= CheckUserData("/disk");
success &= CheckUserData("/rect");
success &= CheckUserData("/sphere");
success &= CheckUserData("/cylinder");
AiEnd();
return (success) ? 0 : 1;
}







0 comments on commit 5e7998d

Please sign in to comment.