Skip to content

Commit b62a1f0

Browse files
committed
[hdEmbree] add dome light suppport
1 parent f793aa5 commit b62a1f0

File tree

5 files changed

+91
-0
lines changed

5 files changed

+91
-0
lines changed

pxr/imaging/plugin/hdEmbree/light.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ HdEmbree_Light::HdEmbree_Light(SdfPath const& id, TfToken const& lightType)
9191
_lightData.lightVariant = HdEmbree_Cylinder();
9292
} else if (lightType == HdSprimTypeTokens->diskLight) {
9393
_lightData.lightVariant = HdEmbree_Disk();
94+
} else if (lightType == HdSprimTypeTokens->domeLight) {
95+
_lightData.lightVariant = HdEmbree_Dome();
9496
} else if (lightType == HdSprimTypeTokens->rectLight) {
9597
// Get shape parameters
9698
_lightData.lightVariant = HdEmbree_Rect();
@@ -164,6 +166,9 @@ HdEmbree_Light::Sync(HdSceneDelegate *sceneDelegate,
164166
sceneDelegate->GetLightParamValue(id, HdLightTokens->radius)
165167
.GetWithDefault(0.5f),
166168
};
169+
} else if constexpr (std::is_same_v<T, HdEmbree_Dome>) {
170+
typedLight = HdEmbree_Dome{};
171+
_SyncLightTexture(id, _lightData, sceneDelegate);
167172
} else if constexpr (std::is_same_v<T, HdEmbree_Rect>) {
168173
typedLight = HdEmbree_Rect{
169174
sceneDelegate->GetLightParamValue(id, HdLightTokens->width)

pxr/imaging/plugin/hdEmbree/light.h

+9
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ struct HdEmbree_Disk
3535
float radius;
3636
};
3737

38+
// Needed for HdEmbree_LightVariant
39+
struct HdEmbree_Dome
40+
{};
41+
3842
struct HdEmbree_Rect
3943
{
4044
float width;
@@ -50,6 +54,7 @@ using HdEmbree_LightVariant = std::variant<
5054
HdEmbree_UnknownLight,
5155
HdEmbree_Cylinder,
5256
HdEmbree_Disk,
57+
HdEmbree_Dome,
5358
HdEmbree_Rect,
5459
HdEmbree_Sphere>;
5560

@@ -108,6 +113,10 @@ class HdEmbree_Light final : public HdLight
108113
return _lightData;
109114
}
110115

116+
bool IsDome() const {
117+
return std::holds_alternative<HdEmbree_Dome>(_lightData.lightVariant);
118+
}
119+
111120
private:
112121
HdEmbree_LightData _lightData;
113122
};

pxr/imaging/plugin/hdEmbree/renderDelegate.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ const TfTokenVector HdEmbreeRenderDelegate::SUPPORTED_SPRIM_TYPES =
3838
HdPrimTypeTokens->extComputation,
3939
HdPrimTypeTokens->cylinderLight,
4040
HdPrimTypeTokens->diskLight,
41+
HdPrimTypeTokens->domeLight,
4142
HdPrimTypeTokens->rectLight,
4243
HdPrimTypeTokens->sphereLight,
4344
};
@@ -338,6 +339,7 @@ HdEmbreeRenderDelegate::CreateSprim(TfToken const& typeId,
338339
return new HdExtComputation(sprimId);
339340
} else if (typeId == HdPrimTypeTokens->light ||
340341
typeId == HdPrimTypeTokens->diskLight ||
342+
typeId == HdPrimTypeTokens->domeLight ||
341343
typeId == HdPrimTypeTokens->rectLight ||
342344
typeId == HdPrimTypeTokens->sphereLight ||
343345
typeId == HdPrimTypeTokens->cylinderLight) {
@@ -360,6 +362,7 @@ HdEmbreeRenderDelegate::CreateFallbackSprim(TfToken const& typeId)
360362
return new HdExtComputation(SdfPath::EmptyPath());
361363
} else if (typeId == HdPrimTypeTokens->light ||
362364
typeId == HdPrimTypeTokens->diskLight ||
365+
typeId == HdPrimTypeTokens->domeLight ||
363366
typeId == HdPrimTypeTokens->rectLight ||
364367
typeId == HdPrimTypeTokens->sphereLight ||
365368
typeId == HdPrimTypeTokens->cylinderLight) {

pxr/imaging/plugin/hdEmbree/renderer.cpp

+73
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,45 @@ _EvalAreaLight(HdEmbree_LightData const& light, _ShapeSample const& ss,
443443
};
444444
}
445445

