37 #ifndef RixIESInline_h
38 #define RixIESInline_h
47 #include "RiTypesHelper.h"
55 emission->r = emission->g = emission->b = 1.f;
60 RtFloat3 localDir = P;
65 if (!m_hasNegativeDeterminant)
70 calcLatLongParam(1, (
float*)&localDir, m_iesProfile.
isExr, &u, &v);
72 if ((u != u) || (v != v))
76 emission->r = emission->g = emission->b = 1.f;
80 if (u < 0.0f || u > 1.0f || v < 0.0f || v > 1.0f)
84 emission->r = emission->g = emission->b = 1.f;
89 float coneSize = 1.0f;
90 float profileScale = 1.0f;
91 if (m_coneAngle > 0.0f)
93 coneSize = m_coneAngle / (float)
F_PI;
94 profileScale = coneSize;
106 v = v / profileScale;
111 v = std::max(std::min(v * vScale, 1.0f), 0.0f);
115 float uf = u *
static_cast<float>(m_iesProfile.
nu);
116 if (uf >= m_iesProfile.
nu)
117 uf -=
static_cast<float>(m_iesProfile.
nu);
119 int u0 =
static_cast<int>(floorf(uf));
121 if (u1 >= m_iesProfile.
nu)
124 float fu = uf -
static_cast<float>(u0);
126 if (u0 < 0 || u0 >= m_iesProfile.
nu || u1 < 0 || u1 >= m_iesProfile.
nu)
130 emission->r = emission->g = emission->b = 1.f;
134 float vf = v * (
static_cast<float>(m_iesProfile.
nv) - 1.0f);
135 if (vf >= m_iesProfile.
nv)
136 vf =
static_cast<float>(m_iesProfile.
nv) - 1.0f;
138 int v0 =
static_cast<int>(floorf(vf));
140 if (v1 >= m_iesProfile.
nv)
141 v1 = m_iesProfile.
nv - 1;
143 float fv = vf -
static_cast<float>(v0);
145 if (v0 < 0 || v0 >= m_iesProfile.
nv || v1 < 0 || v1 >= m_iesProfile.
nv)
149 emission->r = emission->g = emission->b = 1.f;
153 int v00 = u0 + v0 * m_iesProfile.
nu;
154 int v10 = u1 + v0 * m_iesProfile.
nu;
155 int v01 = u0 + v1 * m_iesProfile.
nu;
156 int v11 = u1 + v1 * m_iesProfile.
nu;
158 float rfu = 1.0f - fu;
165 (1.0f - fv) * ( rfu * m_iesProfile.
profile[3 * v00 + 0]
166 + fu * m_iesProfile.
profile[3 * v10 + 0])
167 + fv * ( rfu * m_iesProfile.
profile[3 * v01 + 0]
168 + fu * m_iesProfile.
profile[3 * v11 + 0]);
169 emission->r = std::max(0.0f, emission->r);
172 (1.0f - fv) * ( rfu * m_iesProfile.
profile[3 * v00 + 1]
173 + fu * m_iesProfile.
profile[3 * v10 + 1])
174 + fv * ( rfu * m_iesProfile.
profile[3 * v01 + 1]
175 + fu * m_iesProfile.
profile[3 * v11 + 1]);
176 emission->g = std::max(0.0f, emission->g);
179 (1.0f - fv) * ( rfu * m_iesProfile.
profile[3 * v00 + 2]
180 + fu * m_iesProfile.
profile[3 * v10 + 2])
181 + fv * ( rfu * m_iesProfile.
profile[3 * v01 + 2]
182 + fu * m_iesProfile.
profile[3 * v11 + 2]);
183 emission->b = std::max(0.0f, emission->b);
188 (1.0f - fv) * ( rfu * m_iesProfile.
profile[v00]
189 + fu * m_iesProfile.
profile[v10])
190 + fv * ( rfu * m_iesProfile.
profile[v01]
191 + fu * m_iesProfile.
profile[v11]);
193 emission->r = std::max(0.0f, emission->r);
194 emission->g = emission->b = emission->r;
203 m_iesProfile.
clear();
206 if (!iesProfile.Empty())
208 static std::string rtxPrefix(
"rtxplugin:RtxIES?filename=");
215 std::string mapName = rtxPrefix + std::string(iesProfile.CStr());
216 m_iesProfile.
mapName = RtUString(mapName.c_str());
226 "RixIES emission profile: could not open %s",
228 m_iesProfile.
mapName = US_NULL;
234 "Building RixIES emission profile(\"%s\")\n",
237 m_iesProfile.
nu = txProps.
width;
239 m_iesProfile.
isExr =
false;
243 m_iesProfile.
profile =
new float[
254 int nu = m_iesProfile.
nu;
255 int nv = m_iesProfile.
nv;
260 for (
int j = 0; j <= nv / 2; ++j)
272 float lowerAngle = (j == 0) ? 0 :
F_PI * (2 * j - 1) / nv;
274 (j == nv / 2) ?
F_PI :
F_PI * (2 * j + 1) / nv;
276 0.5f * (cosf(lowerAngle) - cosf(upperAngle));
277 for (
int i = 0; i < nu; ++i)
279 for (
int k = 0; k < nchans; ++k)
281 total += scalefactor *
282 m_iesProfile.
profile[((j * nu) + i) * nchans + k];
286 m_normalizationFactor = nu * nchans / total;
297 if (m_coneAngle > 0.0f)
300 RtFloat3 localDir = P;
301 if (m_hasNegativeDeterminant)
304 if (localDir.z > 0.0f)
306 localDir.Normalize();
307 if (localDir.z >= m_cosConeAngle)
318 RtPoint3
const& offsetP, RtVector3
const& segmentDir,
319 float& minT,
float& maxT)
const
323 float ts = lightN.Dot(offsetP + minT * segmentDir - lightP);
324 float te = lightN.Dot(offsetP + maxT * segmentDir - lightP);
325 if (ts < 0.0f && te < 0.0f)
return 0.0f;
328 float planeT = lightN.Dot(lightP - offsetP) / segmentDir.Dot(lightN);
338 if (m_cosConeAngle < 1e-5f)
return 1.0f;
340 float vDn = segmentDir.Dot(lightN);
341 RtVector3 lToP = offsetP - lightP;
342 float c2 = vDn * vDn - segmentDir.Dot(segmentDir) * m_cosConeAngle * m_cosConeAngle;
343 if (c2 == 0.0f)
return 0.0f;
344 float lpDn = lToP.Dot(lightN);
345 float c1 = vDn * lpDn - lToP.Dot(segmentDir) * m_cosConeAngle * m_cosConeAngle;
346 float c0 = lpDn * lpDn - lToP.Dot(lToP) * m_cosConeAngle * m_cosConeAngle;
348 float delta = c1*c1 - c0*c2;
352 float rootDelta = sqrtf(delta);
357 t0 = (-c1 - rootDelta) / c2;
358 t1 = (-c1 + rootDelta) / c2;
362 t1 = (-c1 - rootDelta) / c2;
363 t0 = (-c1 + rootDelta) / c2;
367 minT = std::max(minT, t0);
368 maxT = std::min(maxT, t1);
384 RixIES::calcLongitude(
float x,
float y,
bool isExr)
const
390 float s = atan2f(y, x);
405 PRMAN_INLINE
void RixIES::calcLatLongParam(
414 float x, y, z, len, zlen;
415 for (
int i = 0; i < n; i++, s++, t++, dir += 3)
423 len = x * x + y * y + z * z;
425 len = 1.f / sqrtf(len);
437 *t = 0.5f - asinf(zlen) * 1.0f /
F_PI;
438 *s = calcLongitude(x, y, openEXR);