Skip to content

Commit

Permalink
[hdEmbree] add light texture support
Browse files Browse the repository at this point in the history
  • Loading branch information
pmolodo committed Sep 23, 2024
1 parent 9088c1b commit 4ab9adb
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 0 deletions.
56 changes: 56 additions & 0 deletions pxr/imaging/plugin/hdEmbree/light.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,61 @@
#include <sstream>
#include <vector>

namespace {

PXR_NAMESPACE_USING_DIRECTIVE

HdEmbree_LightTexture
_LoadLightTexture(std::string const& path)
{
if (path.empty()) {
return HdEmbree_LightTexture();
}

HioImageSharedPtr img = HioImage::OpenForReading(path);
if (!img) {
return HdEmbree_LightTexture();
}

int width = img->GetWidth();
int height = img->GetHeight();

std::vector<GfVec3f> pixels(width * height * 3.0f);

HioImage::StorageSpec storage;
storage.width = width;
storage.height = height;
storage.depth = 1;
storage.format = HioFormatFloat32Vec3;
storage.data = &pixels.front();

if (img->Read(storage)) {
return {std::move(pixels), width, height};
}
TF_WARN("Could not read image %s", path.c_str());
return { std::vector<GfVec3f>(), 0, 0 };
}


void
_SyncLightTexture(const SdfPath& id, HdEmbree_LightData& light, HdSceneDelegate *sceneDelegate)
{
std::string path;
if (VtValue textureValue = sceneDelegate->GetLightParamValue(
id, HdLightTokens->textureFile);
textureValue.IsHolding<SdfAssetPath>()) {
SdfAssetPath texturePath =
textureValue.UncheckedGet<SdfAssetPath>();
path = texturePath.GetResolvedPath();
if (path.empty()) {
path = texturePath.GetAssetPath();
}
}
light.texture = _LoadLightTexture(path);
}


} // anonymous namespace
PXR_NAMESPACE_OPEN_SCOPE

HdEmbree_Light::HdEmbree_Light(SdfPath const& id, TfToken const& lightType)
Expand Down Expand Up @@ -112,6 +167,7 @@ HdEmbree_Light::Sync(HdSceneDelegate *sceneDelegate,
sceneDelegate->GetLightParamValue(id, HdLightTokens->height)
.Get<float>(),
};
_SyncLightTexture(id, _lightData, sceneDelegate);
} else if constexpr (std::is_same_v<T, HdEmbree_Sphere>) {
typedLight = HdEmbree_Sphere{
sceneDelegate->GetLightParamValue(id, HdLightTokens->radius)
Expand Down
8 changes: 8 additions & 0 deletions pxr/imaging/plugin/hdEmbree/light.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@ using HdEmbree_LightVariant = std::variant<
HdEmbree_Rect,
HdEmbree_Sphere>;

struct HdEmbree_LightTexture
{
std::vector<GfVec3f> pixels;
int width = 0;
int height = 0;
};

struct HdEmbree_Shaping
{
GfVec3f focusTint;
Expand All @@ -67,6 +74,7 @@ struct HdEmbree_LightData
GfMatrix3f normalXformLightToWorld;
GfMatrix4f xformWorldToLight;
GfVec3f color;
HdEmbree_LightTexture texture;
float intensity = 1.0f;
float exposure = 0.0f;
float colorTemperature = 6500.0f;
Expand Down
19 changes: 19 additions & 0 deletions pxr/imaging/plugin/hdEmbree/renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,19 @@ struct _LightSample {
float invPdfW;
};

GfVec3f
_SampleLightTexture(HdEmbree_LightTexture const& texture, float s, float t)
{
if (texture.pixels.empty()) {
return GfVec3f(0.0f);
}

int x = float(texture.width) * s;
int y = float(texture.height) * t;

return texture.pixels.at(y*texture.width + x);
}

_ShapeSample
_SampleRect(GfMatrix4f const& xf, GfMatrix3f const& normalXform, float width,
float height, float u1, float u2)
Expand Down Expand Up @@ -363,6 +376,12 @@ _EvalAreaLight(HdEmbree_LightData const& light, _ShapeSample const& ss,
_EvalLightBasic(light)
: GfVec3f(0.0f);

// Multiply by the texture, if there is one
if (!light.texture.pixels.empty()) {
Le = GfCompMult(Le, _SampleLightTexture(light.texture, ss.uv[0],
1.0f - ss.uv[1]));
}

// If normalize is enabled, we need to divide the luminance by the surface
// area of the light, which for an area light is equivalent to multiplying
// by the area pdf, which is itself the reciprocal of the surface area
Expand Down

0 comments on commit 4ab9adb

Please sign in to comment.