Skip to content

Commit be38903

Browse files
anderslanglandspmolodo
authored andcommitted
[hdEmbree] PxrIESFile: add eval() and valid() methods
1 parent f2eb019 commit be38903

File tree

2 files changed

+107
-7
lines changed

2 files changed

+107
-7
lines changed

pxr/imaging/plugin/hdEmbree/pxrIES/pxrIES.cpp

+97-7
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
//
77
#include "pxr/imaging/plugin/hdEmbree/pxrIES/pxrIES.h"
88

9+
#include "pxr/base/gf/math.h"
10+
911
#include <algorithm>
1012

1113

@@ -16,11 +18,43 @@
1618
#define M_PI 3.14159265358979323846
1719
#endif
1820

21+
namespace {
22+
23+
// -------------------------------------------------------------------------
24+
// Constants
25+
// -------------------------------------------------------------------------
26+
27+
template <typename T>
28+
constexpr T _pi = static_cast<T>(M_PI);
29+
30+
constexpr float _hemisphereFudgeFactor = 0.1f;
31+
32+
// -------------------------------------------------------------------------
33+
// Utility functions
34+
// -------------------------------------------------------------------------
35+
36+
37+
float
38+
_linearstep(float x, float a, float b)
39+
{
40+
if (x <= a) {
41+
return 0.0f;
42+
}
43+
44+
if (x >= b) {
45+
return 1.0f;
46+
}
47+
48+
return (x - a) / (b - a);
49+
}
50+
51+
} // anonymous namespace
52+
1953

2054
PXR_NAMESPACE_OPEN_SCOPE
2155

2256
bool
23-
PxrIESFile::load(std::string const& ies) // non-virtual "override"
57+
PxrIESFile::load(const std::string &ies) // non-virtual "override"
2458
{
2559
clear();
2660
if (!Base::load(ies)) {
@@ -47,7 +81,8 @@ PxrIESFile::pxr_extra_process()
4781

4882
// does the distribution cover the whole sphere?
4983
bool is_sphere = false;
50-
if ((*v_angleMax - *v_angleMin) > (M_PI / 2 + 0.1 /* fudge factor*/)) {
84+
if ((*v_angleMax - *v_angleMin)
85+
> (_pi<float> / 2.0f + _hemisphereFudgeFactor)) {
5186
is_sphere = true;
5287
}
5388

@@ -60,19 +95,74 @@ PxrIESFile::pxr_extra_process()
6095
float dh = h_angles[h + 1] - h_angles[h];
6196
float dv = v_angles[v + 1] - v_angles[v];
6297
// bilinearly interpolate intensity at the patch center
63-
float i0 = (intensity[h][v] + intensity[h][v + 1]) / 2;
98+
float i0 = (intensity[h][v] + intensity[h][v + 1]) / 2.0f;
6499
float i1 =
65-
(intensity[h + 1][v] + intensity[h + 1][v + 1]) / 2;
66-
float center_intensity = (i0 + i1) / 2;
100+
(intensity[h + 1][v] + intensity[h + 1][v + 1]) / 2.0f;
101+
float center_intensity = (i0 + i1) / 2.0f;
67102
// solid angle of the patch
68-
float dS = dh * dv * sinf(v_angles[v] + dv / 2);
103+
float dS = dh * dv * sinf(v_angles[v] + dv / 2.0f);
69104
_power += dS * center_intensity;
70105
}
71106
}
72107

73108
// ...and divide by surface area of a unit sphere (or hemisphere)
74109
// (this result matches Karma & RIS)
75-
_power /= M_PI * (is_sphere ? 4 : 2);
110+
_power /= _pi<float> * (is_sphere ? 4.0f : 2.0f);
111+
}
112+
113+
float
114+
PxrIESFile::eval(float theta, float phi, float angleScale) const
115+
{
116+
int hi = -1;
117+
int vi = -1;
118+
float dh = 0.0f;
119+
float dv = 0.0f;
120+
121+
phi = GfMod(phi, 2.0f * _pi<float>);
122+
for (size_t i = 0; i < h_angles.size() - 1; ++i) {
123+
if (phi >= h_angles[i] && phi < h_angles[i + 1]) {
124+
hi = i;
125+
dh = _linearstep(phi, h_angles[i], h_angles[i + 1]);
126+
break;
127+
}
128+
}
129+
130+
// This formula matches Renderman's behavior
131+
132+
// Scale with origin at "top" (ie, 180 degress / pi), by a factor
133+
// of 1 / (1 + angleScale), offset so that angleScale = 0 yields the
134+
// identity function.
135+
const float profileScale = 1.0f + angleScale;
136+
theta = (theta - _pi<float>) / profileScale + _pi<float>;
137+
theta = GfClamp(theta, 0.0f, _pi<float>);
138+
139+
if (theta < 0) {
140+
// vi = 0;
141+
// dv = 0;
142+
return 0.0f;
143+
} else if (theta >= _pi<float>) {
144+
vi = v_angles.size() - 2;
145+
dv = 1;
146+
} else {
147+
for (size_t i = 0; i < v_angles.size() - 1; ++i) {
148+
if (theta >= v_angles[i] && theta < v_angles[i + 1]) {
149+
vi = i;
150+
dv = _linearstep(theta, v_angles[i], v_angles[i + 1]);
151+
break;
152+
}
153+
}
154+
}
155+
156+
if (hi == -1 || vi == -1) {
157+
// XXX: need to indicate error somehow here
158+
return 0.0f;
159+
}
160+
161+
// XXX: This should be a cubic interpolation
162+
float i0 = GfLerp(dv, intensity[hi][vi], intensity[hi][vi + 1]);
163+
float i1 = GfLerp(dv, intensity[hi + 1][vi], intensity[hi + 1][vi + 1]);
164+
165+
return GfLerp(dh, i0, i1);
76166
}
77167

78168
PXR_NAMESPACE_CLOSE_SCOPE

pxr/imaging/plugin/hdEmbree/pxrIES/pxrIES.h

+10
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,16 @@ class PxrIESFile : public pxr_ccl::IESFile {
3333
return _power;
3434
}
3535

36+
// returns true if the IES files was successfully loaded and processed and
37+
// is ready to evaluate
38+
bool valid() const
39+
{
40+
return !intensity.empty();
41+
}
42+
43+
// evaluate the IES file for the given spherical coordinates
44+
float eval(float theta, float phi, float angleScale) const;
45+
3646
protected:
3747
// Extra processing we do on-top of the "standard" process() from IESFile
3848
void pxr_extra_process();

0 commit comments

Comments
 (0)