Skip to content

Commit

Permalink
[hdEmbree] add dome light suppport
Browse files Browse the repository at this point in the history
  • Loading branch information
pmolodo committed Oct 21, 2024
1 parent f793aa5 commit b62a1f0
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 0 deletions.
5 changes: 5 additions & 0 deletions pxr/imaging/plugin/hdEmbree/light.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ HdEmbree_Light::HdEmbree_Light(SdfPath const& id, TfToken const& lightType)
_lightData.lightVariant = HdEmbree_Cylinder();
} else if (lightType == HdSprimTypeTokens->diskLight) {
_lightData.lightVariant = HdEmbree_Disk();
} else if (lightType == HdSprimTypeTokens->domeLight) {
_lightData.lightVariant = HdEmbree_Dome();
} else if (lightType == HdSprimTypeTokens->rectLight) {
// Get shape parameters
_lightData.lightVariant = HdEmbree_Rect();
Expand Down Expand Up @@ -164,6 +166,9 @@ HdEmbree_Light::Sync(HdSceneDelegate *sceneDelegate,
sceneDelegate->GetLightParamValue(id, HdLightTokens->radius)
.GetWithDefault(0.5f),
};
} else if constexpr (std::is_same_v<T, HdEmbree_Dome>) {
typedLight = HdEmbree_Dome{};
_SyncLightTexture(id, _lightData, sceneDelegate);
} else if constexpr (std::is_same_v<T, HdEmbree_Rect>) {
typedLight = HdEmbree_Rect{
sceneDelegate->GetLightParamValue(id, HdLightTokens->width)
Expand Down
9 changes: 9 additions & 0 deletions pxr/imaging/plugin/hdEmbree/light.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ struct HdEmbree_Disk
float radius;
};

// Needed for HdEmbree_LightVariant
struct HdEmbree_Dome
{};

struct HdEmbree_Rect
{
float width;
Expand All @@ -50,6 +54,7 @@ using HdEmbree_LightVariant = std::variant<
HdEmbree_UnknownLight,
HdEmbree_Cylinder,
HdEmbree_Disk,
HdEmbree_Dome,
HdEmbree_Rect,
HdEmbree_Sphere>;

Expand Down Expand Up @@ -108,6 +113,10 @@ class HdEmbree_Light final : public HdLight
return _lightData;
}

bool IsDome() const {
return std::holds_alternative<HdEmbree_Dome>(_lightData.lightVariant);
}

private:
HdEmbree_LightData _lightData;
};
Expand Down
3 changes: 3 additions & 0 deletions pxr/imaging/plugin/hdEmbree/renderDelegate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const TfTokenVector HdEmbreeRenderDelegate::SUPPORTED_SPRIM_TYPES =
HdPrimTypeTokens->extComputation,
HdPrimTypeTokens->cylinderLight,
HdPrimTypeTokens->diskLight,
HdPrimTypeTokens->domeLight,
HdPrimTypeTokens->rectLight,
HdPrimTypeTokens->sphereLight,
};
Expand Down Expand Up @@ -338,6 +339,7 @@ HdEmbreeRenderDelegate::CreateSprim(TfToken const& typeId,
return new HdExtComputation(sprimId);
} else if (typeId == HdPrimTypeTokens->light ||
typeId == HdPrimTypeTokens->diskLight ||
typeId == HdPrimTypeTokens->domeLight ||
typeId == HdPrimTypeTokens->rectLight ||
typeId == HdPrimTypeTokens->sphereLight ||
typeId == HdPrimTypeTokens->cylinderLight) {
Expand All @@ -360,6 +362,7 @@ HdEmbreeRenderDelegate::CreateFallbackSprim(TfToken const& typeId)
return new HdExtComputation(SdfPath::EmptyPath());
} else if (typeId == HdPrimTypeTokens->light ||
typeId == HdPrimTypeTokens->diskLight ||
typeId == HdPrimTypeTokens->domeLight ||
typeId == HdPrimTypeTokens->rectLight ||
typeId == HdPrimTypeTokens->sphereLight ||
typeId == HdPrimTypeTokens->cylinderLight) {
Expand Down
73 changes: 73 additions & 0 deletions pxr/imaging/plugin/hdEmbree/renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,45 @@ _EvalAreaLight(HdEmbree_LightData const& light, _ShapeSample const& ss,
};
}

