-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[hdEmbree] Initial UsdLux reference implementation
This modifies the hdEmbree example plugin to do direct lighting so as to provide a reference implementation of the expected behaviour for UsdLux. If no lights are present in the stage, the old ambient occlusion path will be used.
- Loading branch information
1 parent
4b10db7
commit a6a9136
Showing
8 changed files
with
987 additions
and
65 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,6 +31,7 @@ pxr_plugin(hdEmbree | |
PUBLIC_CLASSES | ||
config | ||
instancer | ||
light | ||
mesh | ||
meshSamplers | ||
renderBuffer | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,171 @@ | ||
// | ||
// Copyright 2024 Pixar | ||
// | ||
// Licensed under the terms set forth in the LICENSE.txt file available at | ||
// https://openusd.org/license. | ||
// | ||
#include "pxr/imaging/plugin/hdEmbree/light.h" | ||
|
||
#include "light.h" | ||
#include "pxr/imaging/plugin/hdEmbree/debugCodes.h" | ||
#include "pxr/imaging/plugin/hdEmbree/renderParam.h" | ||
#include "pxr/imaging/plugin/hdEmbree/renderer.h" | ||
|
||
#include "pxr/imaging/hd/sceneDelegate.h" | ||
#include "pxr/imaging/hio/image.h" | ||
|
||
#include <embree3/rtcore_buffer.h> | ||
#include <embree3/rtcore_scene.h> | ||
|
||
#include <fstream> | ||
#include <sstream> | ||
#include <vector> | ||
|
||
PXR_NAMESPACE_OPEN_SCOPE | ||
|
||
HdEmbree_Light::HdEmbree_Light(SdfPath const& id, TfToken const& lightType) | ||
: HdLight(id) { | ||
if (id.IsEmpty()) { | ||
return; | ||
} | ||
|
||
// Set the variant to the right type - Sync will fill rest of data | ||
if (lightType == HdSprimTypeTokens->cylinderLight) { | ||
_lightData.lightVariant = HdEmbree_Cylinder(); | ||
} else if (lightType == HdSprimTypeTokens->diskLight) { | ||
_lightData.lightVariant = HdEmbree_Disk(); | ||
} else if (lightType == HdSprimTypeTokens->rectLight) { | ||
// Get shape parameters | ||
_lightData.lightVariant = HdEmbree_Rect(); | ||
} else if (lightType == HdSprimTypeTokens->sphereLight) { | ||
_lightData.lightVariant = HdEmbree_Sphere(); | ||
} else { | ||
TF_WARN("HdEmbree - Unrecognized light type: %s", lightType.GetText()); | ||
_lightData.lightVariant = HdEmbree_UnknownLight(); | ||
} | ||
} | ||
|
||
HdEmbree_Light::~HdEmbree_Light() = default; | ||
|
||
void | ||
HdEmbree_Light::Sync(HdSceneDelegate *sceneDelegate, | ||
HdRenderParam *renderParam, HdDirtyBits *dirtyBits) | ||
{ | ||
HD_TRACE_FUNCTION(); | ||
HF_MALLOC_TAG_FUNCTION(); | ||
|
||
HdEmbreeRenderParam *embreeRenderParam = | ||
static_cast<HdEmbreeRenderParam*>(renderParam); | ||
|
||
// calling this bumps the scene version and causes a re-render | ||
embreeRenderParam->AcquireSceneForEdit(); | ||
|
||
SdfPath const& id = GetId(); | ||
|
||
// Get _lightData's transform. We'll only consider the first time sample for now | ||
HdTimeSampleArray<GfMatrix4d, 1> xformSamples; | ||
sceneDelegate->SampleTransform(id, &xformSamples); | ||
_lightData.xformLightToWorld = GfMatrix4f(xformSamples.values[0]); | ||
_lightData.xformWorldToLight = _lightData.xformLightToWorld.GetInverse(); | ||
_lightData.normalXformLightToWorld = | ||
_lightData.xformWorldToLight.ExtractRotationMatrix().GetTranspose(); | ||
|
||
// Store luminance parameters | ||
_lightData.intensity = sceneDelegate->GetLightParamValue( | ||
id, HdLightTokens->intensity).GetWithDefault(1.0f); | ||
_lightData.exposure = sceneDelegate->GetLightParamValue( | ||
id, HdLightTokens->exposure).GetWithDefault(0.0f); | ||
_lightData.color = sceneDelegate->GetLightParamValue( | ||
id, HdLightTokens->color).GetWithDefault(GfVec3f{1.0f, 1.0f, 1.0f}); | ||
_lightData.normalize = sceneDelegate->GetLightParamValue( | ||
id, HdLightTokens->normalize).GetWithDefault(false); | ||
_lightData.colorTemperature = sceneDelegate->GetLightParamValue( | ||
id, HdLightTokens->colorTemperature).GetWithDefault(6500.0f); | ||
_lightData.enableColorTemperature = sceneDelegate->GetLightParamValue( | ||
id, HdLightTokens->enableColorTemperature).GetWithDefault(false); | ||
|
||
// Get visibility | ||
_lightData.visible = sceneDelegate->GetVisible(id); | ||
|
||
// Switch on the _lightData type and pull the relevant attributes from the scene | ||
// delegate | ||
std::visit([this, &id, &sceneDelegate](auto& typedLight) { | ||
using T = std::decay_t<decltype(typedLight)>; | ||
if constexpr (std::is_same_v<T, HdEmbree_UnknownLight>) { | ||
// Do nothing | ||
} else if constexpr (std::is_same_v<T, HdEmbree_Cylinder>) { | ||
typedLight = HdEmbree_Cylinder{ | ||
sceneDelegate->GetLightParamValue(id, HdLightTokens->radius) | ||
.GetWithDefault(0.5f), | ||
sceneDelegate->GetLightParamValue(id, HdLightTokens->length) | ||
.GetWithDefault(1.0f), | ||
}; | ||
} else if constexpr (std::is_same_v<T, HdEmbree_Disk>) { | ||
typedLight = HdEmbree_Disk{ | ||
sceneDelegate->GetLightParamValue(id, HdLightTokens->radius) | ||
.GetWithDefault(0.5f), | ||
}; | ||
} else if constexpr (std::is_same_v<T, HdEmbree_Rect>) { | ||
typedLight = HdEmbree_Rect{ | ||
sceneDelegate->GetLightParamValue(id, HdLightTokens->width) | ||
.Get<float>(), | ||
sceneDelegate->GetLightParamValue(id, HdLightTokens->height) | ||
.Get<float>(), | ||
}; | ||
} else if constexpr (std::is_same_v<T, HdEmbree_Sphere>) { | ||
typedLight = HdEmbree_Sphere{ | ||
sceneDelegate->GetLightParamValue(id, HdLightTokens->radius) | ||
.GetWithDefault(0.5f), | ||
}; | ||
} else { | ||
static_assert(false, "non-exhaustive _LightVariant visitor"); | ||
} | ||
}, _lightData.lightVariant); | ||
|
||
if (const auto value = sceneDelegate->GetLightParamValue( | ||
id, HdLightTokens->shapingFocus); | ||
value.IsHolding<float>()) { | ||
_lightData.shaping.focus = value.UncheckedGet<float>(); | ||
} | ||
|
||
if (const auto value = sceneDelegate->GetLightParamValue( | ||
id, HdLightTokens->shapingFocusTint); | ||
value.IsHolding<GfVec3f>()) { | ||
_lightData.shaping.focusTint = value.UncheckedGet<GfVec3f>(); | ||
} | ||
|
||
if (const auto value = sceneDelegate->GetLightParamValue( | ||
id, HdLightTokens->shapingConeAngle); | ||
value.IsHolding<float>()) { | ||
_lightData.shaping.coneAngle = value.UncheckedGet<float>(); | ||
} | ||
|
||
if (const auto value = sceneDelegate->GetLightParamValue( | ||
id, HdLightTokens->shapingConeSoftness); | ||
value.IsHolding<float>()) { | ||
_lightData.shaping.coneSoftness = value.UncheckedGet<float>(); | ||
} | ||
|
||
HdEmbreeRenderer *renderer = embreeRenderParam->GetRenderer(); | ||
renderer->AddLight(id, this); | ||
|
||
*dirtyBits &= ~HdLight::AllDirty; | ||
} | ||
|
||
HdDirtyBits | ||
HdEmbree_Light::GetInitialDirtyBitsMask() const | ||
{ | ||
return HdLight::AllDirty; | ||
} | ||
|
||
void | ||
HdEmbree_Light::Finalize(HdRenderParam *renderParam) | ||
{ | ||
auto* embreeParam = static_cast<HdEmbreeRenderParam*>(renderParam); | ||
|
||
// Remove from renderer's light map | ||
HdEmbreeRenderer *renderer = embreeParam->GetRenderer(); | ||
renderer->RemoveLight(GetId(), this); | ||
} | ||
|
||
PXR_NAMESPACE_CLOSE_SCOPE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
// | ||
// Copyright 2024 Pixar | ||
// | ||
// Licensed under the terms set forth in the LICENSE.txt file available at | ||
// https://openusd.org/license. | ||
// | ||
#ifndef PXR_IMAGING_PLUGIN_HD_EMBREE_LIGHT_H | ||
#define PXR_IMAGING_PLUGIN_HD_EMBREE_LIGHT_H | ||
|
||
#include "pxr/base/gf/vec3f.h" | ||
#include "pxr/base/gf/matrix3f.h" | ||
#include "pxr/base/gf/matrix4f.h" | ||
#include "pxr/imaging/hd/light.h" | ||
|
||
#include <embree3/rtcore_common.h> | ||
#include <embree3/rtcore_geometry.h> | ||
|
||
#include <limits> | ||
#include <variant> | ||
|
||
PXR_NAMESPACE_OPEN_SCOPE | ||
|
||
class HdEmbreeRenderer; | ||
|
||
struct HdEmbree_UnknownLight | ||
{}; | ||
struct HdEmbree_Cylinder | ||
{ | ||
float radius; | ||
float length; | ||
}; | ||
|
||
struct HdEmbree_Disk | ||
{ | ||
float radius; | ||
}; | ||
|
||
struct HdEmbree_Rect | ||
{ | ||
float width; | ||
float height; | ||
}; | ||
|
||
struct HdEmbree_Sphere | ||
{ | ||
float radius; | ||
}; | ||
|
||
using HdEmbree_LightVariant = std::variant< | ||
HdEmbree_UnknownLight, | ||
HdEmbree_Cylinder, | ||
HdEmbree_Disk, | ||
HdEmbree_Rect, | ||
HdEmbree_Sphere>; | ||
|
||
struct HdEmbree_Shaping | ||
{ | ||
GfVec3f focusTint; | ||
float focus = 0.0f; | ||
float coneAngle = 180.0f; | ||
float coneSoftness = 0.0f; | ||
}; | ||
|
||
struct HdEmbree_LightData | ||
{ | ||
GfMatrix4f xformLightToWorld; | ||
GfMatrix3f normalXformLightToWorld; | ||
GfMatrix4f xformWorldToLight; | ||
GfVec3f color; | ||
float intensity = 1.0f; | ||
float exposure = 0.0f; | ||
float colorTemperature = 6500.0f; | ||
bool enableColorTemperature = false; | ||
HdEmbree_LightVariant lightVariant; | ||
bool normalize = false; | ||
bool visible = true; | ||
HdEmbree_Shaping shaping; | ||
}; | ||
|
||
class HdEmbree_Light final : public HdLight | ||
{ | ||
public: | ||
HdEmbree_Light(SdfPath const& id, TfToken const& lightType); | ||
~HdEmbree_Light(); | ||
|
||
/// Synchronizes state from the delegate to this object. | ||
void Sync(HdSceneDelegate* sceneDelegate, | ||
HdRenderParam* renderParam, | ||
HdDirtyBits* dirtyBits) override; | ||
|
||
/// Returns the minimal set of dirty bits to place in the | ||
/// change tracker for use in the first sync of this prim. | ||
/// Typically this would be all dirty bits. | ||
HdDirtyBits GetInitialDirtyBitsMask() const override; | ||
|
||
void Finalize(HdRenderParam *renderParam) override; | ||
|
||
HdEmbree_LightData const& LightData() const { | ||
return _lightData; | ||
} | ||
|
||
private: | ||
HdEmbree_LightData _lightData; | ||
}; | ||
|
||
|
||
PXR_NAMESPACE_CLOSE_SCOPE | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.