37 #ifndef RixShadingUtils_h
38 #define RixShadingUtils_h
52 #include "RiTypesHelper.h"
53 #include "RixPredefinedStrings.hpp"
65 #define F_PI (3.14159265f)
66 #define F_TWOPI (6.283185307f)
67 #define F_FOURPI (12.56637061f)
68 #define F_INVPI (0.318309886f)
69 #define F_INVPISQ (0.1013211836f)
70 #define F_INVTWOPI (0.15915494309f)
71 #define F_INVFOURPI (0.0795774715f)
72 #define F_PIDIV2 (1.57079632679f)
73 #define F_PIDIV4 (0.785398163397f)
74 #define F_DEGTORAD (0.017453292520f)
75 #define F_RADTODEG (57.2957795131f)
76 #define F_INVLN2 (1.44269504089f)
77 #define F_INVLN4 (0.72134752f)
78 #define F_LOG2E (1.44269504088896f)
79 #define F_SQRT2 (1.41421356237f)
80 #define F_MAXDIST (1.0e10f)
81 #define F_SQRTMIN (1.0842021721e-19f)
82 #define F_MINDIVISOR (1.0e-6f)
85 namespace RixConstants
90 static const RtColorRGB k_ZeroRGB(0.0f);
91 static const RtColorRGB k_OneRGB(1.0f);
92 static const RtFloat3 k_ZeroF3(0.0f);
93 static const RtFloat3 k_OneF3(1.0f);
94 static const RtFloat2 k_ZeroF2(0.0f);
95 static const RtFloat2 k_OneF2(1.0f);
96 static const float k_ZeroF(0.0f);
97 static const float k_OneF(1.0f);
98 static const float k_Infinity(1e+38f);
99 static const RtMatrix4x4 k_IdentityMatrix(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1);
114 _BitScanForward64( &r, v );
116 #else // Linux, OS X, gcc or clang
117 return __builtin_ctzll( v );
138 template <
typename T>
157 return std::isfinite(x);
178 return x < y ? x : y;
188 return x < y ? x : y;
198 return x > y ? x : y;
208 return x > y ? x : y;
218 return x < min ? min : (x > max) ? max : x;
228 return x < min ? min : (x > max) ? max : x;
238 return (x - floorf(x));
249 float n = float(
int(x/y));
250 float result = x - n*y;
251 if (result < 0.0f) result += y;
299 float etaSq = eta * eta;
300 float rcos_tSq = 1.0f - etaSq * (1.0f - rcos_i * rcos_i);
301 if (rcos_tSq <= 0.0f)
305 float rcos_t = std::sqrt(rcos_tSq);
306 float rpar = (eta * rcos_t - rcos_i) / (eta * rcos_t + rcos_i);
307 float rper = (eta * rcos_i - rcos_t) / (eta * rcos_i + rcos_t);
308 *Kr = 0.5f * (rpar * rpar + rper * rper);
322 RtVector3* Rn = NULL,
323 RtVector3* Tn = NULL)
325 float VdN = Dot(Nn, Vn);
342 *Rn = 2.0f * VdN * Nn - Vn;
344 float etaSq = eta * eta;
345 float rcos_tSq = 1.0f - etaSq * (1.0f - rcos_i * rcos_i);
346 if (rcos_tSq <= 0.0f)
350 *Tn = RtVector3(0.0f);
354 float rcos_t = std::sqrt(rcos_tSq);
355 float rpar = (eta * rcos_t - rcos_i) / (eta * rcos_t + rcos_i);
356 float rper = (eta * rcos_i - rcos_t) / (eta * rcos_i + rcos_t);
357 *Kr = 0.5f * (rpar * rpar + rper * rper);
359 *Tn = sign * (eta * rcos_i - rcos_t) * Nn - eta * Vn;
383 for (
int i = 0; i < nPts; ++i)
386 Kt[i] = 1.0f - Kr[i];
391 for (
int i = 0; i < nPts; ++i)
394 Kt[i] = 1.0f - Kr[i];
416 kappa = 1.0f / kappa;
417 float cosSq = VdN * VdN;
418 float cos2eta = 2.0f * eta * VdN;
419 float t0 = eta * eta + kappa * kappa;
420 float t1 = t0 * cosSq;
421 float rperp = (t0 - cos2eta + cosSq) / (t0 + cos2eta + cosSq);
422 float rpar = (t1 - cos2eta + 1.0f) / (t1 + cos2eta + 1.0f);
423 *Kr = 0.5f * (rpar + rperp);
444 float cosSq = VdN * VdN, sinSq = 1.0f - cosSq, sin4 = sinSq * sinSq;
446 float t0 = eta * eta - kappa * kappa - sinSq;
447 float aSqPlusbSq = std::sqrt(t0 * t0 + 4.0f * kappa * kappa * eta * eta);
448 float a = std::sqrt(0.5f * (aSqPlusbSq + t0));
450 float t1 = aSqPlusbSq + cosSq;
451 float t2 = 2.0f * a * VdN;
453 float rperpSq = (t1 - t2) / (t1 + t2);
455 float t3 = aSqPlusbSq * cosSq + sin4;
456 float t4 = t2 * sinSq;
458 float rparSq = rperpSq * (t3 - t4) / (t3 + t4);
460 *Kr = 0.5f * (rperpSq + rparSq);
482 RtVector3* Rn = NULL)
484 float VdN = Dot(Nn, Vn);
487 *Rn = 2.0f * VdN * Nn - Vn;
494 RtColorRGB
const& eta,
495 RtColorRGB
const& kappa,
504 if (eta.g == eta.r && kappa.g == kappa.r)
508 if (eta.b == eta.r && kappa.b == kappa.r)
510 else if (eta.b == eta.g && kappa.b == kappa.g)
528 RtColorRGB
const& eta,
529 RtColorRGB
const& kappa,
531 RtVector3* Rn = NULL)
533 float VdN = Dot(Nn, Vn);
536 *Rn = 2.0f * VdN * Nn - Vn;
555 float f = 1.0f - NdV;
565 PRMAN_INLINE RtVector3
568 float VdN = Dot(Nn, Vn);
569 return 2.0f * VdN * Nn - Vn;
577 PRMAN_INLINE RtVector3
578 RixReflect(RtVector3
const& Vn, RtVector3
const& Nn,
float VdN)
580 return 2.0f * VdN * Nn - Vn;
591 RixRefract(
const RtVector3& Vn,
const RtNormal3& Nn,
float eta, RtVector3& Tn)
594 float VdN = Dot(Vn, Nn);
608 float etaSq = eta * eta;
609 float rcos_tSq = 1.0f - etaSq * (1.0f - rcos_i * rcos_i);
610 if (rcos_tSq <= 0.0f)
612 Tn = RtVector3(0.0f);
617 float rcos_t = std::sqrt(rcos_tSq);
618 Tn = sign * (eta * rcos_i - rcos_t) * Nn - eta * Vn;
625 PRMAN_INLINE RtNormal3
629 float* VdotNf = NULL)
632 float d = Dot(Vn, Nn);
649 PRMAN_INLINE RtNormal3
653 float* VdotNb = NULL)
656 float d = Dot(Vn, Nn);
673 #define ALMOSTZERO 0.005f
694 assert(n.IsUnitLength());
695 assert(t0.IsUnitLength());
696 assert(t1.IsUnitLength());
702 float z = std::sqrt(xi.y);
703 float r = std::sqrt(std::max(0.0f, 1.0f - xi.y));
704 float x = r * cosf(e1);
705 float y = r * sinf(e1);
709 outDir = x * t0 + y * t1 + z * n;
712 assert(outDir.IsUnitLength());
729 n.CreateOrthonormalBasis(t0, t1);
752 float r = std::sqrt(std::max(0.0f, 1.0f - z * z));
753 float x = r * cosf(e1);
754 float y = r * sinf(e1);
758 outDir = x * t0 + y * t1 + z * n;
776 n.CreateOrthonormalBasis(t0, t1);
790 const RtVector3& n,
const RtVector3& t0,
791 const RtVector3& t1, RtVector3& outDir,
795 float cosAngle = cosf(coneAngle);
796 float z = xi.y * (1.0f - cosAngle) + cosAngle;
797 float r = std::sqrt(std::max(0.0f, 1.0f - z * z));
798 float x = r * cosf(e1);
799 float y = r * sinf(e1);
803 outDir = x * t0 + y * t1 + z * n;
816 const RtFloat2& xi,
const float coneAngle,
822 n.CreateOrthonormalBasis(t0, t1);
831 PRMAN_INLINE RtVector3
835 outDir.z = 2.0f * xi.y - 1.0f;
836 float sinTheta = 1.0f - outDir.z * outDir.z;
840 sinTheta = std::sqrt(sinTheta);
842 outDir.x = sinTheta * cosf(phi);
843 outDir.y = sinTheta * sinf(phi);
865 if (xi < thresholds[0])
871 for (
int i = 1; i < numThresholds; i++)
873 if (thresholds[i - 1] <= xi && xi < thresholds[i])
875 xi = (xi - thresholds[i - 1]) / (thresholds[i] - thresholds[i - 1]);
880 float lastThres = thresholds[numThresholds - 1];
881 xi = (xi - lastThres) / (1.0f - lastThres);
882 return numThresholds;
893 const RtVector3& dir,
897 return (N.Dot(dir) < 0.0f) ? biasT : biasR;
904 PRMAN_INLINE RtPoint3
908 const RtVector3& dir,
912 float biasAmt =
RixTraceBias(org, N, dir, biasR, biasT);
918 return org + biasAmt * dir;
930 sincosf(phi, sinPhi, cosPhi);
931 #elif (defined(OSX) && defined(__clang__))
932 __sincosf(phi, sinPhi, cosPhi);
943 PRMAN_INLINE RtVector3
950 return RtVector3(sinTheta * cosPhi, sinTheta * sinPhi, cosTheta);
957 PRMAN_INLINE RtVector3
960 float sinPhi, cosPhi;
971 PRMAN_INLINE RtVector3
979 result.x = in.x * X.x + in.y * Y.x + in.z * Z.x;
980 result.y = in.x * X.y + in.y * Y.y + in.z * Z.y;
981 result.z = in.x * X.z + in.y * Y.z + in.z * Z.z;
986 PRMAN_INLINE RtVector3
1002 PRMAN_INLINE RtVector3
1004 RtVector3
const& in,
1009 return RtVector3(Dot(in, X), Dot(in, Y), Dot(in, Z));
1016 template <
typename T>
1020 return (1.0f - m) * v0 + m * v1;
1028 template <
typename T>
1040 x3 = x1 + dx * t * t * (3.0f - 2.0f * t);
1051 template <
typename T>
1063 x3 = x1 + dx * t * t;
1074 template <
typename T>
1086 x3 = t * dx * (2.0f - t) + x1;
1103 return val < min ? 0.0f : 1.0f;
1118 : (val >= max ? 1.0f : (val - min) / (max - min));
1125 : (val >= min ? 1.0f : (val - max) / (min - max)));
1146 val = (val - min) / (max - min);
1154 val = 1.0f - (val - max) / (min - max);
1159 return val * val * (3.0f - 2.0f * val);
1177 val = 1.0f - (val - min) / (max - min);
1185 val = (val - max) / (min - max);
1190 return std::pow(2.0f, -8.0f * val * val);
1216 if (solidangle > 1.840302f)
1220 float omega_div_2pi = solidangle * 0.15915494f;
1223 float cosTheta = 1.0f - omega_div_2pi;
1224 assert(cosTheta > 0.0f);
1227 return std::sqrt(1.0f - cosTheta * cosTheta) / cosTheta;
1241 #define RixAlloca(s) alloca(s)
1251 RtNormal3
const& Nf,
1252 RtVector3
const& Tn,
1260 assert(Nf.IsUnitLength());
1261 assert(Tn.IsUnitLength());
1263 if (Nf.AbsDot(Tn) < 0.995f)
1274 Nf.CreateOrthonormalBasis(TX, TY);
1294 float orthonormalCheck = z.Dot(Cross(x, y));
1295 if (orthonormalCheck < 0.98f)
1297 const RtColorRGB r = RtColorRGB(1, 0, 0);
1298 const RtColorRGB g = RtColorRGB(0, 1, 0);
1299 const RtColorRGB b = RtColorRGB(0, 0, 1);
1322 int numPts = sCtx->
numPts;
1325 for (
int i = 0; i < numPts; i++)
1327 newu[i] = u[i] + du[i];
1345 int numPts = sCtx->
numPts;
1348 for (
int i = 0; i < numPts; i++)
1350 newv[i] = v[i] + dv[i];
1370 int numPts = sCtx->
numPts;
1373 RtVector3
const* dPdu;
1374 RtVector3
const* dPdv;
1375 RtVector3
const* Norig;
1376 RtNormal3
const* Ngn;
1377 RtNormal3
const* Naon;
1387 RtNormal3 fill(0,0,0);
1388 RtNormal3
const *Nuser;
1392 for (
int i = 0; i < numPts; i++)
1395 if(disp[i] == 0.0f && dispU[i] == 0.0f && dispV[i] == 0.0f)
1405 RtPoint3 P0 = Norig[i] * disp[i];
1406 RtPoint3 P1 = du[i] * dPdu[i] + Norig[i] * dispU[i];
1407 RtPoint3 P2 = dv[i] * dPdv[i] + Norig[i] * dispV[i];
1408 Nn[i] = Cross(P1 - P0, P2 - P0);
1413 RtNormal3 computedNgn = Cross(du[i] * dPdu[i], dv[i] * dPdv[i]);
1414 computedNgn.Normalize();
1416 float const dotNg = Dot(computedNgn, Ngn[i]);
1422 RtNormal3 Nuser_i = Nuser[i];
1423 RtNormal3 Naon_i = Naon[i];
1433 Nuser_i.Normalize();
1437 RtNormal3 delta = Nuser_i - Naon_i;
1440 if (delta != RtNormal3(0.0f))
1455 computedNgn = -computedNgn;
1458 RtNormal3
const delta = Norig[i] - computedNgn;
1462 if (delta != RtNormal3(0.0f))
1483 static const RtUString k_matteName(
"Ri:Matte");
1484 static const int k_matteLen =
sizeof(float);
1485 static const int k_matteDef = 0;
1487 int matte = k_matteDef;
1497 matteRet = state->GetAttribute(
1498 k_matteName, &matteVal, k_matteLen, &matteType, &matteCount);
1502 else if (matteCount == 1)
1503 matte = (int)matteVal;
1517 static const RtUString k_holdoutName(
"trace:holdout");
1518 static const int k_holdoutLen =
sizeof(float);
1519 static const int k_holdoutDef = 0;
1520 int holdout = k_holdoutDef;
1527 int holdoutRet = state->GetAttribute(
1528 k_holdoutName, &holdoutVal, k_holdoutLen, &holdoutType, &holdoutCount);
1532 holdout = (int)holdoutVal;
1538 PRMAN_INLINE
unsigned long
1539 RixImod(
const unsigned long a,
const unsigned long b)
1541 unsigned long n = a/b;
1557 RixHash(
const char *bufPtr,
unsigned long range=65535)
1559 unsigned long hash = 5381;
1561 while ((c =
int(*bufPtr++)))
1562 hash = ((hash << 5) + hash) ^ c;
1564 return float(
RixImod(hash,range));
1572 PRMAN_INLINE RtColorRGB
1573 RixLerpRGB(RtColorRGB
const &a, RtColorRGB
const &b,
float const mix)
1575 RtColorRGB result = b + mix * (a - b);
1576 result.r = a.r < b.r ?
RixClamp(result.r, a.r, b.r) :
RixClamp(result.r, b.r, a.r);
1577 result.g = a.g < b.g ?
RixClamp(result.g, a.g, b.g) :
RixClamp(result.g, b.g, a.g);
1578 result.b = a.b < b.b ?
RixClamp(result.b, a.b, b.b) :
RixClamp(result.b, b.b, a.b);
1594 if (Dot(Vn, Ngn) >= 0.0f)
1596 float VdotN = Dot(Vn, Nn);
1601 Nn -= amount * 1.01f * VdotN * Vn;
1607 PRMAN_INLINE RtFloat
1613 float cos_d =
RixMin(std::abs(shadingNormal.Dot(bumpNormal)), 1.0f);
1614 float tan2_d = (1.0f - cos_d * cos_d) / (cos_d * cos_d);
1615 float alpha2 =
RixClamp(0.125f * tan2_d , 0.0f , 1.0f);
1617 float cos_i =
RixMax(std::abs(shadingNormal.Dot(Ln)), 1e-6f);
1618 float tan2_i_square = (cos_i * cos_i);
1619 float tan2_i = (1.0f - cos_i * cos_i) / tan2_i_square;
1620 if (tan2_i_square < 1e-6f)
1626 return (2.0f / (1.0f + sqrtf(1.0f + alpha2 * tan2_i)));
1632 PRMAN_INLINE RtFloat
1635 float instanceId = 0;
1638 rstate->
GetAttribute(RtUString(
"user:procprimid"), &instanceId,
sizeof(RtFloat), &type, &count);
1648 float incidentRayRadius,
float incidentRaySpread)
1650 float sinTheta = std::max(fabsf(incidentRaySpread), fabsf(incidentRayRadius*curvature));
1651 sinTheta *= multiplier;
1653 if (sinTheta == 0.0f)
return 0.0f;
1655 sinTheta = std::min(1.0f, sinTheta);
1656 float cosTheta = sqrtf(std::max(0.0f, 1.0f-sinTheta*sinTheta));
1659 float theta = (sinTheta < 0.01f) ? sinTheta : asinf(sinTheta);
1661 float sigmaSq = (theta*theta-2.0f) + 2.0f*cosTheta*(theta/sinTheta);
1664 return std::max(0.0f, 2.0f*sigmaSq);
1679 return sqrtf(roughness*roughness + rayCurvatureRoughnessSq);
1683 #endif // RixShadingUtils_h