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