18#include <pxr/imaging/hd/sceneDelegate.h>
19#include <pxr/usd/sdf/assetPath.h>
32 : HdLight(sprimId), _lightType(lightType)
40 return DirtyBits::DirtyTransform | DirtyBits::DirtyParams;
44 HdRenderParam *renderParam,
45 HdDirtyBits *dirtyBits)
47 if (*dirtyBits == DirtyBits::Clean) {
51 Initialize(renderParam);
56 const SdfPath &
id = GetId();
58 if (*dirtyBits & DirtyBits::DirtyTransform) {
59 const float metersPerUnit =
63#if PXR_VERSION >= 2011
67 sceneDelegate->GetLightParamValue(
id, HdTokens->transform)
70 _object->set_tfm(tfm);
73 if (*dirtyBits & DirtyBits::DirtyParams) {
76 value = sceneDelegate->GetLightParamValue(
id, HdLightTokens->color);
77 if (!value.IsEmpty()) {
78 const auto color = value.Get<GfVec3f>();
79 strength =
make_float3(color[0], color[1], color[2]);
82 value = sceneDelegate->GetLightParamValue(
id, HdLightTokens->exposure);
83 if (!value.IsEmpty()) {
84 strength *=
exp2(value.Get<
float>());
87 value = sceneDelegate->GetLightParamValue(
id, HdLightTokens->intensity);
88 if (!value.IsEmpty()) {
89 strength *= value.Get<
float>();
92 if (_lightType == HdPrimTypeTokens->distantLight) {
101 value = sceneDelegate->GetLightParamValue(
id, HdLightTokens->normalize);
102 _light->set_normalize(value.IsHolding<
bool>() && value.UncheckedGet<
bool>());
104 value = sceneDelegate->GetLightParamValue(
id, _tokens->visibleInPrimaryRay);
105 if (!value.IsEmpty()) {
106 if (value.Get<
bool>()) {
114 value = sceneDelegate->GetLightParamValue(
id, HdLightTokens->shadowEnable);
115 if (!value.IsEmpty()) {
116 _light->set_cast_shadow(value.Get<
bool>());
119 if (_lightType == HdPrimTypeTokens->distantLight) {
120 value = sceneDelegate->GetLightParamValue(
id, HdLightTokens->angle);
121 if (!value.IsEmpty()) {
122 _light->set_angle(GfDegreesToRadians(value.Get<
float>()));
125 else if (_lightType == HdPrimTypeTokens->diskLight) {
126 value = sceneDelegate->GetLightParamValue(
id, HdLightTokens->radius);
127 if (!value.IsEmpty()) {
128 const float size = value.Get<
float>() * 2.0f;
129 _light->set_sizeu(
size);
130 _light->set_sizev(
size);
133 else if (_lightType == HdPrimTypeTokens->rectLight) {
134 value = sceneDelegate->GetLightParamValue(
id, HdLightTokens->width);
135 if (!value.IsEmpty()) {
136 _light->set_sizeu(value.Get<
float>());
139 value = sceneDelegate->GetLightParamValue(
id, HdLightTokens->height);
140 if (!value.IsEmpty()) {
141 _light->set_sizev(value.Get<
float>());
144 else if (_lightType == HdPrimTypeTokens->sphereLight) {
145 value = sceneDelegate->GetLightParamValue(
id, TfToken(
"treatAsPoint"));
146 if (!value.IsEmpty() && value.Get<
bool>()) {
147 _light->set_size(0.0f);
150 value = sceneDelegate->GetLightParamValue(
id, HdLightTokens->radius);
151 if (!value.IsEmpty()) {
152 _light->set_size(value.Get<
float>());
156 bool shaping =
false;
158 value = sceneDelegate->GetLightParamValue(
id, HdLightTokens->shapingConeAngle);
159 if (!value.IsEmpty()) {
160 _light->set_spot_angle(GfDegreesToRadians(value.Get<
float>()) * 2.0f);
164 value = sceneDelegate->GetLightParamValue(
id, HdLightTokens->shapingConeSoftness);
165 if (!value.IsEmpty()) {
166 _light->set_spot_smooth(value.Get<
float>());
173 const bool visible = sceneDelegate->GetVisible(
id);
180 _light->set_strength(strength);
181 _light->set_is_enabled(visible);
183 PopulateShaderGraph(sceneDelegate);
186 else if (_object->tfm_is_modified() && (_lightType == HdPrimTypeTokens->domeLight ||
187 _light->get_shader()->has_surface_spatial_varying))
189 PopulateShaderGraph(sceneDelegate);
192 if (_light->is_modified()) {
193 _light->tag_update(
lock.scene);
196 *dirtyBits = DirtyBits::Clean;
199void HdCyclesLight::PopulateShaderGraph(HdSceneDelegate *sceneDelegate)
204 if (_lightType == HdPrimTypeTokens->domeLight) {
207 bgNode->set_color(_light->get_strength());
209 graph->connect(bgNode->
output(
"Background"), graph->output()->input(
"Surface"));
213 else if (sceneDelegate !=
nullptr) {
215 const SdfPath &
id = GetId();
216 value = sceneDelegate->GetLightParamValue(
id, TfToken(
"falloff"));
217 if (!value.IsEmpty()) {
218 const std::string strVal = value.Get<
string>();
219 if (strVal ==
"Constant" || strVal ==
"Linear" || strVal ==
"Quadratic") {
220 LightFalloffNode *lfoNode = graph->create_node<LightFalloffNode>();
221 lfoNode->set_strength(1.f);
222 graph->connect(lfoNode->
output(strVal.c_str()), graph->output()->input(
"Surface"));
223 outputNode = lfoNode;
228 if (outputNode ==
nullptr) {
229 EmissionNode *emissionNode = graph->create_node<EmissionNode>();
231 emissionNode->set_strength(1.0f);
233 graph->connect(emissionNode->
output(
"Emission"), graph->output()->input(
"Surface"));
235 outputNode = emissionNode;
239 const SdfPath &
id = GetId();
240 bool hasSpatialVarying =
false;
241 bool hasColorTemperature =
false;
243 if (sceneDelegate !=
nullptr) {
244 value = sceneDelegate->GetLightParamValue(
id, HdLightTokens->enableColorTemperature);
245 const bool enableColorTemperature = value.IsHolding<
bool>() && value.UncheckedGet<
bool>();
247 if (enableColorTemperature) {
248 value = sceneDelegate->GetLightParamValue(
id, HdLightTokens->colorTemperature);
249 if (value.IsHolding<
float>()) {
250 BlackbodyNode *blackbodyNode = graph->create_node<BlackbodyNode>();
251 blackbodyNode->set_temperature(value.UncheckedGet<
float>());
253 if (_lightType == HdPrimTypeTokens->domeLight) {
254 VectorMathNode *mathNode = graph->create_node<VectorMathNode>();
256 mathNode->set_vector2(_light->get_strength());
258 graph->connect(blackbodyNode->
output(
"Color"), mathNode->
input(
"Vector1"));
259 graph->connect(mathNode->
output(
"Vector"), outputNode->
input(
"Color"));
262 graph->connect(blackbodyNode->
output(
"Color"), outputNode->
input(
"Color"));
265 hasColorTemperature =
true;
269 value = sceneDelegate->GetLightParamValue(
id, HdLightTokens->shapingIesFile);
270 if (value.IsHolding<SdfAssetPath>()) {
271 std::string filename = value.UncheckedGet<SdfAssetPath>().GetResolvedPath();
272 if (filename.empty()) {
273 filename = value.UncheckedGet<SdfAssetPath>().GetAssetPath();
276 TextureCoordinateNode *coordNode = graph->create_node<TextureCoordinateNode>();
277 coordNode->set_ob_tfm(_object->get_tfm());
278 coordNode->set_use_transform(
true);
280 IESLightNode *iesNode = graph->create_node<IESLightNode>();
281 iesNode->set_filename(ustring(filename));
283 graph->connect(coordNode->
output(
"Normal"), iesNode->
input(
"Vector"));
284 graph->connect(iesNode->
output(
"Fac"), outputNode->
input(
"Strength"));
286 hasSpatialVarying =
true;
289 value = sceneDelegate->GetLightParamValue(
id, HdLightTokens->textureFile);
290 if (value.IsHolding<SdfAssetPath>()) {
291 std::string filename = value.UncheckedGet<SdfAssetPath>().GetResolvedPath();
292 if (filename.empty()) {
293 filename = value.UncheckedGet<SdfAssetPath>().GetAssetPath();
296 ImageSlotTextureNode *textureNode =
nullptr;
297 if (_lightType == HdPrimTypeTokens->domeLight) {
301 TextureCoordinateNode *coordNode = graph->create_node<TextureCoordinateNode>();
302 coordNode->set_ob_tfm(tfm);
303 coordNode->set_use_transform(
true);
305 textureNode = graph->create_node<EnvironmentTextureNode>();
306 static_cast<EnvironmentTextureNode *
>(textureNode)->set_filename(ustring(filename));
308 graph->connect(coordNode->
output(
"Object"), textureNode->
input(
"Vector"));
310 hasSpatialVarying =
true;
313 GeometryNode *coordNode = graph->create_node<GeometryNode>();
315 textureNode = graph->create_node<ImageTextureNode>();
316 static_cast<ImageTextureNode *
>(textureNode)->set_filename(ustring(filename));
318 graph->connect(coordNode->
output(
"Parametric"), textureNode->
input(
"Vector"));
321 if (hasColorTemperature) {
322 VectorMathNode *mathNode = graph->create_node<VectorMathNode>();
325 graph->connect(textureNode->
output(
"Color"), mathNode->
input(
"Vector1"));
326 ShaderInput *
const outputNodeInput = outputNode->
input(
"Color");
327 graph->connect(outputNodeInput->
link, mathNode->
input(
"Vector2"));
328 graph->disconnect(outputNodeInput);
329 graph->connect(mathNode->
output(
"Vector"), outputNodeInput);
331 else if (_lightType == HdPrimTypeTokens->domeLight) {
332 VectorMathNode *mathNode = graph->create_node<VectorMathNode>();
334 mathNode->set_vector2(_light->get_strength());
336 graph->connect(textureNode->
output(
"Color"), mathNode->
input(
"Vector1"));
337 graph->connect(mathNode->
output(
"Vector"), outputNode->
input(
"Color"));
340 graph->connect(textureNode->
output(
"Color"), outputNode->
input(
"Color"));
345 Shader *
const shader = _light->get_shader();
359 const bool keep_nodes =
static_cast<const HdCyclesSession *
>(renderParam)->keep_nodes;
362 lock.scene->delete_node(_light);
363 lock.scene->delete_node(_object);
370void HdCyclesLight::Initialize(HdRenderParam *renderParam)
376 const SceneLock
lock(renderParam);
379 _object->
name = GetId().GetString();
381 _light =
lock.scene->create_node<
Light>();
382 _light->
name = GetId().GetString();
383 _object->set_geometry(_light);
387 if (_lightType == HdPrimTypeTokens->domeLight) {
390 else if (_lightType == HdPrimTypeTokens->distantLight) {
393 else if (_lightType == HdPrimTypeTokens->diskLight) {
395 _light->set_ellipse(
true);
396 _light->set_size(1.0f);
398 else if (_lightType == HdPrimTypeTokens->rectLight) {
400 _light->set_ellipse(
false);
401 _light->set_size(1.0f);
403 else if (_lightType == HdPrimTypeTokens->sphereLight) {
405 _light->set_size(1.0f);
408 _light->set_use_mis(
true);
412 array<Node *> used_shaders;
413 used_shaders.push_back_slow(shader);
414 _light->set_used_shaders(used_shaders);
417 PopulateShaderGraph(
nullptr);
@ NODE_VECTOR_MATH_MULTIPLY
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
void Finalize(PXR_NS::HdRenderParam *renderParam) override
void Sync(PXR_NS::HdSceneDelegate *sceneDelegate, PXR_NS::HdRenderParam *renderParam, PXR_NS::HdDirtyBits *dirtyBits) override
~HdCyclesLight() override
HdCyclesLight(const PXR_NS::SdfPath &sprimId, const PXR_NS::TfToken &lightType)
PXR_NS::HdDirtyBits GetInitialDirtyBitsMask() const override
ShaderInput * input(const char *name)
ShaderOutput * output(const char *name)
bool has_surface_spatial_varying
void set_graph(unique_ptr< ShaderGraph > &&graph)
void tag_update(Scene *scene)
static uint hash_string(const char *str)
ccl_device_inline uint hash_uint2(const uint kx, const uint ky)
HDCYCLES_NAMESPACE_OPEN_SCOPE Transform convert_transform(const GfMatrix4d &matrix)
#define HDCYCLES_NAMESPACE_CLOSE_SCOPE
TF_DEFINE_PRIVATE_TOKENS(_tokens,(visibleInPrimaryRay))
HDCYCLES_NAMESPACE_OPEN_SCOPE Transform convert_transform(const GfMatrix4d &matrix)
@ PATH_RAY_ALL_VISIBILITY
ccl_device_inline float3 one_float3()
CCL_NAMESPACE_BEGIN ccl_device_inline float3 zero_float3()