From d714b89014d019a1bbead105ad382e002e30649b Mon Sep 17 00:00:00 2001 From: Paul Molodowitch Date: Wed, 5 Jun 2024 17:23:34 -0700 Subject: [PATCH] [hdEmbree] ies: add PxrIESFile subclass, which calculates power via integration --- pxr/imaging/plugin/hdEmbree/CMakeLists.txt | 2 + pxr/imaging/plugin/hdEmbree/pxrIES/pxrIES.cpp | 78 +++++++++++++++++++ pxr/imaging/plugin/hdEmbree/pxrIES/pxrIES.h | 47 +++++++++++ 3 files changed, 127 insertions(+) create mode 100644 pxr/imaging/plugin/hdEmbree/pxrIES/pxrIES.cpp create mode 100644 pxr/imaging/plugin/hdEmbree/pxrIES/pxrIES.h diff --git a/pxr/imaging/plugin/hdEmbree/CMakeLists.txt b/pxr/imaging/plugin/hdEmbree/CMakeLists.txt index 22ba8bc76b..8e4a5d68b8 100644 --- a/pxr/imaging/plugin/hdEmbree/CMakeLists.txt +++ b/pxr/imaging/plugin/hdEmbree/CMakeLists.txt @@ -51,10 +51,12 @@ pxr_plugin(hdEmbree PRIVATE_HEADERS pxrIES/ies.h + pxrIES/pxrIES.h pxrPbrt/pbrtUtils.h CPPFILES pxrIES/ies.cpp + pxrIES/pxrIES.cpp RESOURCE_FILES plugInfo.json diff --git a/pxr/imaging/plugin/hdEmbree/pxrIES/pxrIES.cpp b/pxr/imaging/plugin/hdEmbree/pxrIES/pxrIES.cpp new file mode 100644 index 0000000000..407ae08e67 --- /dev/null +++ b/pxr/imaging/plugin/hdEmbree/pxrIES/pxrIES.cpp @@ -0,0 +1,78 @@ +// +// 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/pxrIES/pxrIES.h" + +#include + + +#define _USE_MATH_DEFINES +#include + +#if !defined(M_PI) +#define M_PI 3.14159265358979323846 +#endif + + +PXR_NAMESPACE_OPEN_SCOPE + +bool +PxrIESFile::load(std::string const& ies) // non-virtual "override" +{ + clear(); + if (!Base::load(ies)) { + return false; + } + pxr_extra_process(); + return true; +} + +void +PxrIESFile::clear() // non-virtual "override" +{ + Base::clear(); + _power = 0; +} + +void +PxrIESFile::pxr_extra_process() +{ + // find max v_angle delta, as a way to estimate whether the distribution + // is over a hemisphere or sphere + const auto [v_angleMin, v_angleMax] = std::minmax_element( + v_angles.cbegin(), v_angles.cend()); + + // does the distribution cover the whole sphere? + bool is_sphere = false; + if ((*v_angleMax - *v_angleMin) > (M_PI / 2 + 0.1 /* fudge factor*/)) { + is_sphere = true; + } + + _power = 0; + + // integrate the intensity over solid angle to get power + for (size_t h = 0; h < h_angles.size() - 1; ++h) { + for (size_t v = 0; v < v_angles.size() - 1; ++v) { + // approximate dimensions of the patch + float dh = h_angles[h + 1] - h_angles[h]; + float dv = v_angles[v + 1] - v_angles[v]; + // bilinearly interpolate intensity at the patch center + float i0 = (intensity[h][v] + intensity[h][v + 1]) / 2; + float i1 = + (intensity[h + 1][v] + intensity[h + 1][v + 1]) / 2; + float center_intensity = (i0 + i1) / 2; + // solid angle of the patch + float dS = dh * dv * sinf(v_angles[v] + dv / 2); + _power += dS * center_intensity; + } + } + + // ...and divide by surface area of a unit sphere (or hemisphere) + // (this result matches Karma & RIS) + _power /= M_PI * (is_sphere ? 4 : 2); +} + +PXR_NAMESPACE_CLOSE_SCOPE diff --git a/pxr/imaging/plugin/hdEmbree/pxrIES/pxrIES.h b/pxr/imaging/plugin/hdEmbree/pxrIES/pxrIES.h new file mode 100644 index 0000000000..a406b62531 --- /dev/null +++ b/pxr/imaging/plugin/hdEmbree/pxrIES/pxrIES.h @@ -0,0 +1,47 @@ +// +// 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_PXRIES_PXRIES_H +#define PXR_IMAGING_PLUGIN_HD_EMBREE_PXRIES_PXRIES_H + +#include "pxr/pxr.h" +#include "pxr/imaging/plugin/hdEmbree/pxrIES/ies.h" + +#include + +PXR_NAMESPACE_OPEN_SCOPE + +/// \class PxrIESFile +/// +/// Extends / overrides some functionality of standard IESFile. +/// +class PxrIESFile : public pxr_ccl::IESFile { +private: + using Base = pxr_ccl::IESFile; + +public: + + bool load(std::string const& ies); // non-virtual "override" + void clear(); // non-virtual "override" + + /// \brief The light's power, as calculated when parsing + inline float power() const + { + return _power; + } + +protected: + // Extra processing we do on-top of the "standard" process() from IESFile + void pxr_extra_process(); + +private: + + float _power = 0; +}; + +PXR_NAMESPACE_CLOSE_SCOPE + +#endif // PXR_IMAGING_PLUGIN_HD_EMBREE_PXRIES_PXRIES_H