Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[hdEmbree] add dome light suppport #6

Open
wants to merge 1 commit into
base: pr/hdEmbree-light-textures
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -491,6 +491,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 @@ -558,6 +597,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 @@ -677,13 +720,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 @@ -1475,6 +1525,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