RenderMan API  23.0
RixBxdfLobe.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 RixBxdfLobe_h
39 #define RixBxdfLobe_h
40 
41 #include <algorithm> // for min
42 #include <cassert> // for assert
43 #include <cstring> // for memset, NULL
44 #include "RixInterfaces.h" // for RixLPEInfo, RixContext, etc
45 #include "RixShadingUtils.h" // for RixFindFirstSetBit
46 #include "prmanapi.h" // for PRMAN_INLINE
47 #include "ri.h" // for RtColorRGB
48 
50 static const unsigned char k_RixBXMaxNumDiffuseLobes = 4;
51 
53 static const unsigned char k_RixBXMaxNumSpecularLobes = 8;
54 
56 static const unsigned char k_RixBXMaxNumUserLobes = 12; // (was 8 in PRMan 20.x)
57 
59 static const unsigned char k_RixBXSubsurfaceLobeId1 = 9;
60 static const unsigned char k_RixBXSubsurfaceLobeId2 = 10;
61 static const unsigned char k_RixBXSubsurfaceLobeId3 = 11;
62 
65 {
68 
70  PRMAN_INLINE RixBXLobeSampled(unsigned short serialized);
71 
74  bool discrete,
75  bool specular,
76  bool reflect,
77  bool user,
78  unsigned char lpeId,
79  unsigned char lobeId);
80 
81  // CompareLobeID: returns true if rhs is the same as this lobeId.
82  PRMAN_INLINE bool CompareLobeID(RixBXLobeSampled const& rhs) const
83  {
84  return (fields.bits.valid && rhs.fields.bits.valid &&
85  fields.bits.specular == rhs.fields.bits.specular &&
86  fields.bits.user == rhs.fields.bits.user &&
87  fields.bits.lobeId == rhs.fields.bits.lobeId);
88  }
89 
90  // Read-only accessors; these all verify that the valid bit is set before
91  // returning true.
92  PRMAN_INLINE bool GetValid() const;
93  PRMAN_INLINE bool GetDiscrete() const;
94  PRMAN_INLINE bool GetSolidAngle() const;
95  PRMAN_INLINE bool GetDiffuse() const;
96  PRMAN_INLINE bool GetSpecular() const;
97  PRMAN_INLINE bool GetReflect() const;
98  PRMAN_INLINE bool GetTransmit(bool* entering = NULL) const;
99  PRMAN_INLINE bool GetEntering() const; // only valid for Transmit
100  PRMAN_INLINE bool GetContinuation() const;
101  PRMAN_INLINE bool GetScattering() const;
102  PRMAN_INLINE bool GetUser() const;
103  PRMAN_INLINE unsigned char GetLpeId() const;
104  PRMAN_INLINE unsigned char GetLobeId() const;
105  PRMAN_INLINE bool LobeIdIsSubsurface() const;
106  PRMAN_INLINE bool GetThinShadowFlag() const;
107  PRMAN_INLINE unsigned char GetUnused() const;
108 
109  // Set individual fields (only SetValid() changes the valid bit).
110  PRMAN_INLINE void SetValid(bool val);
111  PRMAN_INLINE void SetDiscrete(bool val);
112  PRMAN_INLINE void SetSpecular(bool val);
113  PRMAN_INLINE void SetReflect();
114  PRMAN_INLINE void SetTransmit(bool entering);
115  PRMAN_INLINE void SetEntering(bool entering); // valid only for Transmit
116  PRMAN_INLINE void SetContinuation(bool val);
117  PRMAN_INLINE void SetUser(bool val);
118  PRMAN_INLINE void SetLpeId(unsigned char val);
119  PRMAN_INLINE void SetLobeId(unsigned char val);
120  PRMAN_INLINE void SetThinShadowFlag(bool val);
121  PRMAN_INLINE void SetUnused(unsigned char val);
122 
124  PRMAN_INLINE void Set(
125  bool vDiscrete,
126  bool vSpecular,
127  bool vReflect,
128  bool vContinuation,
129  bool vUser,
130  unsigned char vLpeId,
131  unsigned char vLobeId,
132  bool vThinShadowFlag = false);
133 
134  // Convert to a serialized integral representation.
135  PRMAN_INLINE unsigned short Serialize() const;
136 
137  struct Bitfield
138  {
139  unsigned short valid : 1;
140  unsigned short discrete : 1;
141  unsigned short specular : 1;
143  unsigned short reflect : 1;
144  unsigned short entering : 1;
145  unsigned short continuation : 1;
147  unsigned short user : 1;
148  unsigned short lpeId : 3;
149  unsigned short lobeId : 4;
150  unsigned short thinShadow : 1;
151  unsigned short unused : 1;
152  };
153 
154  union Converter
155  {
157  unsigned short us;
158  };
159 
160 private:
161  Converter fields;
162 };
163 
167  RixContext& ctx,
168  bool discrete,
169  bool specular,
170  bool reflect,
171  bool user,
172  unsigned char lobeId,
173  char const* name);
174 
178 {
181 
183  PRMAN_INLINE RixBXLobeTraits(unsigned serialized);
184 
186  PRMAN_INLINE RixBXLobeTraits(
187  bool discrete,
188  bool solidAngle,
189  bool reflect,
190  bool transmit,
191  unsigned short D,
192  unsigned short S,
193  unsigned short U);
194 
196  PRMAN_INLINE explicit RixBXLobeTraits(RixBXLobeSampled lobe);
197 
198  // Read-only accessors; return individual fields.
199  PRMAN_INLINE bool GetDiscrete() const;
200  PRMAN_INLINE bool GetSolidAngle() const;
201  PRMAN_INLINE bool GetReflect() const;
202  PRMAN_INLINE bool GetTransmit() const;
203  PRMAN_INLINE bool GetContinuation() const;
204  PRMAN_INLINE unsigned short GetDiffuse() const;
205  PRMAN_INLINE unsigned short GetSpecular() const;
206  PRMAN_INLINE unsigned short GetUser() const;
214  PRMAN_INLINE bool GetValid() const;
215 
216  PRMAN_INLINE bool GetMaxSpecularDepth() const;
217  PRMAN_INLINE bool GetMaxDiffuseDepth() const;
218 
219  // Set individual fields.
220  PRMAN_INLINE void SetValid(bool val);
221  PRMAN_INLINE void SetDiscrete(bool val);
222  PRMAN_INLINE void SetSolidAngle(bool val);
223  PRMAN_INLINE void SetReflect(bool val);
224  PRMAN_INLINE void SetTransmit(bool val);
225  PRMAN_INLINE void SetContinuation(bool val);
226  PRMAN_INLINE void SetMaxSpecularDepth(bool val);
227  PRMAN_INLINE void SetMaxDiffuseDepth(bool val);
228  PRMAN_INLINE void SetDiffuse(unsigned short bits);
229  PRMAN_INLINE void SetSpecular(unsigned short bits);
230  PRMAN_INLINE void SetUser(unsigned short bits);
231 
233  PRMAN_INLINE void SetNone();
234 
239  PRMAN_INLINE void SetAll();
240 
243  PRMAN_INLINE bool HasAny() const;
244 
247  PRMAN_INLINE bool HasAnyDiffSpec() const;
248 
251  PRMAN_INLINE bool HasAnyDiffuse() const;
252 
255  PRMAN_INLINE bool HasAnySpecular() const;
256 
258  PRMAN_INLINE bool HasAnyUser() const;
259 
260  // Convert to a serialized integral representation.
261  PRMAN_INLINE unsigned Serialize() const;
262 
264  PRMAN_INLINE RixBXLobeTraits const& operator&=(RixBXLobeTraits const& rhs);
265 
267  PRMAN_INLINE RixBXLobeTraits const& operator|=(RixBXLobeTraits const& rhs);
268 
269  struct Bitfield
270  {
271  unsigned valid : 1;
272  unsigned discreteSubset : 1;
273  unsigned solidAngleSubset : 1;
274  unsigned reflectSubset : 1;
275  unsigned transmitSubset : 1;
276  unsigned continuationSubset : 1;
277  unsigned D : k_RixBXMaxNumDiffuseLobes;
278  unsigned S : k_RixBXMaxNumSpecularLobes;
279  unsigned U : k_RixBXMaxNumUserLobes;
280 
281  unsigned maxspeculardepth : 1;
282  unsigned maxdiffusedepth : 1;
283  };
284 
285  union Converter
286  {
288  unsigned us;
289  };
290 
291 private:
292  Converter fields;
293 };
294 
297  RixBXLobeTraits const& lhs,
298  RixBXLobeTraits const& rhs);
299 
302  RixBXLobeTraits const& lhs,
303  RixBXLobeTraits const& rhs);
304 
305 // clang-format off
307 static const RixBXLobeTraits k_RixBXTraitsNullLobe(
308  false, false, false, false, 0x0, 0x0, 0x0);
309 static const RixBXLobeTraits k_RixBXTraitsReflectDiffuse(
310  false, true, true, false, 0xF, 0x0, 0x0);
311 static const RixBXLobeTraits k_RixBXTraitsReflectSpecular(
312  false, true, true, false, 0x0, 0xFF, 0x0);
313 static const RixBXLobeTraits k_RixBXTraitsTransmitDiffuse(
314  false, true, false, true, 0xF, 0x0, 0x0);
315 static const RixBXLobeTraits k_RixBXTraitsTransmitSpecular(
316  false, true, false, true, 0x0, 0xFF, 0x0);
317 static const RixBXLobeTraits k_RixBXTraitsAllDiffuse(
318  false, true, true, true, 0xF, 0x0, 0x0);
319 static const RixBXLobeTraits k_RixBXTraitsAllSpecular(
320  false, true, true, true, 0x0, 0xFF, 0x0);
321 static const RixBXLobeTraits k_RixBXTraitsAllUser(
322  false, false, false, false, 0x0, 0x0, 0xFFF);
323 static const RixBXLobeTraits k_RixBXTraitsAllReflect(
324  false, true, true, false, 0x0F, 0xFF, 0x0);
325 static const RixBXLobeTraits k_RixBXTraitsAllTransmit(
326  false, true, false, true, 0x0F, 0xFF, 0x0);
327 static const RixBXLobeTraits k_RixBXTraitsAllLobe(
328  false, true, true, true, 0x0F, 0xFF, 0xFFF);
329 // clang-format on
330 
332 {
335 
337  PRMAN_INLINE RixBXActiveLobeWeights(
338  RixBXLobeTraits lobeTraits,
339  int numDiffuseLobes,
340  int numSpecularLobes,
341  int numUserLobes,
342  RtColorRGB* diffuseLobes[],
343  RtColorRGB* specularLobes[],
344  RtColorRGB* userLobes[],
345  unsigned char diffuseLpeIds[],
346  unsigned char specularLpeIds[],
347  unsigned char userLpeIds[],
348  int offset = 0);
349 
351  PRMAN_INLINE RixBXActiveLobeWeights(RixBXActiveLobeWeights const& that);
352 
354  PRMAN_INLINE RixBXActiveLobeWeights& operator=(
355  RixBXActiveLobeWeights const& that);
356 
357  // Get the pointer to the array of weights for a diffuse or specular lobe.
358  PRMAN_INLINE RtColorRGB const* GetDiffuseLobe(int i) const;
359  PRMAN_INLINE RtColorRGB const* GetSpecularLobe(int i) const;
360  PRMAN_INLINE RtColorRGB const* GetUserLobe(int i) const;
361  PRMAN_INLINE RtColorRGB* GetDiffuseLobe(int i);
362  PRMAN_INLINE RtColorRGB* GetSpecularLobe(int i);
363  PRMAN_INLINE RtColorRGB* GetUserLobe(int i);
364 
365  // Clears all diffuse or specular lobes from active lobes list
366  PRMAN_INLINE void ClearAllDiffuseLobes();
367  PRMAN_INLINE void ClearAllSpecularLobes();
368  PRMAN_INLINE void ClearAllUserLobes();
369 
370  // Get or set the current offset into array of weights.
371  PRMAN_INLINE int GetOffset() const;
372  PRMAN_INLINE void SetOffset(int offset);
373 
374  // Get or set the lobe traits.
375  PRMAN_INLINE RixBXLobeTraits GetLobeTraits() const;
376  PRMAN_INLINE void SetLobeTraits(RixBXLobeTraits lobes);
377 
378  // Get the number of diffuse or specular lobes.
379  PRMAN_INLINE unsigned char GetNumDiffuseLobes() const;
380  PRMAN_INLINE unsigned char GetNumSpecularLobes() const;
381  PRMAN_INLINE unsigned char GetNumUserLobes() const;
382 
383  // Get the original LPE id of a diffuse or specular lobe.
384  PRMAN_INLINE unsigned char GetDiffuseLpeId(int i) const;
385  PRMAN_INLINE unsigned char GetSpecularLpeId(int i) const;
386  PRMAN_INLINE unsigned char GetUserLpeId(int i) const;
387 
388  // Return the sum at a particular index in the array of lobe weights.
389  PRMAN_INLINE RtColorRGB SumAtIndex(
390  int index,
391  bool includeUserLobes = false) const;
392 
393  // Multiply by a value at a particular index in the array of lobe weights.
394  PRMAN_INLINE void MultiplyByWeightAtIndex(
395  int index,
396  float weight,
397  bool includeUserLobes = false);
398  PRMAN_INLINE void MultiplyByWeightAtIndex(
399  int index,
400  RtColorRGB const& weight,
401  bool includeUserLobes = false);
402 
403  // Sets to zero at a particular index in the array of lobe weights.
404  PRMAN_INLINE void ZeroAtIndex(int index, bool includeUserLobes = false);
405 
406 private:
407  friend struct RixBXLobeWeights;
408 
409  // Ptrs to diffuse and specular weights
410  RtColorRGB* m_diffuseLobes[k_RixBXMaxNumDiffuseLobes];
411  RtColorRGB* m_specularLobes[k_RixBXMaxNumSpecularLobes];
412  RtColorRGB* m_userLobes[k_RixBXMaxNumUserLobes];
413 
414  int m_offset; // Offset into arrays
415  RixBXLobeTraits m_lobeTraits; // Active lobe traits
416  unsigned char m_numDiffuseLobes; // Diff lobe count
417  unsigned char m_numSpecularLobes; // Spec lobe count
418  unsigned char m_numUserLobes; // User lobe count
419 
420  // Diffuse and specular LPE ids.
421  unsigned char m_diffuseLpeIds[k_RixBXMaxNumDiffuseLobes];
422  unsigned char m_specularLpeIds[k_RixBXMaxNumSpecularLobes];
423  unsigned char m_userLpeIds[k_RixBXMaxNumUserLobes];
424 };
425 
426 // RixBXLobeWeights distributes weights into qualitative properties.
428 {
432 
434  PRMAN_INLINE RixBXLobeWeights(
435  int numPoints,
436  int numDiffuseLobes,
437  int numSpecularLobes,
438  int numUserLobes,
439  RtColorRGB* diffuseLobes[],
440  RtColorRGB* specularLobes[],
441  RtColorRGB* userLobes[],
442  int offset = 0);
443 
445  PRMAN_INLINE RixBXLobeWeights(RixBXLobeWeights const& that);
446 
448  PRMAN_INLINE RixBXLobeWeights& operator=(RixBXLobeWeights const& that);
449 
450  // Get the pointer to the array of weights for a diffuse or specular lobe.
451  PRMAN_INLINE RtColorRGB const* GetDiffuseLobe(int i) const;
452  PRMAN_INLINE RtColorRGB const* GetSpecularLobe(int i) const;
453  PRMAN_INLINE RtColorRGB const* GetUserLobe(int i) const;
454  PRMAN_INLINE RtColorRGB* GetDiffuseLobe(int i);
455  PRMAN_INLINE RtColorRGB* GetSpecularLobe(int i);
456  PRMAN_INLINE RtColorRGB* GetUserLobe(int i);
457 
458  // Get or set the current number of points in the arrays of weights.
459  PRMAN_INLINE int GetNumPoints() const;
460  PRMAN_INLINE void SetNumPoints(int numPoints);
461 
462  // Get or set the current offset into array of weights.
463  PRMAN_INLINE int GetOffset() const;
464  PRMAN_INLINE void SetOffset(int offset);
465 
466  // Get, set or add to the active lobe traits.
467  PRMAN_INLINE RixBXLobeTraits GetActiveLobeTraits() const;
468  PRMAN_INLINE void SetActiveLobeTraits(RixBXLobeTraits lobes);
469  PRMAN_INLINE void AddActiveLobeTraits(RixBXLobeTraits lobes);
470 
471  // Get the number of diffuse or specular lobes.
472  PRMAN_INLINE int GetNumDiffuseLobes() const;
473  PRMAN_INLINE int GetNumSpecularLobes() const;
474  PRMAN_INLINE int GetNumUserLobes() const;
475 
478  PRMAN_INLINE RtColorRGB* AddActiveLobe(
479  RixBXLobeSampled lobe,
480  bool doInitializeWeights = true);
481 
483  PRMAN_INLINE void GetActiveLobes(RixBXActiveLobeWeights& r) const;
484 
487  PRMAN_INLINE void GetActiveLobesIntersection(
488  RixBXLobeWeights const& rhs,
489  RixBXActiveLobeWeights& activeLhs,
490  RixBXActiveLobeWeights& activeRhs) const;
491 
492  // Copy over just the active lobe weights in 'src' at the given index into
493  // the lobe weights. Any lobes that are not present in 'src' will not be
494  // updated in this instance.
495  PRMAN_INLINE void CopyWeightAtIndex(
496  int index,
497  RixBXActiveLobeWeights const& src,
498  bool includeUserLobes = false);
499 
500  // Add in just the active lobe weights in 'src' at the given index into
501  // the lobe weights. Any lobes that are not present in 'src' will not be
502  // updated in this instance.
503  PRMAN_INLINE void AddWeightAtIndex(
504  int index,
505  RixBXActiveLobeWeights const& src,
506  bool includeUserLobes = false);
507 
508 private:
509  // Ptrs to diffuse and specular weights
510  RtColorRGB* m_diffuseLobes[k_RixBXMaxNumDiffuseLobes];
511  RtColorRGB* m_specularLobes[k_RixBXMaxNumSpecularLobes];
512  RtColorRGB* m_userLobes[k_RixBXMaxNumUserLobes];
513 
514  int m_numPoints; // Size of each array
515  int m_offset; // Offset into arrays
516  RixBXLobeTraits m_activeLobeTraits; // Active lobe traits
517  unsigned char m_numDiffuseLobes; // Diff lobe count
518  unsigned char m_numSpecularLobes; // Spec lobe count
519  unsigned char m_numUserLobes; // User lobe count
520 };
521 
524 
528 PRMAN_INLINE int RixBXChoose(float const xi, int const numThresholds,
529  float const* thresholds);
530 
556 PRMAN_INLINE bool RixBXChooseLobe(float const xi,
558  RixBXLobeSampled &chosenLobe);
559 
578 PRMAN_INLINE void RixBXChooseLobe(int const npoints, float const* xi,
579  RixBXLobeWeights& lw,
580  RixBXLobeSampled* lobeSampled);
581 
587 PRMAN_INLINE void RixBXChooseLobe(float const xi, RixBXActiveLobeWeights& lw,
588  RixBXLobeTraits &traits);
589 
590 //
591 // --- inline implementations of classes and functions above ---
592 //
593 
594 //
595 // class RixBXLobeSampled inline implementation
596 //
597 
600 {
601  /* Init all fields to zero. We write one instruction that has the
602  * same effect as performing the following assignments:
603 
604  fields.bits.valid = 0;
605  fields.bits.discrete = 0;
606  fields.bits.specular = 0;
607  fields.bits.reflect = 0;
608  fields.bits.entering = 0;
609  fields.bits.continuation = 0;
610  fields.bits.user = 0;
611  fields.bits.lpeId = 0;
612  fields.bits.lobeId = 0;
613  fields.bits.thinShadow = 0;
614  fields.bits.unused = 0;
615  */
616 
617  fields.us = 0;
618 }
619 
621 RixBXLobeSampled::RixBXLobeSampled(unsigned short serialized)
622 {
623  fields.us = serialized;
624 }
625 
628  bool vDiscrete,
629  bool vSpecular,
630  bool vReflect,
631  bool vUser,
632  unsigned char vLpeId,
633  unsigned char vLobeId)
634 {
635  fields.bits.valid = 1;
636  fields.bits.discrete = vDiscrete;
637  fields.bits.specular = vSpecular;
638  fields.bits.reflect = vReflect;
639  fields.bits.entering = 0;
640  fields.bits.continuation = 0;
641  fields.bits.user = vUser;
642  fields.bits.lpeId = vLpeId & 0x7;
643  fields.bits.lobeId = vLobeId & 0xF;
644  fields.bits.thinShadow = 0;
645  fields.bits.unused = 0;
646 }
647 
648 PRMAN_INLINE bool
650 {
651  return fields.bits.valid;
652 }
653 
654 PRMAN_INLINE bool
656 {
657  return fields.bits.valid && fields.bits.discrete;
658 }
659 
660 PRMAN_INLINE bool
662 {
663  return fields.bits.valid && !fields.bits.discrete;
664 }
665 
666 PRMAN_INLINE bool
668 {
669  return fields.bits.valid && !fields.bits.specular;
670 }
671 
672 PRMAN_INLINE bool
674 {
675  return fields.bits.valid && fields.bits.specular;
676 }
677 
678 PRMAN_INLINE bool
680 {
681  return fields.bits.valid && fields.bits.reflect;
682 }
683 
684 PRMAN_INLINE bool
685 RixBXLobeSampled::GetTransmit(bool* vEntering) const
686 {
687  bool transmit = fields.bits.valid && !fields.bits.reflect;
688  if (vEntering)
689  *vEntering = fields.bits.entering && transmit;
690  return transmit;
691 }
692 
693 PRMAN_INLINE bool
695 {
696  return fields.bits.valid && !fields.bits.reflect && fields.bits.entering;
697 }
698 
699 PRMAN_INLINE bool
701 {
702  return fields.bits.valid && fields.bits.continuation;
703 }
704 
705 PRMAN_INLINE bool
707 {
708  return fields.bits.valid && !fields.bits.continuation;
709 }
710 
711 PRMAN_INLINE bool
713 {
714  return fields.bits.valid && fields.bits.user;
715 }
716 
717 PRMAN_INLINE unsigned char
719 {
720  return (unsigned char)(fields.bits.valid ? fields.bits.lpeId : 0);
721 }
722 
723 PRMAN_INLINE unsigned char
725 {
726  return (unsigned char)(fields.bits.valid ? fields.bits.lobeId : 0);
727 }
728 
729 PRMAN_INLINE bool
731 {
732  if (!fields.bits.valid)
733  return false;
734  else
735  return (fields.bits.lobeId == k_RixBXSubsurfaceLobeId1 ||
736  fields.bits.lobeId == k_RixBXSubsurfaceLobeId2 ||
737  fields.bits.lobeId == k_RixBXSubsurfaceLobeId3);
738 }
739 
740 PRMAN_INLINE bool
742 {
743  return fields.bits.valid && fields.bits.thinShadow;
744 }
745 
746 PRMAN_INLINE unsigned char
748 {
749  return (unsigned char)(fields.bits.valid ? fields.bits.unused : 0);
750 }
751 
752 PRMAN_INLINE void
754 {
755  fields.bits.valid = val;
756 }
757 
758 PRMAN_INLINE void
760 {
761  fields.bits.discrete = val;
762 }
763 
764 PRMAN_INLINE void
766 {
767  fields.bits.specular = val;
768 }
769 
770 PRMAN_INLINE void
772 {
773  fields.bits.reflect = 1;
774 }
775 
776 PRMAN_INLINE void
778 {
779  fields.bits.reflect = 0;
780  fields.bits.entering = val;
781 }
782 
783 PRMAN_INLINE void
785 {
786  // valid only for Transmit
787  assert(fields.bits.reflect == 0);
788  fields.bits.entering = val;
789 }
790 
791 PRMAN_INLINE void
793 {
794  fields.bits.continuation = val;
795 }
796 
797 PRMAN_INLINE void
799 {
800  fields.bits.user = val;
801 }
802 
803 PRMAN_INLINE void
804 RixBXLobeSampled::SetLpeId(unsigned char val)
805 {
806  fields.bits.lpeId = val & 0x7;
807 }
808 
809 PRMAN_INLINE void
810 RixBXLobeSampled::SetLobeId(unsigned char val)
811 {
812  fields.bits.lobeId = val & 0xF;
813 }
814 
815 PRMAN_INLINE void
817 {
818  fields.bits.thinShadow = val;
819 }
820 
821 PRMAN_INLINE void
822 RixBXLobeSampled::SetUnused(unsigned char val)
823 {
824  fields.bits.unused = val & 0x1;
825 }
826 
827 PRMAN_INLINE void
829  bool vDiscrete,
830  bool vSpecular,
831  bool vReflect,
832  bool vContinuation,
833  bool vUser,
834  unsigned char vLpeId,
835  unsigned char vLobeId,
836  bool vThinShadowFlag)
837 {
838  fields.bits.valid = 1;
839  fields.bits.discrete = vDiscrete;
840  fields.bits.specular = vSpecular;
841  fields.bits.reflect = vReflect;
842  fields.bits.continuation = vContinuation;
843  fields.bits.entering = 0;
844  fields.bits.user = vUser;
845  fields.bits.lpeId = vLpeId & 0x7;
846  fields.bits.lobeId = vLobeId & 0xF;
847  fields.bits.thinShadow = vThinShadowFlag;
848  fields.bits.unused = 0;
849 }
850 
851 PRMAN_INLINE unsigned short
853 {
854  return fields.us;
855 }
856 
857 //
858 // RixBXLookupLobeByName() inline implementation
859 //
860 
863  RixContext& ctx,
864  bool discrete,
865  bool specular,
866  bool reflect,
867  bool user,
868  unsigned char lobeId,
869  char const* name)
870 {
871  unsigned char lpeId = 0;
872  if (RixLPEInfo* lpeInfo = (RixLPEInfo*)ctx.GetRixInterface(k_RixLPEInfo))
873  {
874  lpeId = (unsigned char)lpeInfo->GetLpeIdByName(
875  discrete, specular, reflect, user, lobeId, name);
876  }
877  return RixBXLobeSampled(discrete, specular, reflect, user, lpeId, lobeId);
878 }
879 
880 //
881 // class RixBXLobeTraits inline implementation.
882 //
883 
886 {
887  // starts with a valid but clean lobe traits
888  SetNone();
889  fields.bits.valid = 1;
890 }
891 
894 {
895  // initializes from serialization as unsigned short
896  fields.us = serialized;
897 }
898 
901  bool discrete,
902  bool solidAngle,
903  bool reflect,
904  bool transmit,
905  unsigned short D,
906  unsigned short S,
907  unsigned short U)
908 {
909  assert(sizeof(fields.bits) == sizeof(unsigned));
910  fields.bits.discreteSubset = discrete;
911  fields.bits.solidAngleSubset = solidAngle;
912  fields.bits.reflectSubset = reflect;
913  fields.bits.transmitSubset = transmit;
914  fields.bits.continuationSubset = 0;
915  fields.bits.D = D & 0x0F;
916  fields.bits.S = S & 0xFF;
917  fields.bits.U = U & 0xFFF;
918  fields.bits.maxspeculardepth = 0;
919  fields.bits.maxdiffusedepth = 0;
920  fields.bits.valid = 1; // samples are valid until explicitly set to invalid (by bxdf)
921 }
922 
925 {
926  if (lobe.GetValid())
927  {
928  if (lobe.GetUser())
929  {
930  fields.bits.discreteSubset = 0;
931  fields.bits.solidAngleSubset = 0;
932  fields.bits.reflectSubset = 0;
933  fields.bits.transmitSubset = 0;
934  fields.bits.continuationSubset = 0;
935 
936  fields.bits.D = 0;
937  fields.bits.S = 0;
938  if (lobe.GetLpeId() < k_RixBXMaxNumUserLobes)
939  fields.bits.U = (1 << lobe.GetLpeId()) & 0xFFF;
940  else
941  fields.bits.U = 0;
942  }
943  else
944  {
945  fields.bits.discreteSubset = lobe.GetDiscrete();
946  fields.bits.solidAngleSubset = lobe.GetSolidAngle();
947  fields.bits.reflectSubset = lobe.GetReflect();
948  fields.bits.transmitSubset = lobe.GetTransmit();
949  fields.bits.continuationSubset = lobe.GetContinuation();
950 
951  if (lobe.GetDiffuse() && lobe.GetLpeId() < k_RixBXMaxNumDiffuseLobes)
952  fields.bits.D = (1 << lobe.GetLpeId()) & 0x0F;
953  else
954  fields.bits.D = 0;
955  if (lobe.GetSpecular() && lobe.GetLpeId() < k_RixBXMaxNumSpecularLobes)
956  fields.bits.S = (1 << lobe.GetLpeId()) & 0xFF;
957  else
958  fields.bits.S = 0;
959  fields.bits.U = 0;
960  }
961  SetValid(true);
962  }
963  else
964  {
965  SetNone();
966  SetValid(false); // an invalid sample
967  }
968  fields.bits.maxspeculardepth = 0;
969  fields.bits.maxdiffusedepth = 0;
970 }
971 
972 PRMAN_INLINE bool
974 {
975  return fields.bits.valid;
976 }
977 
978 PRMAN_INLINE bool
980 {
981  return fields.bits.discreteSubset;
982 }
983 
984 PRMAN_INLINE bool
986 {
987  return fields.bits.solidAngleSubset;
988 }
989 
990 PRMAN_INLINE bool
992 {
993  return fields.bits.reflectSubset;
994 }
995 
996 PRMAN_INLINE bool
998 {
999  return fields.bits.transmitSubset;
1000 }
1001 
1002 PRMAN_INLINE bool
1004 {
1005  return fields.bits.continuationSubset;
1006 }
1007 
1008 PRMAN_INLINE unsigned short
1010 {
1011  return static_cast<unsigned short>(fields.bits.D);
1012 }
1013 
1014 PRMAN_INLINE unsigned short
1016 {
1017  return static_cast<unsigned short>(fields.bits.S);
1018 }
1019 
1020 PRMAN_INLINE unsigned short
1022 {
1023  return static_cast<unsigned short>(fields.bits.U);
1024 }
1025 
1026 PRMAN_INLINE bool
1028 {
1029  return fields.bits.maxspeculardepth;
1030 }
1031 
1032 PRMAN_INLINE bool
1034 {
1035  return fields.bits.maxdiffusedepth;
1036 }
1037 
1038 PRMAN_INLINE void
1040 {
1041  fields.bits.valid = val;
1042 }
1043 
1044 PRMAN_INLINE void
1046 {
1047  fields.bits.discreteSubset = val;
1048 }
1049 
1050 PRMAN_INLINE void
1052 {
1053  fields.bits.solidAngleSubset = val;
1054 }
1055 
1056 PRMAN_INLINE void
1058 {
1059  fields.bits.reflectSubset = val;
1060 }
1061 
1062 PRMAN_INLINE void
1064 {
1065  fields.bits.transmitSubset = val;
1066 }
1067 
1068 PRMAN_INLINE void
1070 {
1071  fields.bits.continuationSubset = val;
1072 }
1073 
1074 PRMAN_INLINE void
1075 RixBXLobeTraits::SetDiffuse(unsigned short val)
1076 {
1077  fields.bits.D = static_cast<unsigned>(val & 0x0F);
1078 }
1079 
1080 PRMAN_INLINE void
1081 RixBXLobeTraits::SetSpecular(unsigned short val)
1082 {
1083  fields.bits.S = static_cast<unsigned>(val & 0xFF);
1084 }
1085 
1086 PRMAN_INLINE void
1087 RixBXLobeTraits::SetUser(unsigned short val)
1088 {
1089  fields.bits.U = static_cast<unsigned>(val & 0xFFF);
1090 }
1091 
1092 PRMAN_INLINE void
1094 {
1095  fields.bits.maxspeculardepth = val;
1096 }
1097 
1098 PRMAN_INLINE void
1100 {
1101  fields.bits.maxdiffusedepth = val;
1102 }
1103 
1104 PRMAN_INLINE void
1106 {
1107  /* Init all fields to zero. We write one instruction that has the
1108  * same effect as performing the following assignments:
1109 
1110  fields.bits.discreteSubset = 0;
1111  fields.bits.solidAngleSubset = 0;
1112  fields.bits.reflectSubset = 0;
1113  fields.bits.transmitSubset = 0;
1114  fields.bits.continuationSubset = 0;
1115  fields.bits.D = 0;
1116  fields.bits.S = 0;
1117  fields.bits.U = 0;
1118  fields.bits.maxspeculardepth = 0;
1119  fields.bits.maxdiffusedepth = 0;
1120  */
1121 
1122  fields.us = 0;
1123 }
1124 
1125 PRMAN_INLINE void
1127 {
1128  fields.bits.valid = 1;
1129  fields.bits.discreteSubset = 0;
1130  fields.bits.solidAngleSubset = 1;
1131  fields.bits.reflectSubset = 1;
1132  fields.bits.transmitSubset = 1;
1133  fields.bits.continuationSubset = 0;
1134  fields.bits.maxspeculardepth = 0;
1135  fields.bits.maxdiffusedepth = 0;
1136  fields.bits.D = 0x0F;
1137  fields.bits.S = 0xFF;
1138  fields.bits.U = 0xFFF;
1139 }
1140 
1141 PRMAN_INLINE bool
1143 {
1144  return HasAnyDiffSpec() || HasAnyUser();
1145 }
1146 
1147 PRMAN_INLINE bool
1149 {
1150  return (fields.bits.D | fields.bits.S) &&
1151  (fields.bits.reflectSubset | fields.bits.transmitSubset |
1152  fields.bits.continuationSubset);
1153 }
1154 
1155 PRMAN_INLINE bool
1157 {
1158  return (fields.bits.D != 0) &&
1159  (fields.bits.reflectSubset || fields.bits.transmitSubset);
1160 }
1161 
1162 PRMAN_INLINE bool
1164 {
1165  return (fields.bits.S != 0) &&
1166  (fields.bits.reflectSubset || fields.bits.transmitSubset);
1167 }
1168 
1169 PRMAN_INLINE bool
1171 {
1172  return (fields.bits.U != 0);
1173 }
1174 
1175 PRMAN_INLINE unsigned
1177 {
1178  return fields.us;
1179 }
1180 
1183 {
1184  /* Bitwise AND all fields. We write one instruction that has the
1185  * same effect as performing the following assignments:
1186 
1187  fields.bits.discreteSubset &= rhs.fields.bits.discreteSubset;
1188  fields.bits.solidAngleSubset &= rhs.fields.bits.solidAngleSubset;
1189  fields.bits.reflectSubset &= rhs.fields.bits.reflectSubset;
1190  fields.bits.transmitSubset &= rhs.fields.bits.transmitSubset;
1191  fields.bits.continuationSubset &= rhs.fields.bits.continuationSubset;
1192  fields.bits.D &= rhs.fields.bits.D;
1193  fields.bits.S &= rhs.fields.bits.S;
1194  fields.bits.U &= rhs.fields.bits.U;
1195  fields.bits.maxspeculardepth &= rhs.fields.bits.maxspeculardepth;
1196  fields.bits.maxdiffusedepth &= rhs.fields.bits.maxdiffusedepth;
1197  */
1198 
1199  fields.us &= rhs.fields.us;
1200 
1201  return *this;
1202 }
1203 
1206 {
1207  /* Bitwise OR all fields. We write one instruction that has the
1208  * same effect as performing the following assignments:
1209 
1210  fields.bits.discreteSubset |= rhs.fields.bits.discreteSubset;
1211  fields.bits.solidAngleSubset |= rhs.fields.bits.solidAngleSubset;
1212  fields.bits.reflectSubset |= rhs.fields.bits.reflectSubset;
1213  fields.bits.transmitSubset |= rhs.fields.bits.transmitSubset;
1214  fields.bits.continuationSubset |= rhs.fields.bits.continuationSubset;
1215  fields.bits.D |= rhs.fields.bits.D;
1216  fields.bits.S |= rhs.fields.bits.S;
1217  fields.bits.U |= rhs.fields.bits.U;
1218  fields.bits.maxspeculardepth |= rhs.fields.bits.maxspeculardepth;
1219  fields.bits.maxdiffusedepth |= rhs.fields.bits.maxdiffusedepth;
1220  */
1221 
1222  fields.us |= rhs.fields.us;
1223 
1224  return *this;
1225 }
1226 
1229 {
1230  /* Bitwise AND all fields. We write one instruction that has the
1231  * same effect as performing the following assignments:
1232 
1233  r.fields.bits.discreteSubset =
1234  lhs.fields.bits.discreteSubset & rhs.fields.bits.discreteSubset;
1235  r.fields.bits.solidAngleSubset =
1236  lhs.fields.bits.solidAngleSubset & rhs.fields.bits.solidAngleSubset;
1237  r.fields.bits.reflectSubset =
1238  lhs.fields.bits.reflectSubset & rhs.fields.bits.reflectSubset;
1239  r.fields.bits.transmitSubset =
1240  lhs.fields.bits.transmitSubset & rhs.fields.bits.transmitSubset;
1241  r.fields.bits.continuationSubset =
1242  lhs.fields.bits.continuationSubset &
1243  rhs.fields.bits.continuationSubset;
1244  r.fields.bits.D = lhs.fields.bits.D & rhs.fields.bits.D;
1245  r.fields.bits.S = lhs.fields.bits.S & rhs.fields.bits.S;
1246  r.fields.bits.U = lhs.fields.bits.U & rhs.fields.bits.U;
1247  */
1248 
1249  RixBXLobeTraits r(lhs.Serialize() & rhs.Serialize());
1250  return r;
1251 }
1252 
1255 {
1256  /* Bitwise OR all fields. We write one instruction that has the
1257  * same effect as performing the following assignments:
1258 
1259  r.fields.bits.discreteSubset =
1260  lhs.fields.bits.discreteSubset | rhs.fields.bits.discreteSubset;
1261  r.fields.bits.solidAngleSubset =
1262  lhs.fields.bits.solidAngleSubset | rhs.fields.bits.solidAngleSubset;
1263  r.fields.bits.reflectSubset =
1264  lhs.fields.bits.reflectSubset | rhs.fields.bits.reflectSubset;
1265  r.fields.bits.transmitSubset =
1266  lhs.fields.bits.transmitSubset | rhs.fields.bits.transmitSubset;
1267  r.fields.bits.continuationSubset =
1268  lhs.fields.bits.continuationSubset |
1269  rhs.fields.bits.continuationSubset;
1270  r.fields.bits.D = lhs.fields.bits.D | rhs.fields.bits.D;
1271  r.fields.bits.S = lhs.fields.bits.S | rhs.fields.bits.S;
1272  r.fields.bits.U = lhs.fields.bits.U | rhs.fields.bits.U;
1273  */
1274 
1275  RixBXLobeTraits r(lhs.Serialize() | rhs.Serialize());
1276  return r;
1277 }
1278 
1279 //
1280 // class RixBXActiveLobeWeights implementation
1281 //
1282 
1285  : m_offset(0),
1286  m_numDiffuseLobes(0),
1287  m_numSpecularLobes(0),
1288  m_numUserLobes(0)
1289 {
1290 }
1291 
1294  RixBXLobeTraits lobeTraits,
1295  int numDiffuseLobes,
1296  int numSpecularLobes,
1297  int numUserLobes,
1298  RtColorRGB* diffuseLobes[],
1299  RtColorRGB* specularLobes[],
1300  RtColorRGB* userLobes[],
1301  unsigned char diffuseLpeIds[],
1302  unsigned char specularLpeIds[],
1303  unsigned char userLpeIds[],
1304  int offset)
1305  : m_offset(offset),
1306  m_lobeTraits(lobeTraits),
1307  m_numDiffuseLobes((unsigned char)numDiffuseLobes),
1308  m_numSpecularLobes((unsigned char)numSpecularLobes),
1309  m_numUserLobes((unsigned char)numUserLobes)
1310 {
1311  for (int i = 0; i < numDiffuseLobes; i++)
1312  {
1313  m_diffuseLobes[i] = diffuseLobes[i];
1314  m_diffuseLpeIds[i] = diffuseLpeIds[i];
1315  }
1316 
1317  for (int i = 0; i < numSpecularLobes; i++)
1318  {
1319  m_specularLobes[i] = specularLobes[i];
1320  m_specularLpeIds[i] = specularLpeIds[i];
1321  }
1322 
1323  for (int i = 0; i < numUserLobes; i++)
1324  {
1325  m_userLobes[i] = userLobes[i];
1326  m_userLpeIds[i] = userLpeIds[i];
1327  }
1328 }
1329 
1332  RixBXActiveLobeWeights const& that)
1333  : m_offset(that.m_offset),
1334  m_lobeTraits(that.m_lobeTraits),
1335  m_numDiffuseLobes(that.m_numDiffuseLobes),
1336  m_numSpecularLobes(that.m_numSpecularLobes),
1337  m_numUserLobes(that.m_numUserLobes)
1338 {
1339  for (int i = 0; i < m_numDiffuseLobes; i++)
1340  {
1341  m_diffuseLobes[i] = that.m_diffuseLobes[i];
1342  m_diffuseLpeIds[i] = that.m_diffuseLpeIds[i];
1343  }
1344  for (int i = 0; i < m_numSpecularLobes; i++)
1345  {
1346  m_specularLobes[i] = that.m_specularLobes[i];
1347  m_specularLpeIds[i] = that.m_specularLpeIds[i];
1348  }
1349  for (int i = 0; i < m_numUserLobes; i++)
1350  {
1351  m_userLobes[i] = that.m_userLobes[i];
1352  m_userLpeIds[i] = that.m_userLpeIds[i];
1353  }
1354 }
1355 
1358 {
1359  m_offset = that.m_offset;
1360  m_lobeTraits = that.m_lobeTraits;
1361  m_numDiffuseLobes = that.m_numDiffuseLobes;
1362  m_numSpecularLobes = that.m_numSpecularLobes;
1363  m_numUserLobes = that.m_numUserLobes;
1364 
1365  for (int i = 0; i < m_numDiffuseLobes; i++)
1366  {
1367  m_diffuseLobes[i] = that.m_diffuseLobes[i];
1368  m_diffuseLpeIds[i] = that.m_diffuseLpeIds[i];
1369  }
1370  for (int i = 0; i < m_numSpecularLobes; i++)
1371  {
1372  m_specularLobes[i] = that.m_specularLobes[i];
1373  m_specularLpeIds[i] = that.m_specularLpeIds[i];
1374  }
1375  for (int i = 0; i < m_numUserLobes; i++)
1376  {
1377  m_userLobes[i] = that.m_userLobes[i];
1378  m_userLpeIds[i] = that.m_userLpeIds[i];
1379  }
1380 
1381  return *this;
1382 }
1383 
1384 PRMAN_INLINE int
1386 {
1387  return m_offset;
1388 }
1389 
1390 PRMAN_INLINE void
1392 {
1393  m_offset = offset;
1394 }
1395 
1398 {
1399  return m_lobeTraits;
1400 }
1401 
1402 PRMAN_INLINE void
1404 {
1405  m_lobeTraits = lobes;
1406 }
1407 
1408 PRMAN_INLINE unsigned char
1410 {
1411  return m_numDiffuseLobes;
1412 }
1413 
1414 PRMAN_INLINE unsigned char
1416 {
1417  return m_numSpecularLobes;
1418 }
1419 
1420 PRMAN_INLINE unsigned char
1422 {
1423  return m_numUserLobes;
1424 }
1425 
1426 PRMAN_INLINE RtColorRGB const*
1428 {
1429  return m_diffuseLobes[i] + m_offset;
1430 }
1431 
1432 PRMAN_INLINE RtColorRGB const*
1434 {
1435  return m_specularLobes[i] + m_offset;
1436 }
1437 
1438 PRMAN_INLINE RtColorRGB const*
1440 {
1441  return m_userLobes[i] + m_offset;
1442 }
1443 
1446 {
1447  return m_diffuseLobes[i] + m_offset;
1448 }
1449 
1452 {
1453  return m_specularLobes[i] + m_offset;
1454 }
1455 
1458 {
1459  return m_userLobes[i] + m_offset;
1460 }
1461 
1462 PRMAN_INLINE unsigned char
1464 {
1465  return m_diffuseLpeIds[i];
1466 }
1467 
1468 PRMAN_INLINE unsigned char
1470 {
1471  return m_specularLpeIds[i];
1472 }
1473 
1474 PRMAN_INLINE unsigned char
1476 {
1477  return m_userLpeIds[i];
1478 }
1479 
1480 PRMAN_INLINE void
1482 {
1483  m_numDiffuseLobes = 0;
1484  // Removes all diffuse lobes from traits
1485  m_lobeTraits &= (k_RixBXTraitsAllSpecular | k_RixBXTraitsAllUser);
1486 }
1487 
1488 PRMAN_INLINE void
1490 {
1491  m_numSpecularLobes = 0;
1492  // Removes all specular lobes from traits
1493  m_lobeTraits &= (k_RixBXTraitsAllDiffuse | k_RixBXTraitsAllUser);
1494 }
1495 
1496 PRMAN_INLINE void
1498 {
1499  m_numUserLobes = 0;
1500  // Removes all user lobes from traits
1501  m_lobeTraits &= (k_RixBXTraitsAllDiffuse | k_RixBXTraitsAllSpecular);
1502 }
1503 
1505 RixBXActiveLobeWeights::SumAtIndex(int index, bool includeUserLobes) const
1506 {
1507  RtColorRGB sum(0.0f);
1508 
1509  int idx = m_offset + index;
1510  for (int i = 0; i < m_numDiffuseLobes; i++)
1511  sum += m_diffuseLobes[i][idx];
1512  for (int i = 0; i < m_numSpecularLobes; i++)
1513  sum += m_specularLobes[i][idx];
1514 
1515  if (includeUserLobes)
1516  {
1517  for (int i = 0; i < m_numUserLobes; i++)
1518  sum += m_userLobes[i][idx];
1519  }
1520 
1521  return sum;
1522 }
1523 
1524 PRMAN_INLINE void
1526  int index,
1527  float weight,
1528  bool includeUserLobes)
1529 {
1530  int idx = m_offset + index;
1531  for (int i = 0; i < m_numDiffuseLobes; i++)
1532  m_diffuseLobes[i][idx] *= weight;
1533  for (int i = 0; i < m_numSpecularLobes; i++)
1534  m_specularLobes[i][idx] *= weight;
1535 
1536  if (includeUserLobes)
1537  {
1538  for (int i = 0; i < m_numUserLobes; i++)
1539  m_userLobes[i][idx] *= weight;
1540  }
1541 }
1542 
1543 PRMAN_INLINE void
1545  int index,
1546  RtColorRGB const& weight,
1547  bool includeUserLobes)
1548 {
1549  int idx = m_offset + index;
1550  for (int i = 0; i < m_numDiffuseLobes; i++)
1551  m_diffuseLobes[i][idx] *= weight;
1552  for (int i = 0; i < m_numSpecularLobes; i++)
1553  m_specularLobes[i][idx] *= weight;
1554 
1555  if (includeUserLobes)
1556  {
1557  for (int i = 0; i < m_numUserLobes; i++)
1558  m_userLobes[i][idx] *= weight;
1559  }
1560 }
1561 
1562 PRMAN_INLINE void
1563 RixBXActiveLobeWeights::ZeroAtIndex(int index, bool includeUserLobes)
1564 {
1565  int idx = m_offset + index;
1566  for (int i = 0; i < m_numDiffuseLobes; i++)
1567  m_diffuseLobes[i][idx].Zero();
1568  for (int i = 0; i < m_numSpecularLobes; i++)
1569  m_specularLobes[i][idx].Zero();
1570 
1571  if (includeUserLobes)
1572  {
1573  for (int i = 0; i < m_numUserLobes; i++)
1574  m_userLobes[i][idx].Zero();
1575  }
1576 }
1577 
1578 //
1579 // struct RixBXLobeWeights implementation
1580 //
1581 
1584  : m_numPoints(0),
1585  m_offset(0),
1586  m_numDiffuseLobes(0),
1587  m_numSpecularLobes(0),
1588  m_numUserLobes(0)
1589 {
1590 }
1591 
1594  int numPoints,
1595  int numDiffuseLobes,
1596  int numSpecularLobes,
1597  int numUserLobes,
1598  RtColorRGB* diffuseLobes[],
1599  RtColorRGB* specularLobes[],
1600  RtColorRGB* userLobes[],
1601  int offset)
1602  : m_numPoints(numPoints),
1603  m_offset(offset),
1604  m_numDiffuseLobes((unsigned char)numDiffuseLobes),
1605  m_numSpecularLobes((unsigned char)numSpecularLobes),
1606  m_numUserLobes((unsigned char)numUserLobes)
1607 {
1608  for (int i = 0; i < numDiffuseLobes; i++)
1609  m_diffuseLobes[i] = diffuseLobes[i];
1610 
1611  for (int i = 0; i < numSpecularLobes; i++)
1612  m_specularLobes[i] = specularLobes[i];
1613 
1614  for (int i = 0; i < numUserLobes; i++)
1615  m_userLobes[i] = userLobes[i];
1616 }
1617 
1620  : m_numPoints(that.m_numPoints),
1621  m_offset(that.m_offset),
1622  m_activeLobeTraits(that.m_activeLobeTraits),
1623  m_numDiffuseLobes(that.m_numDiffuseLobes),
1624  m_numSpecularLobes(that.m_numSpecularLobes),
1625  m_numUserLobes(that.m_numUserLobes)
1626 {
1627  for (int i = 0; i < m_numDiffuseLobes; i++)
1628  m_diffuseLobes[i] = that.m_diffuseLobes[i];
1629 
1630  for (int i = 0; i < m_numSpecularLobes; i++)
1631  m_specularLobes[i] = that.m_specularLobes[i];
1632 
1633  for (int i = 0; i < m_numUserLobes; i++)
1634  m_userLobes[i] = that.m_userLobes[i];
1635 }
1636 
1639 {
1640  m_numPoints = that.m_numPoints;
1641  m_offset = that.m_offset;
1642  m_activeLobeTraits = that.m_activeLobeTraits;
1643  m_numDiffuseLobes = that.m_numDiffuseLobes;
1644  m_numSpecularLobes = that.m_numSpecularLobes;
1645  m_numUserLobes = that.m_numUserLobes;
1646 
1647  for (int i = 0; i < m_numDiffuseLobes; i++)
1648  m_diffuseLobes[i] = that.m_diffuseLobes[i];
1649 
1650  for (int i = 0; i < m_numSpecularLobes; i++)
1651  m_specularLobes[i] = that.m_specularLobes[i];
1652 
1653  for (int i = 0; i < m_numUserLobes; i++)
1654  m_userLobes[i] = that.m_userLobes[i];
1655 
1656  return *this;
1657 }
1658 
1659 PRMAN_INLINE RtColorRGB const*
1661 {
1662  return m_diffuseLobes[i] + m_offset;
1663 }
1664 
1665 PRMAN_INLINE RtColorRGB const*
1667 {
1668  return m_specularLobes[i] + m_offset;
1669 }
1670 
1671 PRMAN_INLINE RtColorRGB const*
1673 {
1674  return m_userLobes[i] + m_offset;
1675 }
1676 
1679 {
1680  return m_diffuseLobes[i] + m_offset;
1681 }
1682 
1685 {
1686  return m_specularLobes[i] + m_offset;
1687 }
1688 
1691 {
1692  return m_userLobes[i] + m_offset;
1693 }
1694 
1695 PRMAN_INLINE int
1697 {
1698  return m_numPoints;
1699 }
1700 
1701 PRMAN_INLINE void
1703 {
1704  m_numPoints = numPoints;
1705 }
1706 
1707 PRMAN_INLINE int
1709 {
1710  return m_offset;
1711 }
1712 
1713 PRMAN_INLINE void
1715 {
1716  m_offset = offset;
1717 }
1718 
1721 {
1722  return m_activeLobeTraits;
1723 }
1724 
1725 PRMAN_INLINE void
1727 {
1728  m_activeLobeTraits = lobes;
1729 }
1730 
1731 PRMAN_INLINE void
1733 {
1734  m_activeLobeTraits |= lobes;
1735 }
1736 
1737 PRMAN_INLINE int
1739 {
1740  return m_numDiffuseLobes;
1741 }
1742 
1743 PRMAN_INLINE int
1745 {
1746  return m_numSpecularLobes;
1747 }
1748 
1749 PRMAN_INLINE int
1751 {
1752  return m_numUserLobes;
1753 }
1754 
1757  RixBXLobeSampled lobeSampled,
1758  bool doInitializeWeights)
1759 {
1760  // If lobeSampled is valid, then either GetDiffuse() or
1761  // GetSpecular() must be true, so we will always trigger one of
1762  // the inner conditionals
1763  if (lobeSampled.GetValid())
1764  {
1765  RtColorRGB* p;
1766  unsigned char lpeId = lobeSampled.GetLpeId();
1767  unsigned short traitMask;
1768  unsigned short sampleMask;
1769  if (lobeSampled.GetUser())
1770  {
1771  p = m_userLobes[lpeId];
1772  traitMask = m_activeLobeTraits.GetUser();
1773  sampleMask = (1U << lpeId) & 0xFFFFU;
1774  }
1775  else if (lobeSampled.GetDiffuse())
1776  {
1777  p = m_diffuseLobes[lpeId];
1778  traitMask = m_activeLobeTraits.GetDiffuse();
1779  sampleMask = (1U << lpeId) & 0x0FU;
1780  }
1781  else { // if (lobeSampled.GetSpecular())
1782  p = m_specularLobes[lpeId];
1783  traitMask = m_activeLobeTraits.GetSpecular();
1784  sampleMask = (1U << lpeId) & 0xFFU;
1785  }
1786  if (!(traitMask & sampleMask))
1787  {
1788  RixBXLobeTraits traits(lobeSampled);
1789  m_activeLobeTraits |= traits;
1790  if (doInitializeWeights)
1791  memset(p, 0, m_numPoints * sizeof(RtColorRGB));
1792  }
1793  return p + m_offset;
1794  }
1795  else
1796  return NULL;
1797 }
1798 
1799 PRMAN_INLINE void
1801 {
1802  r.m_numDiffuseLobes = r.m_numSpecularLobes = r.m_numUserLobes = 0;
1803  r.m_lobeTraits = m_activeLobeTraits;
1804  r.m_offset = m_offset;
1805 
1806  int mask;
1807  unsigned long lpeId;
1808  mask = m_activeLobeTraits.GetDiffuse() & ((1 << m_numDiffuseLobes) - 1);
1809  while (mask)
1810  {
1811  lpeId = RixFindFirstSetBit(mask);
1812  mask &= mask - 1;
1813  r.m_diffuseLobes[r.m_numDiffuseLobes] = m_diffuseLobes[lpeId];
1814  r.m_diffuseLpeIds[r.m_numDiffuseLobes] = (unsigned char)lpeId;
1815  r.m_numDiffuseLobes++;
1816  }
1817  mask = m_activeLobeTraits.GetSpecular() & ((1 << m_numSpecularLobes) - 1);
1818  while (mask)
1819  {
1820  lpeId = RixFindFirstSetBit(mask);
1821  mask &= mask - 1;
1822  r.m_specularLobes[r.m_numSpecularLobes] = m_specularLobes[lpeId];
1823  r.m_specularLpeIds[r.m_numSpecularLobes] = (unsigned char)lpeId;
1824  r.m_numSpecularLobes++;
1825  }
1826  mask = m_activeLobeTraits.GetUser() & ((1 << m_numUserLobes) - 1);
1827  while (mask)
1828  {
1829  lpeId = RixFindFirstSetBit(mask);
1830  mask &= mask - 1;
1831  r.m_userLobes[r.m_numUserLobes] = m_userLobes[lpeId];
1832  r.m_userLpeIds[r.m_numUserLobes] = (unsigned char)lpeId;
1833  r.m_numUserLobes++;
1834  }
1835 }
1836 
1837 PRMAN_INLINE void
1839  RixBXLobeWeights const& rhs,
1840  RixBXActiveLobeWeights& activeLhs,
1841  RixBXActiveLobeWeights& activeRhs) const
1842 {
1843  int numDiffuseLobes = 0;
1844  int numSpecularLobes = 0;
1845  int numUserLobes = 0;
1846 
1847  RixBXLobeTraits lobes = (m_activeLobeTraits & rhs.m_activeLobeTraits);
1848  int mask;
1849  unsigned long lpeId;
1850  int nDiff = std::min(m_numDiffuseLobes, rhs.m_numDiffuseLobes);
1851  mask = lobes.GetDiffuse() & ((1 << nDiff) - 1);
1852  while (mask)
1853  {
1854  lpeId = RixFindFirstSetBit(mask);
1855  mask &= mask - 1;
1856  activeLhs.m_diffuseLobes[numDiffuseLobes] = m_diffuseLobes[lpeId];
1857  activeRhs.m_diffuseLobes[numDiffuseLobes] = rhs.m_diffuseLobes[lpeId];
1858  activeLhs.m_diffuseLpeIds[numDiffuseLobes] = (unsigned char)lpeId;
1859  activeRhs.m_diffuseLpeIds[numDiffuseLobes] = (unsigned char)lpeId;
1860  numDiffuseLobes++;
1861  }
1862  int nSpec = std::min(m_numSpecularLobes, rhs.m_numSpecularLobes);
1863  mask = lobes.GetSpecular() & ((1 << nSpec) - 1);
1864  while (mask)
1865  {
1866  lpeId = RixFindFirstSetBit(mask);
1867  mask &= mask - 1;
1868  activeLhs.m_specularLobes[numSpecularLobes] = m_specularLobes[lpeId];
1869  activeRhs.m_specularLobes[numSpecularLobes] = rhs.m_specularLobes[lpeId];
1870  activeLhs.m_specularLpeIds[numSpecularLobes] = (unsigned char)lpeId;
1871  activeRhs.m_specularLpeIds[numSpecularLobes] = (unsigned char)lpeId;
1872  numSpecularLobes++;
1873  }
1874  int nUser = std::min(m_numUserLobes, rhs.m_numUserLobes);
1875  mask = lobes.GetUser() & ((1 << nUser) - 1);
1876  while (mask)
1877  {
1878  lpeId = RixFindFirstSetBit(mask);
1879  mask &= mask - 1;
1880  activeLhs.m_userLobes[numUserLobes] = m_userLobes[lpeId];
1881  activeRhs.m_userLobes[numUserLobes] = rhs.m_userLobes[lpeId];
1882  activeLhs.m_userLpeIds[numUserLobes] = (unsigned char)lpeId;
1883  activeRhs.m_userLpeIds[numUserLobes] = (unsigned char)lpeId;
1884  numUserLobes++;
1885  }
1886 
1887  activeLhs.m_offset = m_offset;
1888  activeLhs.m_lobeTraits = lobes;
1889  activeLhs.m_numDiffuseLobes = (unsigned char)numDiffuseLobes;
1890  activeLhs.m_numSpecularLobes = (unsigned char)numSpecularLobes;
1891  activeLhs.m_numUserLobes = (unsigned char)numUserLobes;
1892 
1893  activeRhs.m_offset = rhs.m_offset;
1894  activeRhs.m_lobeTraits = lobes;
1895  activeRhs.m_numDiffuseLobes = (unsigned char)numDiffuseLobes;
1896  activeRhs.m_numSpecularLobes = (unsigned char)numSpecularLobes;
1897  activeRhs.m_numUserLobes = (unsigned char)numUserLobes;
1898 }
1899 
1900 PRMAN_INLINE void
1902  int index,
1903  RixBXActiveLobeWeights const& src,
1904  bool includeUserLobes)
1905 {
1906  // Copy over just the active diffuse, specular, and user lobes in 'src'.
1907  int nDiff = src.GetNumDiffuseLobes();
1908  for (int i = 0; i < nDiff; i++)
1909  {
1910  int lpeId = src.GetDiffuseLpeId(i);
1911  GetDiffuseLobe(lpeId)[index] = src.GetDiffuseLobe(i)[index];
1912  }
1913 
1914  int nSpec = src.GetNumSpecularLobes();
1915  for (int i = 0; i < nSpec; i++)
1916  {
1917  int lpeId = src.GetSpecularLpeId(i);
1918  GetSpecularLobe(lpeId)[index] = src.GetSpecularLobe(i)[index];
1919  }
1920 
1921  if (includeUserLobes)
1922  {
1923  int nUser = src.GetNumUserLobes();
1924  for (int i = 0; i < nUser; i++)
1925  {
1926  int lpeId = src.GetUserLpeId(i);
1927  GetUserLobe(lpeId)[index] = src.GetUserLobe(i)[index];
1928  }
1929  }
1930 }
1931 
1932 PRMAN_INLINE void
1934  int index,
1935  RixBXActiveLobeWeights const& src,
1936  bool includeUserLobes)
1937 {
1938  // Add in just the active diffuse, specular, and user lobes in 'src'.
1939  int nDiff = src.GetNumDiffuseLobes();
1940  for (int i = 0; i < nDiff; i++)
1941  {
1942  int lpeId = src.GetDiffuseLpeId(i);
1943  GetDiffuseLobe(lpeId)[index] += src.GetDiffuseLobe(i)[index];
1944  }
1945 
1946  int nSpec = src.GetNumSpecularLobes();
1947  for (int i = 0; i < nSpec; i++)
1948  {
1949  int lpeId = src.GetSpecularLpeId(i);
1950  GetSpecularLobe(lpeId)[index] += src.GetSpecularLobe(i)[index];
1951  }
1952 
1953  if (includeUserLobes)
1954  {
1955  int nUser = src.GetNumUserLobes();
1956  for (int i = 0; i < nUser; i++)
1957  {
1958  int lpeId = src.GetUserLpeId(i);
1959  GetUserLobe(lpeId)[index] += src.GetUserLobe(i)[index];
1960  }
1961  }
1962 }
1963 
1964 // Randomly choose between numThresholds+1 scattering lobes using xi
1965 PRMAN_INLINE int
1966 RixBXChoose(float const xi, int const numThresholds, float const* thresholds)
1967 {
1968  // below lowest threshold?
1969  if (xi < thresholds[0])
1970  {
1971  return 0; // chose lobe 0
1972  }
1973  // between thresholds?
1974  for (int i = 1; i < numThresholds; i++)
1975  {
1976  if (thresholds[i - 1] <= xi && xi < thresholds[i])
1977  {
1978  return i; // chose lobe i
1979  }
1980  }
1981  // must be above highest threshold
1982  return numThresholds; // chose last lobe
1983 }
1984 
1985 PRMAN_INLINE bool
1986 RixBXChooseLobe(float const xi,
1988  RixBXLobeSampled &chosenLobe)
1989 {
1990  // Stochastically choose a lobe
1991  int numDiffuse = lw.GetNumDiffuseLobes();
1992  int numSpecular = lw.GetNumSpecularLobes();
1993  int totalLobes = numDiffuse + numSpecular;
1994 
1995  // We only ever consider the first point
1996  const int point = 0;
1997 
1998  // Keep track of the number of non-zero lobe responses
1999  int nLobes = 0;
2000 
2001  // Build an importance table from all lobes
2002  float importance[k_RixBXMaxNumDiffuseLobes+k_RixBXMaxNumSpecularLobes];
2003  float totalImportance = 0.f;
2004  int lobeId = 0;
2005  for( int l = 0; l < numDiffuse; l++ )
2006  {
2007  RtColorRGB *pLobe = lw.GetDiffuseLobe(l);
2008  float lum = pLobe[point].Luminance();
2009 
2010  if (lum > 0.f) {
2011  nLobes += 1;
2012  lobeId = l;
2013  }
2014 
2015  totalImportance += lum;
2016  importance[l] = totalImportance;
2017  }
2018  bool firstLobeIsDiffuse = nLobes > 0;
2019  for( int l = 0; l < numSpecular; l++ )
2020  {
2021  RtColorRGB *pLobe = lw.GetSpecularLobe(l);
2022  float lum = pLobe[point].Luminance();
2023 
2024  if (lum > 0.f) {
2025  nLobes += 1;
2026  lobeId = l;
2027  }
2028 
2029  totalImportance += lum;
2030  importance[numDiffuse+l] = totalImportance;
2031  }
2032 
2033  if( totalImportance == 0.f || (nLobes == 0) )
2034  {
2035  // This can happen if the sampled/evaluated lobe has a black albedo at
2036  // this point. Indicate as such to the caller.
2037  chosenLobe.SetValid(false);
2038  return false;
2039  }
2040 
2041  // Early out if only one lobe
2042  if( nLobes == 1 )
2043  {
2044  bool isSpecular = !firstLobeIsDiffuse;
2045  unsigned char lpeId = isSpecular ? lw.GetSpecularLpeId(lobeId) : lw.GetDiffuseLpeId(lobeId);
2046  chosenLobe.SetSpecular( isSpecular );
2047  chosenLobe.SetLpeId( lpeId );
2048  chosenLobe.SetValid(true);
2049  return true;
2050  }
2051 
2052  // Normalize the importance
2053  for( int l = 0; l < totalLobes; l++ )
2054  importance[l] /= totalImportance;
2055 
2056  // Choose the lobe
2057  int lobe = RixBXChoose( xi, totalLobes-1, importance );
2058 
2059  if( lobe < 0 || lobe >= totalLobes )
2060  {
2061  // This should never happen but invalidate the event and return in any
2062  // error case.
2063  assert(0);
2064  chosenLobe.SetValid(false);
2065  return false;
2066  }
2067 
2068  // Get the probability of having chosen this lobe
2069  float probability = (lobe == 0) ?
2070  importance[0] : (importance[lobe] - importance[lobe-1]);
2071 
2072  bool isDiffuse = lobe < numDiffuse;
2073  if( !isDiffuse ) lobe -= numDiffuse;
2074 
2075  unsigned char lpeId = 0;
2076 
2077  for( int l = 0; l < numDiffuse; l++ )
2078  {
2079  RtColorRGB *pDiffuse = lw.GetDiffuseLobe(l);
2080  if( isDiffuse && (l == lobe) )
2081  {
2082  lpeId = lw.GetDiffuseLpeId(l);
2083  // Modify the weight
2084  pDiffuse[point] /= probability;
2085  }
2086  else
2087  pDiffuse[point].Zero();
2088  }
2089 
2090  for( int l = 0; l < numSpecular; l++ )
2091  {
2092  RtColorRGB *pSpec = lw.GetSpecularLobe(l);
2093  if( !isDiffuse && (l == lobe) )
2094  {
2095  lpeId = lw.GetSpecularLpeId(l);
2096  // Modify the weight
2097  pSpec[point] /= probability;
2098  }
2099  else
2100  pSpec[point].Zero();
2101  }
2102 
2103  // Fill in the chosen lobe info
2104  chosenLobe.SetValid(true);
2105  chosenLobe.SetSpecular( !isDiffuse );
2106  chosenLobe.SetLpeId( lpeId );
2107  return true;
2108 }
2109 
2110 PRMAN_INLINE void
2111 RixBXChooseLobe(int const npoints,
2112  float const* xi,
2113  RixBXLobeWeights& lw,
2114  RixBXLobeSampled* lobeSampled)
2115 {
2116  RixBXActiveLobeWeights activeWeights;
2117  lw.GetActiveLobes(activeWeights);
2118  int offset = activeWeights.GetOffset();
2119  for( int i = 0; i < npoints; i++ )
2120  {
2121  activeWeights.SetOffset(offset+i);
2122 
2123  if( !lobeSampled[i].GetValid() )
2124  {
2125  continue;
2126  }
2127 
2128  RixBXLobeSampled chosenLobe;
2129  if( RixBXChooseLobe( xi[i], activeWeights, chosenLobe) )
2130  {
2131  lobeSampled[i].SetSpecular(chosenLobe.GetSpecular());
2132  lobeSampled[i].SetLpeId(chosenLobe.GetLpeId());
2133  }
2134  }
2135 }
2136 
2137 PRMAN_INLINE void
2139  RixBXLobeTraits &traits)
2140 {
2141  RixBXLobeSampled chosenLobe;
2142 
2143  if(RixBXChooseLobe(xi, lw, chosenLobe))
2144  {
2145  // Modify the traits
2146  if( chosenLobe.GetSpecular() )
2147  {
2148  traits.SetDiffuse(0);
2149  unsigned short s = (unsigned short)(1U << chosenLobe.GetLpeId());
2150  traits.SetSpecular(s);
2151  }
2152  else
2153  {
2154  unsigned short d = (unsigned short)(1U << chosenLobe.GetLpeId());
2155  traits.SetDiffuse(d);
2156  traits.SetSpecular(0);
2157  }
2158  }
2159 }
2160 
2161 #endif
PRMAN_INLINE void SetLpeId(unsigned char val)
Definition: RixBxdfLobe.h:804
PRMAN_INLINE unsigned char GetUnused() const
Definition: RixBxdfLobe.h:747
PRMAN_INLINE bool GetThinShadowFlag() const
Definition: RixBxdfLobe.h:741
unsigned reflectSubset
includes solid angle (non-discrete) lobe
Definition: RixBxdfLobe.h:274
PRMAN_INLINE bool GetMaxDiffuseDepth() const
Definition: RixBxdfLobe.h:1033
PRMAN_INLINE void SetDiscrete(bool val)
Definition: RixBxdfLobe.h:759
PRMAN_INLINE void ClearAllUserLobes()
Definition: RixBxdfLobe.h:1497
PRMAN_INLINE bool GetContinuation() const
Definition: RixBxdfLobe.h:1003
PRMAN_INLINE bool HasAnyDiffSpec() const
Definition: RixBxdfLobe.h:1148
PRMAN_INLINE void SetUser(bool val)
Definition: RixBxdfLobe.h:798
pxrcore::ColorRGB RtColorRGB
PRMAN_INLINE bool HasAnyUser() const
Returns true if any user bits are set.
Definition: RixBxdfLobe.h:1170
PRMAN_INLINE bool GetSpecular() const
Definition: RixBxdfLobe.h:673
PRMAN_INLINE RixBXActiveLobeWeights()
Constructor; sets the number of diffuse and specular lobes to zero.
Definition: RixBxdfLobe.h:1284
PRMAN_INLINE bool GetValid() const
Definition: RixBxdfLobe.h:649
PRMAN_INLINE void AddWeightAtIndex(int index, RixBXActiveLobeWeights const &src, bool includeUserLobes=false)
Definition: RixBxdfLobe.h:1933
PRMAN_INLINE RixBXLobeWeights & operator=(RixBXLobeWeights const &that)
Assignment.
Definition: RixBxdfLobe.h:1638
PRMAN_INLINE bool HasAnyDiffuse() const
Definition: RixBxdfLobe.h:1156
PRMAN_INLINE void SetUnused(unsigned char val)
Definition: RixBxdfLobe.h:822
unsigned S
1 bit / diffuse lobe
Definition: RixBxdfLobe.h:278
PRMAN_INLINE bool GetDiscrete() const
Definition: RixBxdfLobe.h:655
This struct represents the characteristics of just one lobe of a bxdf.
Definition: RixBxdfLobe.h:64
PRMAN_INLINE RtColorRGB SumAtIndex(int index, bool includeUserLobes=false) const
Definition: RixBxdfLobe.h:1505
PRMAN_INLINE void GetActiveLobesIntersection(RixBXLobeWeights const &rhs, RixBXActiveLobeWeights &activeLhs, RixBXActiveLobeWeights &activeRhs) const
Definition: RixBxdfLobe.h:1838
PRMAN_INLINE void SetValid(bool val)
Definition: RixBxdfLobe.h:1039
PRMAN_INLINE bool GetSolidAngle() const
Definition: RixBxdfLobe.h:661
unsigned continuationSubset
include transmitted rays
Definition: RixBxdfLobe.h:276
PRMAN_INLINE bool GetDiffuse() const
Definition: RixBxdfLobe.h:667
unsigned maxspeculardepth
1 bit / user lobe
Definition: RixBxdfLobe.h:281
PRMAN_INLINE void SetUser(unsigned short bits)
Definition: RixBxdfLobe.h:1087
unsigned discreteSubset
if 0, its an invalid sample
Definition: RixBxdfLobe.h:272
PRMAN_INLINE void SetActiveLobeTraits(RixBXLobeTraits lobes)
Definition: RixBxdfLobe.h:1726
PRMAN_INLINE int GetNumUserLobes() const
Definition: RixBxdfLobe.h:1750
unsigned U
1 bit / specular lobe
Definition: RixBxdfLobe.h:279
PRMAN_INLINE int GetNumDiffuseLobes() const
Definition: RixBxdfLobe.h:1738
unsigned solidAngleSubset
includes discrete lobe
Definition: RixBxdfLobe.h:273
PRMAN_INLINE void AddActiveLobeTraits(RixBXLobeTraits lobes)
Definition: RixBxdfLobe.h:1732
PRMAN_INLINE unsigned int RixFindFirstSetBit(unsigned long long v)
PRMAN_INLINE unsigned char GetLobeId() const
Definition: RixBxdfLobe.h:724
PRMAN_INLINE int GetOffset() const
Definition: RixBxdfLobe.h:1385
PRMAN_INLINE int GetOffset() const
Definition: RixBxdfLobe.h:1708
PRMAN_INLINE void SetContinuation(bool val)
Definition: RixBxdfLobe.h:1069
PRMAN_INLINE RtColorRGB const * GetUserLobe(int i) const
Definition: RixBxdfLobe.h:1672
PRMAN_INLINE bool GetDiscrete() const
Definition: RixBxdfLobe.h:979
PRMAN_INLINE bool GetMaxSpecularDepth() const
Definition: RixBxdfLobe.h:1027
PRMAN_INLINE RixBXLobeTraits GetLobeTraits() const
Definition: RixBxdfLobe.h:1397
PRMAN_INLINE bool GetContinuation() const
Definition: RixBxdfLobe.h:700
PRMAN_INLINE RixBXLobeTraits()
Constructor; initializes all fields to zero.
Definition: RixBxdfLobe.h:885
unsigned short continuation
Definition: RixBxdfLobe.h:146
PRMAN_INLINE void SetSpecular(unsigned short bits)
Definition: RixBxdfLobe.h:1081
PRMAN_INLINE bool HasAny() const
Definition: RixBxdfLobe.h:1142
PRMAN_INLINE unsigned char GetDiffuseLpeId(int i) const
Definition: RixBxdfLobe.h:1463
PRMAN_INLINE unsigned short GetUser() const
Definition: RixBxdfLobe.h:1021
unsigned short lpeId
0 is standard, 1 is user-specific
Definition: RixBxdfLobe.h:148
unsigned D
include continuation rays
Definition: RixBxdfLobe.h:277
PRMAN_INLINE bool GetTransmit(bool *entering=NULL) const
Definition: RixBxdfLobe.h:685
PRMAN_INLINE void CopyWeightAtIndex(int index, RixBXActiveLobeWeights const &src, bool includeUserLobes=false)
Definition: RixBxdfLobe.h:1901
PRMAN_INLINE void SetTransmit(bool val)
Definition: RixBxdfLobe.h:1063
PRMAN_INLINE void SetContinuation(bool val)
Definition: RixBxdfLobe.h:792
PRMAN_INLINE unsigned char GetNumSpecularLobes() const
Definition: RixBxdfLobe.h:1415
PRMAN_INLINE void SetAll()
Definition: RixBxdfLobe.h:1126
PRMAN_INLINE RixBXLobeTraits operator &(RixBXLobeTraits const &lhs, RixBXLobeTraits const &rhs)
Bitwise AND all fields.
Definition: RixBxdfLobe.h:1228
PRMAN_INLINE void SetMaxSpecularDepth(bool val)
Definition: RixBxdfLobe.h:1093
PRMAN_INLINE unsigned char GetLpeId() const
Definition: RixBxdfLobe.h:718
PRMAN_INLINE void MultiplyByWeightAtIndex(int index, float weight, bool includeUserLobes=false)
Definition: RixBxdfLobe.h:1525
PRMAN_INLINE void SetNumPoints(int numPoints)
Definition: RixBxdfLobe.h:1702
PRMAN_INLINE RixBXLobeSampled()
Constructor; initializes the valid bit to false.
Definition: RixBxdfLobe.h:599
PRMAN_INLINE void SetLobeTraits(RixBXLobeTraits lobes)
Definition: RixBxdfLobe.h:1403
PRMAN_INLINE RixBXActiveLobeWeights & operator=(RixBXActiveLobeWeights const &that)
Assignment.
Definition: RixBxdfLobe.h:1357
unsigned transmitSubset
include reflected rays
Definition: RixBxdfLobe.h:275
PRMAN_INLINE bool GetValid() const
Definition: RixBxdfLobe.h:973
PRMAN_INLINE RixBXLobeWeights()
Definition: RixBxdfLobe.h:1583
PRMAN_INLINE void SetDiffuse(unsigned short bits)
Definition: RixBxdfLobe.h:1075
unsigned short lobeId
specular or diffuse lobe identity
Definition: RixBxdfLobe.h:149
PRMAN_INLINE RixBXLobeTraits const & operator &=(RixBXLobeTraits const &rhs)
Bitwise AND all fields with the right-hand-side.
PRMAN_INLINE unsigned char GetNumDiffuseLobes() const
Definition: RixBxdfLobe.h:1409
PRMAN_INLINE RtColorRGB * AddActiveLobe(RixBXLobeSampled lobe, bool doInitializeWeights=true)
Definition: RixBxdfLobe.h:1756
unsigned short unused
1 to flag thin shadow, 0 otherwise
Definition: RixBxdfLobe.h:151
PRMAN_INLINE RtColorRGB const * GetDiffuseLobe(int i) const
Definition: RixBxdfLobe.h:1427
PRMAN_INLINE void SetOffset(int offset)
Definition: RixBxdfLobe.h:1391
PRMAN_INLINE RtColorRGB const * GetUserLobe(int i) const
Definition: RixBxdfLobe.h:1439
Id for RixLPEInfo interface.
PRMAN_INLINE unsigned short GetSpecular() const
Definition: RixBxdfLobe.h:1015
PRMAN_INLINE void SetEntering(bool entering)
Definition: RixBxdfLobe.h:784
PRMAN_INLINE void ClearAllSpecularLobes()
Definition: RixBxdfLobe.h:1489
PRMAN_INLINE RixBXLobeTraits GetActiveLobeTraits() const
Definition: RixBxdfLobe.h:1720
#define PRMAN_INLINE
Definition: prmanapi.h:86
PRMAN_INLINE void SetSpecular(bool val)
Definition: RixBxdfLobe.h:765
PRMAN_INLINE void SetMaxDiffuseDepth(bool val)
Definition: RixBxdfLobe.h:1099
PRMAN_INLINE RixBXLobeSampled RixBXLookupLobeByName(RixContext &ctx, bool discrete, bool specular, bool reflect, bool user, unsigned char lobeId, char const *name)
Definition: RixBxdfLobe.h:862
PRMAN_INLINE void ClearAllDiffuseLobes()
Definition: RixBxdfLobe.h:1481
PRMAN_INLINE RtColorRGB const * GetSpecularLobe(int i) const
Definition: RixBxdfLobe.h:1666
PRMAN_INLINE int GetNumSpecularLobes() const
Definition: RixBxdfLobe.h:1744
PRMAN_INLINE void SetLobeId(unsigned char val)
Definition: RixBxdfLobe.h:810
PRMAN_INLINE void SetDiscrete(bool val)
Definition: RixBxdfLobe.h:1045
PRMAN_INLINE bool GetSolidAngle() const
Definition: RixBxdfLobe.h:985
PRMAN_INLINE bool GetEntering() const
Definition: RixBxdfLobe.h:694
PRMAN_INLINE unsigned char GetNumUserLobes() const
Definition: RixBxdfLobe.h:1421
PRMAN_INLINE unsigned char GetUserLpeId(int i) const
Definition: RixBxdfLobe.h:1475
PRMAN_INLINE int GetNumPoints() const
Definition: RixBxdfLobe.h:1696
PRMAN_INLINE bool GetReflect() const
Definition: RixBxdfLobe.h:679
unsigned short entering
0 is refract, 1 is reflect
Definition: RixBxdfLobe.h:144
PRMAN_INLINE bool HasAnySpecular() const
Definition: RixBxdfLobe.h:1163
PRMAN_INLINE void ZeroAtIndex(int index, bool includeUserLobes=false)
Definition: RixBxdfLobe.h:1563
PRMAN_INLINE unsigned Serialize() const
Definition: RixBxdfLobe.h:1176
PRMAN_INLINE void SetOffset(int offset)
Definition: RixBxdfLobe.h:1714
PRMAN_INLINE RtColorRGB const * GetSpecularLobe(int i) const
Definition: RixBxdfLobe.h:1433
PRMAN_INLINE bool RixBXChooseLobe(float const xi, RixBXActiveLobeWeights &lw, RixBXLobeSampled &chosenLobe)
Definition: RixBxdfLobe.h:1986
PRMAN_INLINE RtColorRGB const * GetDiffuseLobe(int i) const
Definition: RixBxdfLobe.h:1660
PRMAN_INLINE bool GetUser() const
Definition: RixBxdfLobe.h:712
PRMAN_INLINE void SetNone()
Zero all fields.
Definition: RixBxdfLobe.h:1105
PRMAN_INLINE void SetTransmit(bool entering)
Definition: RixBxdfLobe.h:777
PRMAN_INLINE void SetReflect(bool val)
Definition: RixBxdfLobe.h:1057
PRMAN_INLINE bool LobeIdIsSubsurface() const
Definition: RixBxdfLobe.h:730
PRMAN_INLINE void SetThinShadowFlag(bool val)
Definition: RixBxdfLobe.h:816
PRMAN_INLINE unsigned short GetDiffuse() const
Definition: RixBxdfLobe.h:1009
PRMAN_INLINE void SetValid(bool val)
Definition: RixBxdfLobe.h:753
PRMAN_INLINE bool GetReflect() const
Definition: RixBxdfLobe.h:991
PRMAN_INLINE void Set(bool vDiscrete, bool vSpecular, bool vReflect, bool vContinuation, bool vUser, unsigned char vLpeId, unsigned char vLobeId, bool vThinShadowFlag=false)
Set all fields and also sets the valid bit to true.
Definition: RixBxdfLobe.h:828
PRMAN_INLINE RixBXLobeTraits operator|(RixBXLobeTraits const &lhs, RixBXLobeTraits const &rhs)
Bitwise OR all fields.
Definition: RixBxdfLobe.h:1254
PRMAN_INLINE bool CompareLobeID(RixBXLobeSampled const &rhs) const
Definition: RixBxdfLobe.h:82
virtual RixInterface * GetRixInterface(RixInterfaceId id) const =0
unsigned short discrete
0 means all other fields are invalid
Definition: RixBxdfLobe.h:140
PRMAN_INLINE unsigned char GetSpecularLpeId(int i) const
Definition: RixBxdfLobe.h:1469
unsigned short reflect
0 is diffuse, 1 is specular
Definition: RixBxdfLobe.h:143
PRMAN_INLINE bool GetScattering() const
Definition: RixBxdfLobe.h:706
PRMAN_INLINE unsigned short Serialize() const
Definition: RixBxdfLobe.h:852
PRMAN_INLINE void SetReflect()
Definition: RixBxdfLobe.h:771
PRMAN_INLINE bool GetTransmit() const
Definition: RixBxdfLobe.h:997
PRMAN_INLINE RixBXLobeTraits const & operator|=(RixBXLobeTraits const &rhs)
Bitwise OR all fields with the right-hand-side.
Definition: RixBxdfLobe.h:1205
PRMAN_INLINE void SetSolidAngle(bool val)
Definition: RixBxdfLobe.h:1051
unsigned short user
0 is scattering, 1 is continuation
Definition: RixBxdfLobe.h:147
PRMAN_INLINE int RixBXChoose(float const xi, int const numThresholds, float const *thresholds)
Definition: RixBxdfLobe.h:1966
unsigned short thinShadow
an optional user label for the sample
Definition: RixBxdfLobe.h:150
PRMAN_INLINE void GetActiveLobes(RixBXActiveLobeWeights &r) const
Return just the active lobes in the provided RixBXActiveLobeWeights.
Definition: RixBxdfLobe.h:1800