446+
_LightSample
447+
_SampleDomeLight(HdEmbree_LightData const& light, GfVec3f const& direction)
448+
{
449+
float t = acosf(direction[1]) / _pi<float>;
450+
float s = atan2f(direction[0], direction[2]) / (2.0f * _pi<float>);
451+
s = 1.0f - fmodf(s+0.5f, 1.0f);
452+
453+
GfVec3f Li = light.texture.pixels.empty() ?
454+
GfVec3f(1.0f)
455+
: _SampleLightTexture(light.texture, s, t);
456+
457+
return _LightSample {
458+
Li,
459+
direction,
460+
std::numeric_limits<float>::max(),
461+
4.0f * _pi<float>
462+
};
463+
}
464+
465+
_LightSample
466+
_EvalDomeLight(HdEmbree_LightData const& light, GfVec3f const& W,
467+
float u1, float u2)
468+
{
469+
GfVec3f U, V;
470+
GfBuildOrthonormalFrame(W, &U, &V);
471+
472+
float z = u1;
473+
float r = sqrtf(std::max(0.0f, 1.0f - _Sqr(z)));
474+
float phi = 2.0f * _pi<float> * u2;
475+
476+
const GfVec3f wI =
477+
(W * z + r * cosf(phi) * U + r * sinf(phi) * V).GetNormalized();
478+
479+
_LightSample ls = _SampleDomeLight(light, wI);
480+
ls.invPdfW = 2.0f * _pi<float>; // We only picked from the hemisphere
481+
482+
return ls;
483+
}
484+
446485
class _LightSampler {
447486
public:
448487
static _LightSample GetLightSample(HdEmbree_LightData const& lightData,
@@ -510,6 +549,10 @@ class _LightSampler {
510549
return _EvalAreaLight(_lightData, shapeSample, _hitPosition);
511550
}
512551

552+
_LightSample operator()(HdEmbree_Dome const& dome) {
553+
return _EvalDomeLight(_lightData, _normal, _u1, _u2);
554+
}
555+
513556
private:
514557
_LightSampler(HdEmbree_LightData const& lightData,
515558
GfVec3f const& hitPosition,
@@ -629,13 +672,20 @@ HdEmbreeRenderer::AddLight(SdfPath const& lightPath,
629672
{
630673
ScopedLock lightsWriteLock(_lightsWriteMutex);
631674
_lightMap[lightPath] = light;
675+
676+
if (light->IsDome()) {
677+
_domes.push_back(light);
678+
}
632679
}
633680

634681
void
635682
HdEmbreeRenderer::RemoveLight(SdfPath const& lightPath, HdEmbree_Light* light)
636683
{
637684
ScopedLock lightsWriteLock(_lightsWriteMutex);
638685
_lightMap.erase(lightPath);
686+
_domes.erase(std::remove_if(_domes.begin(), _domes.end(),
687+
[&light](auto& l){ return l == light; }),
688+
_domes.end());
639689
}
640690

641691
bool
@@ -1425,6 +1475,29 @@ HdEmbreeRenderer::_ComputeColor(RTCRayHit const& rayHit,
14251475
std::default_random_engine &random,
14261476
GfVec4f const& clearColor)
14271477
{
1478+
if (rayHit.hit.geomID == RTC_INVALID_GEOMETRY_ID) {
1479+
if (_domes.empty()) {
1480+
return clearColor;
1481+
}
1482+
1483+
// if we missed all geometry in the scene, evaluate the infinite lights
1484+
// directly
1485+
GfVec4f domeColor(0.0f, 0.0f, 0.0f, 1.0f);
1486+
1487+
for (auto* dome : _domes) {
1488+
_LightSample ls = _SampleDomeLight(
1489+
dome->LightData(),
1490+
GfVec3f(rayHit.ray.dir_x,
1491+
rayHit.ray.dir_y,
1492+
rayHit.ray.dir_z)
1493+
);
1494+
domeColor[0] += ls.Li[0];
1495+
domeColor[1] += ls.Li[1];
1496+
domeColor[2] += ls.Li[2];
1497+
}
1498+
return domeColor;
1499+
}
1500+
14281501
// Get the instance and prototype context structures for the hit prim.
14291502
// We don't use embree's multi-level instancing; we
14301503
// flatten everything in hydra. So instID[0] should always be correct.

pxr/imaging/plugin/hdEmbree/renderer.h

+1
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ class HdEmbreeRenderer final
242242
// Lights
243243
mutable WriteMutex _lightsWriteMutex; // protects the 2 below
244244
std::map<SdfPath, HdEmbree_Light*> _lightMap;
245+
std::vector<HdEmbree_Light*> _domes;
245246
};
246247

247248
PXR_NAMESPACE_CLOSE_SCOPE

0 commit comments

Comments
 (0)