_LightSample
_SampleDomeLight(HdEmbree_LightData const& light, GfVec3f const& direction)
{
float t = acosf(direction[1]) / _pi<float>;
float s = atan2f(direction[0], direction[2]) / (2.0f * _pi<float>);
s = 1.0f - fmodf(s+0.5f, 1.0f);

GfVec3f Li = light.texture.pixels.empty() ?
GfVec3f(1.0f)
: _SampleLightTexture(light.texture, s, t);

return _LightSample {
Li,
direction,
std::numeric_limits<float>::max(),
4.0f * _pi<float>
};
}

_LightSample
_EvalDomeLight(HdEmbree_LightData const& light, GfVec3f const& W,
float u1, float u2)
{
GfVec3f U, V;
GfBuildOrthonormalFrame(W, &U, &V);

float z = u1;
float r = sqrtf(std::max(0.0f, 1.0f - _Sqr(z)));
float phi = 2.0f * _pi<float> * u2;

const GfVec3f wI =
(W * z + r * cosf(phi) * U + r * sinf(phi) * V).GetNormalized();

_LightSample ls = _SampleDomeLight(light, wI);
ls.invPdfW = 2.0f * _pi<float>; // We only picked from the hemisphere

return ls;
}

class _LightSampler {
public:
static _LightSample GetLightSample(HdEmbree_LightData const& lightData,
Expand Down Expand Up @@ -510,6 +549,10 @@ class _LightSampler {
return _EvalAreaLight(_lightData, shapeSample, _hitPosition);
}

_LightSample operator()(HdEmbree_Dome const& dome) {
return _EvalDomeLight(_lightData, _normal, _u1, _u2);
}

private:
_LightSampler(HdEmbree_LightData const& lightData,
GfVec3f const& hitPosition,
Expand Down Expand Up @@ -629,13 +672,20 @@ HdEmbreeRenderer::AddLight(SdfPath const& lightPath,
{
ScopedLock lightsWriteLock(_lightsWriteMutex);
_lightMap[lightPath] = light;

if (light->IsDome()) {
_domes.push_back(light);
}
}

void
HdEmbreeRenderer::RemoveLight(SdfPath const& lightPath, HdEmbree_Light* light)
{
ScopedLock lightsWriteLock(_lightsWriteMutex);
_lightMap.erase(lightPath);
_domes.erase(std::remove_if(_domes.begin(), _domes.end(),
[&light](auto& l){ return l == light; }),
_domes.end());
}

bool
Expand Down Expand Up @@ -1425,6 +1475,29 @@ HdEmbreeRenderer::_ComputeColor(RTCRayHit const& rayHit,
std::default_random_engine &random,
GfVec4f const& clearColor)
{
if (rayHit.hit.geomID == RTC_INVALID_GEOMETRY_ID) {
if (_domes.empty()) {
return clearColor;
}

// if we missed all geometry in the scene, evaluate the infinite lights
// directly
GfVec4f domeColor(0.0f, 0.0f, 0.0f, 1.0f);

for (auto* dome : _domes) {
_LightSample ls = _SampleDomeLight(
dome->LightData(),
GfVec3f(rayHit.ray.dir_x,
rayHit.ray.dir_y,
rayHit.ray.dir_z)
);
domeColor[0] += ls.Li[0];
domeColor[1] += ls.Li[1];
domeColor[2] += ls.Li[2];
}
return domeColor;
}

// Get the instance and prototype context structures for the hit prim.
// We don't use embree's multi-level instancing; we
// flatten everything in hydra. So instID[0] should always be correct.
Expand Down
1 change: 1 addition & 0 deletions pxr/imaging/plugin/hdEmbree/renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ class HdEmbreeRenderer final
// Lights
mutable WriteMutex _lightsWriteMutex; // protects the 2 below
std::map<SdfPath, HdEmbree_Light*> _lightMap;
std::vector<HdEmbree_Light*> _domes;
};

PXR_NAMESPACE_CLOSE_SCOPE
Expand Down

0 comments on commit b62a1f0

Please sign in to comment.