RenderMan API  23.0
RixShadingUtils.h
Go to the documentation of this file.
1 /*
2 # ------------------------------------------------------------------------------
3 #
4 # Copyright (c) 1986-2019 Pixar. All rights reserved.
5 #
6 # The information in this file (the "Software") is provided for the exclusive
7 # use of the software licensees of Pixar ("Licensees"). Licensees have the
8 # right to incorporate the Software into other products for use by other
9 # authorized software licensees of Pixar, without fee. Except as expressly
10 # permitted herein, the Software may not be disclosed to third parties, copied
11 # or duplicated in any form, in whole or in part, without the prior written
12 # permission of Pixar.
13 #
14 # The copyright notices in the Software and this entire statement, including the
15 # above license grant, this restriction and the following disclaimer, must be
16 # included in all copies of the Software, in whole or in part, and all permitted
17 # derivative works of the Software, unless such copies or derivative works are
18 # solely in the form of machine-executable object code generated by a source
19 # language processor.
20 #
21 # PIXAR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
22 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL PIXAR BE
23 # LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
24 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
25 # OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
26 # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. IN NO CASE WILL
27 # PIXAR'S TOTAL LIABILITY FOR ALL DAMAGES ARISING OUT OF OR IN CONNECTION WITH
28 # THE USE OR PERFORMANCE OF THIS SOFTWARE EXCEED $50.
29 #
30 # Pixar
31 # 1200 Park Ave
32 # Emeryville CA 94608
33 #
34 # ------------------------------------------------------------------------------
35 */
36 
37 
38 #ifndef RixShadingUtils_h
39 #define RixShadingUtils_h
40 
41 // RixShadingUtils:
42 //
43 // Utility/portability functions for RixShading plugins.
44 //
45 
46 #include <algorithm> // for max
47 #include <cassert> // for assert
48 #include <cmath> // for sqrt, cosf, sinf, floorf, etc
49 #include <cstddef> // for NULL
50 #include "RixInterfaces.h" // for RixRenderState, etc
51 #include "RixShading.h" // for RixShadingContext, etc
52 #include "prmanapi.h" // for PRMAN_INLINE
53 #include "ri.h" // for RtVector3, RtColorRGB, etc
54 #include "RixPredefinedStrings.hpp" // for k_N primvar
55 
56 #if defined(WIN32)
57 #include <malloc.h>
58 #include <intrin.h>
59 #else
60 #include <alloca.h>
61 #endif
62 
63 
64 // single-precision floating point constants
65 // clang-format off
66 #define F_PI (3.14159265f)
67 #define F_TWOPI (6.283185307f)
68 #define F_FOURPI (12.56637061f)
69 #define F_INVPI (0.318309886f)
70 #define F_INVPISQ (0.1013211836f)
71 #define F_INVTWOPI (0.15915494309f)
72 #define F_INVFOURPI (0.0795774715f)
73 #define F_PIDIV2 (1.57079632679f)
74 #define F_PIDIV4 (0.785398163397f)
75 #define F_DEGTORAD (0.017453292520f)
76 #define F_RADTODEG (57.2957795131f)
77 #define F_INVLN2 (1.44269504089f)
78 #define F_INVLN4 (0.72134752f)
79 #define F_LOG2E (1.44269504088896f)
80 #define F_SQRT2 (1.41421356237f)
81 #define F_MAXDIST (1.0e10f)
82 #define F_SQRTMIN (1.0842021721e-19f)
83 #define F_MINDIVISOR (1.0e-6f)
84 // clang-format on
85 
86 namespace RixConstants
87 {
88 
89 // some additional constants
90 
91 static const RtColorRGB k_ZeroRGB(0.0f);
92 static const RtColorRGB k_OneRGB(1.0f);
93 static const RtFloat3 k_ZeroF3(0.0f);
94 static const RtFloat3 k_OneF3(1.0f);
95 static const RtFloat2 k_ZeroF2(0.0f);
96 static const RtFloat2 k_OneF2(1.0f);
97 static const float k_ZeroF(0.0f);
98 static const float k_OneF(1.0f);
99 static const RtMatrix4x4 k_IdentityMatrix(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1);
100 
101 } // namespace RixConstants
102 
103 // Returns the zero-based index of the first (least significant) bit set in
104 // a 64-bit integer. Compiles to a single quick instruction via intrinsics.
105 //
106 // NOTE: The result is undefined if the input is zero!
107 //
108 PRMAN_INLINE unsigned int RixFindFirstSetBit(unsigned long long v)
109 {
110 #if defined(WIN32)
111  unsigned long r = 0;
112  _BitScanForward64( &r, v );
113  return r;
114 #else // Linux, OS X, gcc or clang
115  return __builtin_ctzll( v );
116 #endif
117 }
118 
119 PRMAN_INLINE float
120 RixDegreesToRadians(float degrees)
121 {
122  return degrees * F_DEGTORAD;
123 }
124 
125 PRMAN_INLINE float
127 {
128  return rads * F_RADTODEG;
129 }
130 
131 template <typename T>
132 PRMAN_INLINE T
134 {
135  if (x > T(0))
136  return T(1);
137  if (x < T(0))
138  return T(-1);
139  return T(0);
140 }
141 
142 // RixIsFinite is helpful in diagnosing bugs that produce NaNs
143 // and other exotic breads.
144 PRMAN_INLINE int
145 RixIsFinite(float x)
146 {
147 #if defined(WIN32)
148  return (x == x) && (x != std::numeric_limits<float>::infinity()) &&
149  (x != -std::numeric_limits<float>::infinity());
150 #else
151  return std::isfinite(x);
152 #endif
153 }
154 
155 PRMAN_INLINE int
157 {
158  return RixIsFinite(v.x) && RixIsFinite(v.y) && RixIsFinite(v.z);
159 }
160 
161 PRMAN_INLINE float
162 RixMin(float x, float y)
163 {
164  return x < y ? x : y;
165 }
166 
167 PRMAN_INLINE int
168 RixMin(int x, int y)
169 {
170  return x < y ? x : y;
171 }
172 
173 PRMAN_INLINE float
174 RixMax(float x, float y)
175 {
176  return x > y ? x : y;
177 }
178 
179 PRMAN_INLINE int
180 RixMax(int x, int y)
181 {
182  return x > y ? x : y;
183 }
184 
185 PRMAN_INLINE float
186 RixClamp(float x, float min, float max)
187 {
188  return x < min ? min : (x > max) ? max : x;
189 }
190 
191 PRMAN_INLINE int
192 RixClamp(int x, int min, int max)
193 {
194  return x < min ? min : (x > max) ? max : x;
195 }
196 
197 PRMAN_INLINE float
199 {
200  return (x - floorf(x));
201 }
202 
203 // RixMod is a straight port of RSL's mod() shadeop.
204 // It is NOT equivalent to fmodf() from math.h.
205 //
206 PRMAN_INLINE float
207 RixMod(float x, float y)
208 {
209  float n = float(int(x/y));
210  float result = x - n*y;
211  if (result < 0.f) result += y;
212  return result;
213 }
214 
215 /*
216  * RixFresnelDielectric
217  *
218  * Calculate the reflection coefficient based on the following formula:
219  * Kr = (rpar * rpar + rper * rper) / 2.0
220  *
221  * where:
222  * rcos_i = abs(N.V) -- with V == -I
223  * rcos_t = sqrt( 1.0 - eta * eta * ( 1.0 - rcos_i * rcos_i ) )
224  * rpar = ( eta * rcos_t - rcos_i ) / ( eta * rcos_t + rcos_i )
225  * rper = ( eta * rcos_i - rcos_t ) / ( eta * rcos_i + rcos_t )
226  *
227  * and eta is the relative index of refraction, the ratio of
228  * refraction indices ior_i / ior_t
229  *
230  * Subscript 'i' denotes the side the ray came from (incident direction,
231  * ie. the direction V points into); subscript 't' denotes the other
232  * (refraction/transmission) side.
233  *
234  * (The refraction (transmission) coefficient could be computed as:
235  * Kt = (1.0 - Kr) * rcos_i / rcos_t
236  * but usually we just set Kt = 1 - Kr.)
237  *
238  * The reflected and transmitted (unit) vectors are optionally calculated
239  * using the following formula:
240  * R = I - 2.0 * (N.I) * N
241  * = -V + 2.0 * (N.V) * N
242  * = 2.0 * (N.V) * N - V;
243  * T = eta * I + (eta * rcos_i - rcos_t) * N
244  * = (eta * rcos_i - rcos_t) * N - eta * V;
245  *
246  * All vectors have unit length. Input Vn and results Rn and Tn all point
247  * away from the surface. Kr is between 0 and 1.
248  */
249 PRMAN_INLINE void
250 RixFresnelDielectric(float VdN, float eta, float* Kr)
251 {
252  float rcos_i;
253  if (VdN < 0.f)
254  rcos_i = -VdN;
255  else
256  rcos_i = VdN;
257 
258  float etaSq = eta * eta;
259  float rcos_tSq = 1.0f - etaSq * (1.0f - rcos_i * rcos_i);
260  if (rcos_tSq <= 0.0f)
261  *Kr = 1.0f; // total internal reflection
262  else
263  {
264  float rcos_t = std::sqrt(rcos_tSq);
265  float rpar = (eta * rcos_t - rcos_i) / (eta * rcos_t + rcos_i);
266  float rper = (eta * rcos_i - rcos_t) / (eta * rcos_i + rcos_t);
267  *Kr = 0.5f * (rpar * rpar + rper * rper);
268  }
269 }
270 
271 PRMAN_INLINE void
273  const RtVector3& Vn,
274  const RtNormal3& Nn,
275  float eta,
276  float* Kr,
277  RtVector3* Rn = NULL,
278  RtVector3* Tn = NULL)
279 {
280  float VdN = Dot(Nn, Vn);
281  float rcos_i, sign;
282  if (VdN < 0.f)
283  {
284  rcos_i = -VdN;
285  sign = -1.f;
286  }
287  else
288  {
289  rcos_i = VdN;
290  sign = 1.f;
291  }
292 
293  // reflection direction, formula works if Nn and Vn are on
294  // opposite or same sides
295  if (Rn)
296  *Rn = 2.0f * VdN * Nn - Vn;
297 
298  float etaSq = eta * eta;
299  float rcos_tSq = 1.0f - etaSq * (1.0f - rcos_i * rcos_i);
300  if (rcos_tSq <= 0.0f)
301  {
302  *Kr = 1.0f; // total internal reflection
303  if (Tn)
304  *Tn = RtVector3(0.0f); // no refraction (transmission) dir
305  }
306  else
307  {
308  float rcos_t = std::sqrt(rcos_tSq);
309  float rpar = (eta * rcos_t - rcos_i) / (eta * rcos_t + rcos_i);
310  float rper = (eta * rcos_i - rcos_t) / (eta * rcos_i + rcos_t);
311  *Kr = 0.5f * (rpar * rpar + rper * rper);
312  if (Tn)
313  *Tn = sign * (eta * rcos_i - rcos_t) * Nn - eta * Vn;
314  }
315 }
316 
317 /*
318  * RixFresnelDielectric:
319  * a varying version of RixFresnelDielectric
320  */
322  RixShadingContext& sCtx,
323  float eta,
324  float* Kr,
325  float* Kt, // reflect and refract coeffs
326  RtVector3* R,
327  RtVector3* T) // reflect and refract dirs
328 {
329  RtNormal3 const* Nn;
330  RtVector3 const* Vn;
333  int nPts = sCtx.numPts;
334  if (R && T)
335  {
336  for (int i = 0; i < nPts; ++i)
337  {
338  RixFresnelDielectric(Vn[i], Nn[i], eta, Kr + i, R + i, T + i);
339  Kt[i] = 1.0f - Kr[i];
340  }
341  }
342  else
343  {
344  for (int i = 0; i < nPts; ++i)
345  {
346  RixFresnelDielectric(Vn[i], Nn[i], eta, Kr + i);
347  Kt[i] = 1.0f - Kr[i];
348  }
349  }
350 }
351 
352 /*
353  * RixFresnelConductor:
354  * calculate the reflection coefficient for a conductor (metal)
355  * incoming eta, kappa are assumed ior_i / ior_t (for consistency
356  * with pre-existing dielectric convention). Internally eta and
357  * kappa are ior_t / ior_i
358  */
359 PRMAN_INLINE void
360 RixFresnelConductorApprox(float VdN, float eta, float kappa, float* Kr)
361 {
362  if (kappa > .01f)
363  {
364  // approximation for dielectric/conductor interface
365  if (eta > 0.f)
366  eta = 1.f / eta;
367 
368  kappa = 1.f / kappa;
369  float cosSq = VdN * VdN;
370  float cos2eta = 2.f * eta * VdN;
371  float t0 = eta * eta + kappa * kappa;
372  float t1 = t0 * cosSq;
373  float rperp = (t0 - cos2eta + cosSq) / (t0 + cos2eta + cosSq);
374  float rpar = (t1 - cos2eta + 1.f) / (t1 + cos2eta + 1.f);
375  *Kr = 0.5f * (rpar + rperp);
376  }
377  else
378  {
379  // when kappa is small, we're dielectric
380  RixFresnelDielectric(VdN, eta, Kr);
381  }
382 }
383 
384 // RixFresnelConductor:
385 // more expensive computation of fresnel conductor, usually the
386 // approximation is quite good (except for small kappa).
387 // See: Moeller's Optics
388 PRMAN_INLINE void
389 RixFresnelConductor(float VdN, float eta, float kappa, float* Kr)
390 {
391  if (kappa > .01f)
392  {
393  float cosSq = VdN * VdN, sinSq = 1.f - cosSq, sin4 = sinSq * sinSq;
394 
395  float t0 = eta * eta - kappa * kappa - sinSq;
396  float aSqPlusbSq = std::sqrt(t0 * t0 + 4.f * kappa * kappa * eta * eta);
397  float a = std::sqrt(0.5f * (aSqPlusbSq + t0));
398 
399  float t1 = aSqPlusbSq + cosSq;
400  float t2 = 2.0f * a * VdN;
401 
402  float rperpSq = (t1 - t2) / (t1 + t2);
403 
404  float t3 = aSqPlusbSq * cosSq + sin4;
405  float t4 = t2 * sinSq;
406 
407  float rparSq = rperpSq * (t3 - t4) / (t3 + t4);
408 
409  *Kr = 0.5f * (rperpSq + rparSq);
410  }
411  else
412  {
413  // when kappa is small, we're dielectric
414  RixFresnelDielectric(VdN, eta, Kr);
415  }
416 }
417 
418 /*
419  * RixFresnelConductor:
420  * a version of RixFresnelConductor with the same interface
421  * as RixFresnelDielectric.
422  */
423 PRMAN_INLINE void
425  const RtVector3& Vn,
426  const RtNormal3& Nn,
427  float eta,
428  float kappa,
429  float* Kr,
430  RtVector3* Rn = NULL)
431 {
432  float VdN = Dot(Nn, Vn);
433  RixFresnelConductorApprox(VdN, eta, kappa, Kr);
434  if (Rn)
435  *Rn = 2.0f * VdN * Nn - Vn;
436 }
437 
438 PRMAN_INLINE void
440  float VdN,
441  RtColorRGB const& eta,
442  RtColorRGB const& kappa,
443  RtColorRGB* Kr)
444 {
445  RtColorRGB kr;
446  RixFresnelConductorApprox(VdN, eta.r, kappa.r, &kr.r);
447 
448  // Make sure we compute other bands only when necessary.
449  // if eta and kappa are monochromatic, we only compute one band and the cost
450  // is the same as a RixFresnelDielectric.
451  if (eta.g == eta.r && kappa.g == kappa.r)
452  kr.g = kr.r;
453  else
454  RixFresnelConductorApprox(VdN, eta.g, kappa.g, &kr.g);
455  if (eta.b == eta.r && kappa.b == kappa.r)
456  kr.b = kr.r;
457  else if (eta.b == eta.g && kappa.b == kappa.g)
458  kr.b = kr.g;
459  else
460  RixFresnelConductorApprox(VdN, eta.b, kappa.b, &kr.b);
461 
462  *Kr = kr;
463 }
464 
465 /*
466  * RixFresnelConductor:
467  * compute the reflection coefficient for three spectral bands (RGB).
468  * Similar interface as RixFresnelDielectric.
469  */
470 PRMAN_INLINE void
472  RtVector3 const& Vn,
473  RtNormal3 const& Nn,
474  RtColorRGB const& eta,
475  RtColorRGB const& kappa,
476  RtColorRGB* Kr,
477  RtVector3* Rn = NULL)
478 {
479  float VdN = Dot(Nn, Vn);
480  RixFresnelConductor(VdN, eta, kappa, Kr);
481  if (Rn)
482  *Rn = 2.0f * VdN * Nn - Vn;
483 }
484 
485 // Schlick's approximate Fresnel (only the weighting function).
486 // 0 at normal incidence angle. 1 at grazing angle.
487 // F(cosTheta, rper) = rper + (1-rper) * RixSchlickFresnelWeight
488 // where rper = (ior1-ior2)^2 / (ior1+ior2)
489 PRMAN_INLINE float
491 {
492  if (NdV <= 0.f)
493  return 1.f;
494  if (NdV >= 1.f)
495  return 0.f; // dot prod can be slightly larger than 1.0
496  float f = 1.0f - NdV;
497  float f2 = f * f;
498  return f2 * f2 * f; // std::pow(f, 5); -- result between 0.0 and 1.0
499 }
500 
501 // Reflection direction: standalone computation, useful when Fresnel weights
502 // aren't needed
504 RixReflect(const RtVector3& Vn, const RtNormal3& Nn)
505 {
506  float VdN = Dot(Nn, Vn);
507  return 2.0f * VdN * Nn - Vn; // reflection direction
508 }
509 
510 // Reflection direction: an alternate interface, faster when VdN is already
511 // available
513 RixReflect(RtVector3 const& Vn, RtVector3 const& Nn, float VdN)
514 {
515  return 2.0f * VdN * Nn - Vn; // reflection direction
516 }
517 
518 // Refraction direction: standalone computation using Snell's law.
519 // All vectors have unit length. Input Vn and result Tn all point
520 // away from the surface. Return value is 1 and Tn = (0,0,0) if total
521 // internal reflection occured.
522 PRMAN_INLINE int
523 RixRefract(const RtVector3& Vn, const RtNormal3& Nn, float eta, RtVector3& Tn)
524 {
525  int err = 0;
526  float VdN = Dot(Vn, Nn);
527  float rcos_i, sign;
528  if (VdN < 0.f)
529  {
530  rcos_i = -VdN;
531  sign = -1.f;
532  }
533  else
534  {
535  rcos_i = VdN;
536  sign = 1.f;
537  }
538 
539  float etaSq = eta * eta;
540  float rcos_tSq = 1.0f - etaSq * (1.0f - rcos_i * rcos_i);
541  if (rcos_tSq <= 0.0f)
542  {
543  Tn = RtVector3(0.0f);
544  err = 1; // total internal reflection: no refraction
545  }
546  else
547  {
548  float rcos_t = std::sqrt(rcos_tSq);
549  Tn = sign * (eta * rcos_i - rcos_t) * Nn - eta * Vn; // refraction dir
550  Tn.Normalize();
551  }
552  return err;
553 }
554 
557  RtVector3 const& Vn,
558  RtNormal3 const& Nn,
559  float* VdotNf = NULL)
560 {
561  RtNormal3 Nf;
562  float d = Dot(Vn, Nn);
563  if (d > 0.f)
564  Nf = Nn;
565  else
566  {
567  Nf = -Nn;
568  d = -d;
569  }
570  if (VdotNf)
571  *VdotNf = d;
572  return Nf;
573 }
574 
577  RtVector3 const& Vn,
578  RtNormal3 const& Nn,
579  float* VdotNb = NULL)
580 {
581  RtNormal3 Nb;
582  float d = Dot(Vn, Nn);
583  if (d < 0.f)
584  Nb = Nn;
585  else
586  {
587  Nb = -Nn;
588  d = -d;
589  }
590  if (VdotNb)
591  *VdotNb = d;
592  return Nb;
593 }
594 
595 #define ALMOSTZERO 0.005f
596 
597 // Given two random numbers, generate a vector from a cosine distribution
598 // on the upper hemisphere.
599 // The normal n and two tangent vectors t0 and t1 are assumed to form an
600 // orthonormal basis: |n| = |t0| = |t1| = 1; n.t1 = n.t2 = t1.t2 = 0.
601 // The output outDir has unit length.
602 PRMAN_INLINE void
604  const RtFloat2& xi,
605  const RtVector3& n,
606  const RtVector3& t0,
607  const RtVector3& t1,
608  RtVector3& outDir,
609  float& cosTheta)
610 {
611  // In debug mode, assertion will help us identify unexpected inputs
612  // where n, t0, t1 do not form an orthonormal basis.
613  // Since this func is in the API, any bxdf or plugins that use this func
614  // will get the assertion, which probably indicates a bug in the caller.
615  assert(n.IsUnitLength()); // close to 1 enough
616  assert(t0.IsUnitLength()); // close to 1 enough
617  assert(t1.IsUnitLength()); // close to 1 enough
618  assert(n.AbsDot(t0) < ALMOSTZERO); // orthogonal enough
619  assert(t0.AbsDot(t1) < ALMOSTZERO); // orthogonal enough
620  assert(n.AbsDot(t1) < ALMOSTZERO); // orthogonal enough
621 
622  float e1 = xi.x * F_TWOPI;
623  float z = std::sqrt(xi.y);
624  float r = std::sqrt(std::max(0.0f, 1.0f - xi.y)); // = sqrt(1 - z^2)
625  float x = r * cosf(e1);
626  float y = r * sinf(e1);
627  if (z < 1.e-12f)
628  z = 1.e-12f;
629 
630  outDir = x * t0 + y * t1 + z * n;
631  cosTheta = z;
632 
633  assert(outDir.IsUnitLength()); // close to 1 enough
634 }
635 
636 // Given two random numbers, generate a vector from a cosine distribution
637 // on the upper hemisphere. The normal n is assumed to have unit length.
638 // The output outDir has unit length.
639 PRMAN_INLINE void
641  const RtFloat2& xi,
642  const RtVector3& n,
643  RtVector3& outDir,
644  float& cosTheta)
645 {
646  RtVector3 t0, t1;
647  n.CreateOrthonormalBasis(t0, t1);
648  RixCosDirectionalDistribution(xi, n, t0, t1, outDir, cosTheta);
649 }
650 
651 // Given two random numbers, generate a vector from a uniform distribution
652 // on the upper hemisphere.
653 // The normal n and two tangent vectors t0 and t1 are assumed to form an
654 // orthonormal basis: |n| = |t0| = |t1| = 1; n.t1 = n.t2 = t1.t2 = 0.
655 // The output outDir has unit length.
656 PRMAN_INLINE void
658  const RtFloat2& xi,
659  const RtVector3& n,
660  const RtVector3& t0,
661  const RtVector3& t1,
662  RtVector3& outDir,
663  float& cosTheta)
664 {
665  float e1 = xi.x * F_TWOPI;
666  float z = xi.y;
667  float r = std::sqrt(std::max(0.0f, 1.0f - z * z));
668  float x = r * cosf(e1);
669  float y = r * sinf(e1);
670  if (z < 1.e-12f)
671  z = 1.e-12f;
672 
673  outDir = x * t0 + y * t1 + z * n;
674  cosTheta = z;
675 }
676 
677 // Given two random numbers, generate a vector from a uniform distribution
678 // on the upper hemisphere. The normal n is assumed to have unit length.
679 // The output outDir has unit length.
680 PRMAN_INLINE void
682  const RtFloat2& xi,
683  const RtVector3& n,
684  RtVector3& outDir,
685  float& cosTheta)
686 {
687  RtVector3 t0, t1;
688  n.CreateOrthonormalBasis(t0, t1);
689  RixUniformDirectionalDistribution(xi, n, t0, t1, outDir, cosTheta);
690 }
691 
692 // Given two random numbers and a cone angle, generate a vector from a
693 // uniform distribution over the cone angle around a normal.
694 // The normal n and two tangent vectors t0 and t1 are assumed to form an
695 // orthonormal basis: |n| = |t0| = |t1| = 1; n.t1 = n.t2 = t1.t2 = 0.
696 // The output outDir has unit length.
697 PRMAN_INLINE void
698 RixUniformConeDistribution(const RtFloat2& xi, const float coneAngle,
699  const RtVector3& n, const RtVector3& t0,
700  const RtVector3& t1, RtVector3& outDir,
701  float& cosTheta)
702 {
703  float e1 = xi.x * F_TWOPI;
704  float cosAngle = cosf(coneAngle);
705  float z = xi.y * (1.0f - cosAngle) + cosAngle;
706  float r = std::sqrt(std::max(0.0f, 1.0f - z * z));
707  float x = r * cosf(e1);
708  float y = r * sinf(e1);
709  if (z < 1.e-12f)
710  z = 1.e-12f;
711 
712  outDir = x * t0 + y * t1 + z * n;
713  cosTheta = z;
714 }
715 
716 // Given two random numbers and a cone angle, generate a vector from a
717 // uniform distribution over the cone angle around a normal. The
718 // normal n is assumed to have unit length. The output outDir has
719 // unit length.
720 PRMAN_INLINE void
722  const RtFloat2& xi, const float coneAngle,
723  const RtVector3& n,
724  RtVector3& outDir,
725  float& cosTheta)
726 {
727  RtVector3 t0, t1;
728  n.CreateOrthonormalBasis(t0, t1);
729  RixUniformConeDistribution(xi, coneAngle, n, t0, t1, outDir, cosTheta);
730 }
731 
732 // Given two random numbers, generate a vector from a uniform distribution
733 // on the entire sphere.
736 {
737  RtVector3 outDir;
738  outDir.z = 2.0f * xi.y - 1.0f; // cosTheta
739  float sinTheta = 1.0f - outDir.z * outDir.z; // actually sinTheta^2 here
740  if (sinTheta > 0.0f)
741  {
742  sinTheta = std::sqrt(sinTheta);
743  float phi = xi.x * F_TWOPI;
744  outDir.x = sinTheta * cosf(phi);
745  outDir.y = sinTheta * sinf(phi);
746  }
747  else // rare case
748  {
749  outDir.x = 0.0f;
750  outDir.y = 0.0f;
751  }
752  return outDir;
753 }
754 
755 // Randomly choose between numThresholds+1 scattering lobes using xi,
756 // and remap xi back to [0,1).
757 // Making a random selection this way and stretching the random numbers
758 // preserves stratification properties of a well-distributed set.
759 PRMAN_INLINE int
760 RixChooseAndRemap(float& xi, int numThresholds, float* thresholds)
761 {
762  // below lowest threshold?
763  if (xi < thresholds[0])
764  {
765  xi /= thresholds[0];
766  return 0; // chose lobe 0
767  }
768  // between thresholds?
769  for (int i = 1; i < numThresholds; i++)
770  {
771  if (thresholds[i - 1] <= xi && xi < thresholds[i])
772  {
773  xi = (xi - thresholds[i - 1]) / (thresholds[i] - thresholds[i - 1]);
774  return i; // chose lobe i
775  }
776  }
777  // must be above highest threshold
778  float lastThres = thresholds[numThresholds - 1];
779  xi = (xi - lastThres) / (1.0f - lastThres);
780  return numThresholds; // chose last lobe
781 }
782 
783 // Compute ray-tracing bias amount
784 PRMAN_INLINE float
786  const RtPoint3& /* org */,
787  const RtNormal3& N,
788  const RtVector3& dir,
789  float biasR,
790  float biasT)
791 {
792  return (N.Dot(dir) < 0.0f) ? biasT : biasR;
793 }
794 
795 // Compute ray-tracing bias amount and apply it to the ray origin
798  const RtPoint3& org,
799  const RtNormal3& N,
800  const RtVector3& dir,
801  const float biasR,
802  const float biasT)
803 {
804  float biasAmt = RixTraceBias(org, N, dir, biasR, biasT);
805 
806  // Currently we bias in the ray direction, but in some cases we might
807  // want to bias along the surface normal (which is also provided as an
808  // input to this routine). Note that in the case of a ray in the opposite
809  // direction to the normal, we always want to bias in the ray direction
810  return org + biasAmt * dir;
811 }
812 
813 PRMAN_INLINE void
814 RixSinCos(float phi, float* sinPhi, float* cosPhi)
815 {
816 #ifdef LINUX
817  sincosf(phi, sinPhi, cosPhi);
818 #elif (defined(OSX) && defined(__clang__))
819  __sincosf(phi, sinPhi, cosPhi);
820 #else
821  *sinPhi = sinf(phi);
822  *cosPhi = cosf(phi);
823 #endif
824 }
825 
828  float sinTheta,
829  float cosTheta,
830  float sinPhi,
831  float cosPhi)
832 {
833  return RtVector3(sinTheta * cosPhi, sinTheta * sinPhi, cosTheta);
834 }
835 
837 RixSphericalDirection(float sinTheta, float cosTheta, float phi)
838 {
839  float sinPhi, cosPhi;
840  RixSinCos(phi, &sinPhi, &cosPhi);
841  return RixSphericalDirection(sinTheta, cosTheta, sinPhi, cosPhi);
842 }
843 
844 // RixChangeBasisFrom:
845 // trnansform a vector defined relative to the basis vectors
846 // to the embedding space (local to global)
847 
850  RtVector3 const& in,
851  RtVector3 const& X,
852  RtVector3 const& Y,
853  RtVector3 const& Z)
854 {
855  RtVector3 result;
856  result.x = in.x * X.x + in.y * Y.x + in.z * Z.x;
857  result.y = in.x * X.y + in.y * Y.y + in.z * Z.y;
858  result.z = in.x * X.z + in.y * Y.z + in.z * Z.z;
859  return result;
860 }
861 
864  RtVector3 const& in,
865  RtVector3 const& X,
866  RtVector3 const& Y,
867  RtVector3 const& Z)
868 {
869  return RixChangeBasisFrom(in, X, Y, Z);
870 }
871 
872 // RixChangeBasisTo:
873 // transform a vector defined in the embedding space to be relative
874 // to the provided basis vectors. (global to local)
877  RtVector3 const& in,
878  RtVector3 const& X,
879  RtVector3 const& Y,
880  RtVector3 const& Z)
881 {
882  return RtVector3(Dot(in, X), Dot(in, Y), Dot(in, Z));
883 }
884 
885 // Templated mix: T must define multiply and add (*, + operators)
886 template <typename T>
887 PRMAN_INLINE T
888 RixMix(const T& v0, const T& v1, float m)
889 {
890  return (1.0f - m) * v0 + m * v1;
891 }
892 
893 // Templated smooth (hermite) mix: T must define *, +, plus scalar +, -)
894 // This is also known as the "ease" function.
895 template <typename T>
896 PRMAN_INLINE T
897 RixSmoothMix(const T& x1, const T& x2, float t)
898 {
899  if (t <= 0.0f)
900  return x1;
901  else if (t >= 1.0f)
902  return x2;
903  else
904  {
905  T x3;
906  T dx = x2 - x1;
907  x3 = x1 + dx * t * t * (3.f - 2.f * t);
908  return x3;
909  }
910 }
911 
912 // RixEaseInMix:
913 // Templated ease-in: T must define *, +, plus scalar +, -)
914 // interpolate from x1 to x2, with tangent at x1 of 0
915 template <typename T>
916 PRMAN_INLINE T
917 RixEaseInMix(const T& x1, const T& x2, float t)
918 {
919  if (t <= 0.0f)
920  return x1;
921  else if (t >= 1.0f)
922  return x2;
923  else
924  {
925  T x3;
926  T dx = x2 - x1;
927  x3 = x1 + dx * t * t;
928  return x3;
929  }
930 }
931 
932 // RixEaseOutMix:
933 // Templated ease-in: T must define *, +, plus scalar +, -)
934 // interpolate from x1 to x2, with tangent at x2 of 0
935 template <typename T>
936 PRMAN_INLINE T
937 RixEaseOutMix(const T& x1, const T& x2, float t)
938 {
939  if (t <= 0.0f)
940  return x1;
941  else if (t >= 1.0f)
942  return x2;
943  else
944  {
945  T x3;
946  T dx = x2 - x1;
947  x3 = t * dx * (2.f - t) + x1;
948  return x3;
949  }
950 }
951 
952 // Threshold functions
953 // -------------------
954 
955 // RixBoxStep: returns 0 when val < min and 1 otherwise
956 PRMAN_INLINE float
957 RixBoxStep(float min, float val)
958 {
959  return val < min ? 0.0f : 1.0f;
960 }
961 
962 // RixLinearStep: returns 0 when val < min, 1 when val > max and
963 // a linearly interpolated value between 0 and 1 for val between min and max.
964 PRMAN_INLINE float
965 RixLinearStep(float min, float max, float val)
966 {
967  if (min < max)
968  {
969  return val <= min
970  ? 0.0f
971  : (val >= max ? 1.0f : (val - min) / (max - min));
972  }
973  else if (min > max)
974  {
975  return 1.0f - (
976  val <= max
977  ? 0.0f
978  : (val >= min ? 1.0f : (val - max) / (min - max)));
979  }
980  else
981  return RixBoxStep(min, val);
982 }
983 
984 // RixSmoothStep: returns 0 when val < min, 1 when val > max and
985 // a smooth Hermite interpolated value between 0 and 1 for val between
986 // min and max. The slope at both ends of the cubic curve is zero.
987 PRMAN_INLINE float
988 RixSmoothStep(float min, float max, float val)
989 {
990  if (min < max)
991  {
992  if (val <= min)
993  return 0.f;
994  if (val >= max)
995  return 1.f;
996  val = (val - min) / (max - min);
997  }
998  else if (min > max)
999  {
1000  if (val <= max)
1001  return 1.f;
1002  if (val >= min)
1003  return 0.f;
1004  val = 1.0f - (val - max) / (min - max);
1005  }
1006  else
1007  return RixBoxStep(min, val);
1008 
1009  return val * val * (3.0f - 2.0f * val);
1010 }
1011 
1012 // RixGaussStep: returns 0 when val < min, 1 when val > max and
1013 // an exponential curve between 0 and 1 for val between min and max.
1014 // Strictly speaking, this isn't a gaussian curve.
1015 PRMAN_INLINE float
1016 RixGaussStep(float min, float max, float val)
1017 {
1018  if (min < max)
1019  {
1020  if (val < min)
1021  return 0.0f;
1022  if (val >= max)
1023  return 1.0f;
1024  val = 1.0f - (val - min) / (max - min);
1025  }
1026  else if (min > max)
1027  {
1028  if (val <= max)
1029  return 1.0f;
1030  if (val > min)
1031  return 0.0f;
1032  val = (val - max) / (min - max);
1033  }
1034  else
1035  return RixBoxStep(min, val);
1036 
1037  return std::pow(2.0f, -8.0f * val * val);
1038 }
1039 
1040 PRMAN_INLINE float
1041 RixSolidAngle2Spread(float solidangle)
1042 {
1043  /* To convert from angle to solid angle we use
1044  * cone-endcap formulation, assuming radius of 1
1045  *
1046  * omega = 2.pi.(1-cos(theta))
1047  *
1048  * therefore
1049  *
1050  * cos(theta) = 1 - omega/(2.pi)
1051  *
1052  * we want tan(theta)
1053  *
1054  * tan(theta) = + sqrt(1-cos^2(theta)) / cos(theta)
1055  * or - sqrt(1-cos^2(theta)) / cos(theta)
1056  */
1057 
1058  // Clamp spread to 1. The solid angle corresponding to spread 1 is
1059  // 2 pi (1 - cos(pi/4)) ~ 1.840302
1060  if (solidangle > 1.840302f)
1061  return 1.0f;
1062 
1063  // Divide solidangle by 2*pi
1064  float omega_div_2pi = solidangle * 0.15915494f;
1065 
1066  // Compute cos(theta)
1067  float cosTheta = 1.0f - omega_div_2pi;
1068  assert(cosTheta > 0.0f);
1069 
1070  // Return tan(theta)
1071  return std::sqrt(1.0f - cosTheta * cosTheta) / cosTheta;
1072 }
1073 
1074 // RixAlloca() is a thin veneer atop alloca(). Callers should take
1075 // care to not allocate beyond the platform-specific limits
1076 // on stack size. To avoid this concern, the ShadingContext
1077 // offers a heap-based memory pool. We implement this as a macro
1078 // instead of an inlined function since it's difficult to enforce
1079 // the requisite inlining in a portable fashion. The value of
1080 // this veneer is merely that the windows header contortions are
1081 // centralized in this utility header.
1082 
1083 #define RixAlloca(s) alloca(s)
1084 
1085 // Inputs Nf and Tn are assumed to be normalised, but are not
1086 // necessarily orthogonal. Parallel Nf and Tn are dealt with
1087 // by ignoring Tn.
1088 PRMAN_INLINE void
1090  RtNormal3 const& Nf,
1091  RtVector3 const& Tn,
1092  RtVector3& TX,
1093  RtVector3& TY)
1094 {
1095  // In debug mode, assertion will help us identify unnormalized
1096  // Nf and Tn inputs.
1097  // Since this function is in the API, any bxdf or plugins that this
1098  // will get the assertion, which probably indicates a bug in the caller.
1099  assert(Nf.IsUnitLength()); // length close to 1
1100  assert(Tn.IsUnitLength()); // length close to 1
1101 
1102  if (Nf.AbsDot(Tn) < 0.995f)
1103  {
1104  TY = Cross(Nf, Tn);
1105  TY.Normalize();
1106  TX = Cross(TY, Nf);
1107  }
1108  else
1109  {
1110  // Under rare circumstances, the input vectors
1111  // can be parallel. In this case, we generate
1112  // a basis using only the normal.
1113  Nf.CreateOrthonormalBasis(TX, TY);
1114  }
1115 }
1116 
1117 PRMAN_INLINE void
1119  RixShadingContext* sc,
1120  RtPoint3& o,
1121  RtVector3& x,
1122  RtVector3& y,
1123  RtVector3& z)
1124 {
1125  PIXAR_ARGUSED(sc);
1126  PIXAR_ARGUSED(o);
1127  PIXAR_ARGUSED(x);
1128  PIXAR_ARGUSED(y);
1129  PIXAR_ARGUSED(z);
1130 
1131 #ifndef NDEBUG
1132  float orthonormalCheck = z.Dot(Cross(x, y));
1133  if (orthonormalCheck < 0.98f)
1134  {
1135  const RtColorRGB r = RtColorRGB(1, 0, 0);
1136  const RtColorRGB g = RtColorRGB(0, 1, 0);
1137  const RtColorRGB b = RtColorRGB(0, 0, 1);
1138  RixGeoDebugger* gdb =
1140  gdb->EmitPointNormal(o, x, r);
1141  gdb->EmitPointNormal(o, y, g);
1142  gdb->EmitPointNormal(o, z, b);
1143  }
1144 #endif
1145 }
1146 
1147 // Modify the shading context so that u is shifted
1148 // by one differential.
1149 PRMAN_INLINE void
1151 {
1152  float const* u;
1153  float const* du;
1156 
1157  int numPts = sCtx->numPts;
1158  RixShadingContext::Allocator pool(sCtx);
1159  float* newu = (float*)pool.AllocForPattern<float>(numPts);
1160  for (int i = 0; i < numPts; i++)
1161  {
1162  newu[i] = u[i] + du[i];
1163  }
1165 }
1166 
1167 // Modify the shading context so that v is shifted
1168 // by one differential.
1169 PRMAN_INLINE void
1171 {
1172  float const* v;
1173  float const* dv;
1176 
1177  int numPts = sCtx->numPts;
1178  RixShadingContext::Allocator pool(sCtx);
1179  float* newv = (float*)pool.AllocForPattern<float>(numPts);
1180  for (int i = 0; i < numPts; i++)
1181  {
1182  newv[i] = v[i] + dv[i];
1183  }
1185 }
1186 
1187 // Classic Blinn formulation of bumped normal from a height field.
1188 // The three displacements represent the height at the original point,
1189 // at a point du units in the dPdu direction, and at a point dv units
1190 // in the dPdv direction.
1191 PRMAN_INLINE void
1193  RixShadingContext const* sCtx,
1194  float const* disp,
1195  float const* dispU,
1196  float const* dispV,
1197  RtNormal3* Nn) // result: bumped normal (normalized)
1198 {
1199  int numPts = sCtx->numPts;
1200  float const* du;
1201  float const* dv;
1202  RtVector3 const* dPdu;
1203  RtVector3 const* dPdv;
1204  RtVector3 const* Norig;
1205  RtNormal3 const* Ngn;
1206  RtNormal3 const* Naon;
1211  sCtx->GetBuiltinVar(RixShadingContext::k_Nn, &Norig);
1214 
1215  // Get primvar N, ie. interpolated vertex normal, if present (not normalized).
1216  RtNormal3 fill(0,0,0);
1217  RtNormal3 const *Nuser;
1218  RixSCDetail nDetail = sCtx->GetPrimVar(Rix::k_N, fill, &Nuser);
1219  bool hasUserNormals = (nDetail != k_RixSCInvalidDetail);
1220 
1221  for (int i = 0; i < numPts; i++)
1222  {
1223  // Only skip computations if all disp values are zero
1224  if(disp[i] == 0.f && dispU[i] == 0.f && dispV[i] == 0.0f)
1225  {
1226  Nn[i] = Norig[i];
1227  }
1228  else
1229  {
1230  // We currently assume the normal does not change
1231  // significantly over the neighborhood of P + du and P + dv.
1232  // Should this assumption be invalid a further call to
1233  // evaluate the normal at each location may be warranted.
1234  RtPoint3 P0 = Norig[i] * disp[i];
1235  RtPoint3 P1 = du[i] * dPdu[i] + Norig[i] * dispU[i];
1236  RtPoint3 P2 = dv[i] * dPdv[i] + Norig[i] * dispV[i];
1237  Nn[i] = Cross(P1 - P0, P2 - P0);
1238  Nn[i].Normalize();
1239 
1240  // In some cases, Cross(dPdu, dPdv) is *not* the same as Nn, nor Ngn, mostly because of
1241  // the camera-to-object transform determinant.
1242  RtNormal3 computedNgn = Cross(du[i] * dPdu[i], dv[i] * dPdv[i]);
1243  computedNgn.Normalize();
1244 
1245  RtFloat const dotNg = Dot(computedNgn, Ngn[i]);
1246 
1247  if (hasUserNormals)
1248  {
1249  // Compensate for faceted renders of coarse polygon meshes (large faces)
1250 
1251  RtNormal3 Nuser_i = Nuser[i];
1252  RtNormal3 Naon_i = Naon[i];
1253 
1254  // Flip Naon if needed for calculation of delta
1255  if (dotNg < 0.f)
1256  {
1257  Naon_i = -Naon_i;
1258  }
1259 
1260  // Interpolated user-provided vertex normals aren't usually normalized,
1261  // so normalize now
1262  Nuser_i.Normalize();
1263 
1264  // Compute difference between user-provided smooth normal and polymesh
1265  // face normal
1266  RtNormal3 delta = Nuser_i - Naon_i;
1267 
1268  // Use vertex normals to smooth out faceted renders of coarse polygon meshes
1269  if (delta != RtNormal3(0.f))
1270  {
1271  Nn[i] += delta;
1272  Nn[i].Normalize();
1273  }
1274  }
1275  else
1276  {
1277  // Compensate for faceted renders of coarsely tessellated geometry (large
1278  // micropolygons)
1279 
1280  // Flip Nn and computedNgn if needed for calculation of delta
1281  if (dotNg < 0.f)
1282  {
1283  Nn[i] = -Nn[i];
1284  computedNgn = -computedNgn;
1285  }
1286 
1287  RtNormal3 const delta = Norig[i] - computedNgn;
1288 
1289  // Smooth out coarsely tessellated polygon meshes by adding difference
1290  // between Nn and Ngn
1291  if (delta != RtNormal3(0.f))
1292  {
1293  Nn[i] += delta;
1294  Nn[i].Normalize();
1295  }
1296  }
1297 
1298  }
1299  }
1300 }
1301 
1302 // This routine determines whether the shading points in the provided
1303 // shading context belong to a matte object. Zero is returned if not,
1304 // while a positive value indicates a matte object. A negative value is
1305 // returned on error.
1306 PRMAN_INLINE int
1308 {
1309  static const RtUString k_matteName("Ri:Matte");
1310  static const int k_matteLen = sizeof(float);
1311  static const int k_matteDef = 0;
1312 
1313  int matte = k_matteDef;
1314 
1315  if (RixRenderState* state =
1317  {
1318  RixRenderState::Type matteType;
1319  float matteVal;
1320  int matteRet;
1321  int matteCount;
1322 
1323  matteRet = state->GetAttribute(
1324  k_matteName, &matteVal, k_matteLen, &matteType, &matteCount);
1325 
1326  if (matteRet != 0)
1327  matte = -1;
1328  else if (matteCount == 1)
1329  matte = (int)matteVal;
1330  }
1331  else
1332  {
1333  matte = -1;
1334  }
1335 
1336  return matte;
1337 }
1338 
1339 PRMAN_INLINE int
1341 {
1342  static const RtUString k_holdoutName("trace:holdout");
1343  static const int k_holdoutLen = sizeof(float);
1344  static const int k_holdoutDef = 0;
1345  int holdout = k_holdoutDef;
1346  if (RixRenderState* state =
1348  {
1349  RixRenderState::Type holdoutType;
1350  float holdoutVal;
1351  int holdoutCount;
1352  int holdoutRet = state->GetAttribute(
1353  k_holdoutName, &holdoutVal, k_holdoutLen, &holdoutType, &holdoutCount);
1354  if (holdoutRet)
1355  holdout = -1;
1356  else
1357  holdout = (int)holdoutVal;
1358  }
1359  return holdout;
1360 }
1361 
1362 PRMAN_INLINE unsigned long
1363 RixImod(const unsigned long a, const unsigned long b)
1364 {
1365  unsigned long n = a/b;
1366  return (a - n*b);
1367 }
1368 
1369 // djb2
1370 // http://www.cse.yorku.ca/~oz/hash.html
1371 // this algorithm (k=33) was first reported by dan bernstein many years ago in
1372 // comp.lang.c. another version of this algorithm (now favored by bernstein) uses
1373 // xor: hash(i) = hash(i - 1) * 33 ^ str[i]; the magic of number 33 (why it works
1374 // better than many other constants, prime or not) has never been adequately
1375 // explained.
1376 //
1377 PRMAN_INLINE float
1378 RixHash(const char *bufPtr, unsigned long range=65535)
1379 {
1380  unsigned long hash = 5381;
1381  int c;
1382  while ((c = int(*bufPtr++)))
1383  hash = ((hash << 5) + hash) ^ c; /* hash * 33 + c */
1384 
1385  return float(RixImod(hash,range));
1386 }
1387 
1388 // This function clamps the result between a and b to avoid issues
1389 // with floating point precision.
1391 RixLerpRGB(RtColorRGB const &a, RtColorRGB const &b, float const mix)
1392 {
1393  RtColorRGB result = b + mix * (a - b);
1394  result.r = a.r < b.r ? RixClamp(result.r, a.r, b.r) : RixClamp(result.r, b.r, a.r);
1395  result.g = a.g < b.g ? RixClamp(result.g, a.g, b.g) : RixClamp(result.g, b.g, a.g);
1396  result.b = a.b < b.b ? RixClamp(result.b, a.b, b.b) : RixClamp(result.b, b.b, a.b);
1397  return result;
1398 }
1399 
1400 // This function adjusts the normals when the geometric normals are facing away
1401 // from the camera
1402 PRMAN_INLINE void
1403 RixAdjustNormal(float const amount, RtVector3 const &Vn, RtVector3 const &Ngn,
1404  RtNormal3 &Nn)
1405 {
1406  if (amount == 0.f)
1407  return;
1408 
1409  if (Dot(Vn, Ngn) >= 0.f)
1410  {
1411  float VdotN = Dot(Vn, Nn);
1412  if (VdotN <= 0.f)
1413  {
1414  // If the input normal faces away from camera, nudge it back
1415  // pad an extra 1% towards V
1416  Nn -= amount * 1.01f * VdotN * Vn;
1417  Nn.Normalize();
1418  }
1419  }
1420 }
1421 
1422 
1423 #endif // RixShadingUtils_h
PRMAN_INLINE RtVector3 RixChangeBasisFrom(RtVector3 const &in, RtVector3 const &X, RtVector3 const &Y, RtVector3 const &Z)
PRMAN_INLINE T RixMix(const T &v0, const T &v1, float m)
PRMAN_INLINE float RixSchlickFresnelWeight(float NdV)
#define ALMOSTZERO
PRMAN_INLINE float RixGaussStep(float min, float max, float val)
pxrcore::ColorRGB RtColorRGB
PRMAN_INLINE float RixMax(float x, float y)
virtual RixSCDetail GetPrimVar(const RtUString name, RixSCType *type, int *arraylen) const =0
Id for RixRenderState interface.
PRMAN_INLINE void RixFresnelDielectric(float VdN, float eta, float *Kr)
Ray footprint (radius) in V (type float)
Definition: RixShading.h:896
PRMAN_INLINE void RixSinCos(float phi, float *sinPhi, float *cosPhi)
PRMAN_INLINE float RixFractional(float x)
Normalized shading normal (type RtFloat3)
Definition: RixShading.h:878
PRMAN_INLINE void RixFresnelConductorApprox(float VdN, float eta, float kappa, float *Kr)
#define F_TWOPI
PRMAN_INLINE unsigned int RixFindFirstSetBit(unsigned long long v)
PRMAN_INLINE float RixRadiansToDegrees(float rads)
float RtFloat
Definition: ri.h:54
PRMANAPI const RtUString k_N
"N"
RtFloat3 RtPoint3
Definition: RiTypesHelper.h:69
PRMAN_INLINE int RixChooseAndRemap(float &xi, int numThresholds, float *thresholds)
Id for geometric debugger interface.
#define F_DEGTORAD
PRMAN_INLINE unsigned long RixImod(const unsigned long a, const unsigned long b)
PRMAN_INLINE T RixSmoothMix(const T &x1, const T &x2, float t)
PRMAN_INLINE float RixDegreesToRadians(float degrees)
RixSCDetail
Definition: RixShading.h:376
PRMAN_INLINE void RixAdjustNormal(float const amount, RtVector3 const &Vn, RtVector3 const &Ngn, RtNormal3 &Nn)
Ray footprint (radius) in U (type float)
Definition: RixShading.h:894
Surface derivative in U (type RtFloat3)
Definition: RixShading.h:900
PRMAN_INLINE float RixClamp(float x, float min, float max)
PRMAN_INLINE void RixCosDirectionalDistribution(const RtFloat2 &xi, const RtVector3 &n, const RtVector3 &t0, const RtVector3 &t1, RtVector3 &outDir, float &cosTheta)
RtFloat3 RtNormal3
Definition: RiTypesHelper.h:72
PRMAN_INLINE RtVector3 RixReflect(const RtVector3 &Vn, const RtNormal3 &Nn)
PRMAN_INLINE int RixRefract(const RtVector3 &Vn, const RtNormal3 &Nn, float eta, RtVector3 &Tn)
PRMAN_INLINE float RixLinearStep(float min, float max, float val)
An interface for discovering the current state of the renderer.
Normalized view vector, points away from shading points (type RtFloat3)
Definition: RixShading.h:882
PRMAN_INLINE RtVector3 RixSphericalDistribution(const RtFloat2 &xi)
PRMAN_INLINE T RixSignum(T x)
PRMAN_INLINE RtColorRGB RixLerpRGB(RtColorRGB const &a, RtColorRGB const &b, float const mix)
pxrcore::UString RtUString
virtual void EmitPointNormal(RtPoint3 p, RtNormal3 n, RtColorRGB c)=0
Normalized analytical undisplaced N (type RtFloat3)
Definition: RixShading.h:917
PRMAN_INLINE float RixMin(float x, float y)
#define PRMAN_INLINE
Definition: prmanapi.h:86
PRMAN_INLINE void RixComputeShadingBasis(RtNormal3 const &Nf, RtVector3 const &Tn, RtVector3 &TX, RtVector3 &TY)
PRMAN_INLINE float RixBoxStep(float min, float val)
Surface V parameterization (type float)
Definition: RixShading.h:892
PRMAN_INLINE float RixHash(const char *bufPtr, unsigned long range=65535)
PRMAN_INLINE void RixFresnelConductor(float VdN, float eta, float kappa, float *Kr)
PRMAN_INLINE int RixIsFinite(float x)
PRMAN_INLINE RtVector3 RixChangeBasisTo(RtVector3 const &in, RtVector3 const &X, RtVector3 const &Y, RtVector3 const &Z)
PRMAN_INLINE float RixSolidAngle2Spread(float solidangle)
pxrcore::Matrix4x4 RtMatrix4x4
Definition: RiTypesHelper.h:73
PRMAN_INLINE int RixIsMatte(RixShadingContext const &sCtx)
pxrcore::Float3 RtFloat3
Definition: RiTypesHelper.h:68
PRMAN_INLINE int RixIsHoldout(RixShadingContext const &sCtx)
PRMAN_INLINE void RixBump(RixShadingContext const *sCtx, float const *disp, float const *dispU, float const *dispV, RtNormal3 *Nn)
PRMAN_INLINE void RixDebugBasis(RixShadingContext *sc, RtPoint3 &o, RtVector3 &x, RtVector3 &y, RtVector3 &z)
Surface U parameterization (type float)
Definition: RixShading.h:891
PRMAN_INLINE float RixMod(float x, float y)
#define F_RADTODEG
virtual void SetBuiltinVar(BuiltinVar, float *var)=0
PRMAN_INLINE void RixShiftCtxInU(RixShadingContext *sCtx)
PRMAN_INLINE void RixUniformDirectionalDistribution(const RtFloat2 &xi, const RtVector3 &n, const RtVector3 &t0, const RtVector3 &t1, RtVector3 &outDir, float &cosTheta)
PRMAN_INLINE RtPoint3 RixApplyTraceBias(const RtPoint3 &org, const RtNormal3 &N, const RtVector3 &dir, const float biasR, const float biasT)
PRMAN_INLINE T RixEaseInMix(const T &x1, const T &x2, float t)
PRMAN_INLINE T RixEaseOutMix(const T &x1, const T &x2, float t)
PRMAN_INLINE RtNormal3 RixGetForwardFacingNormal(RtVector3 const &Vn, RtNormal3 const &Nn, float *VdotNf=NULL)
Surface derivative in V (type RtFloat3)
Definition: RixShading.h:901
PRMAN_INLINE RtVector3 RixChangeBasis(RtVector3 const &in, RtVector3 const &X, RtVector3 const &Y, RtVector3 const &Z)
PRMAN_INLINE float RixTraceBias(const RtPoint3 &, const RtNormal3 &N, const RtVector3 &dir, float biasR, float biasT)
virtual RixInterface * GetRixInterface(RixInterfaceId id) const =0
PRMAN_INLINE float RixSmoothStep(float min, float max, float val)
PRMAN_INLINE RtNormal3 RixGetBackwardFacingNormal(RtVector3 const &Vn, RtNormal3 const &Nn, float *VdotNb=NULL)
Normalized geometric normal (type RtFloat3)
Definition: RixShading.h:879
PRMAN_INLINE RtVector3 RixSphericalDirection(float sinTheta, float cosTheta, float sinPhi, float cosPhi)
PRMAN_INLINE void RixShiftCtxInV(RixShadingContext *sCtx)
virtual void GetBuiltinVar(BuiltinVar, int const **var) const =0
PRMAN_INLINE void RixUniformConeDistribution(const RtFloat2 &xi, const float coneAngle, const RtVector3 &n, const RtVector3 &t0, const RtVector3 &t1, RtVector3 &outDir, float &cosTheta)
#define PIXAR_ARGUSED(x)
Definition: prmanapi.h:171
RtFloat3 RtVector3
Definition: RiTypesHelper.h:71