RenderMan  26.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
RixBxdf.h
Go to the documentation of this file.
1 /*
2 # ------------------------------------------------------------------------------
3 #
4 # Copyright (c) 2021 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 RixBxdf_h
38 #define RixBxdf_h
39 
40 #include <cstddef> // for NULL
41 #include <vector> // for vector
42 #include "RixBxdfLobe.h" // for RixBXLobeTraits, etc
43 #include "RixShading.h" // for RixSCShadingMode, etc
44 #include "prmanapi.h" // for PRMANEXPORT, PRMAN_INLINE
45 #include "RiTypesHelper.h" // for RtColorRGB, etc
46 
47 class RixBxdf;
50 class RixOpacity;
51 class RixRNG;
53 class RixPostLighting;
54 struct RtRayGeometry;
55 
125 {
126  // clang-format off
127  k_RixBXEmptyDomain = 0, // black hole (possibly emissive)
128 
129  // Elementary subdomains
130  // V = view , L = light/connect/merge, N = normal, ------ = surface
131  k_RixBXOutsideReflect = 1, // V\ N /L
132  //----------
133  //
134 
136  //----------
137  // V/
138 
140  //----------
141  // V/ \L
142 
144  //----------
145  // \L
146 
147  // Common domains
150  // for reference to v19/20 shaders, these are equivalent
151  // k_RixBXFront = k_RixBXReflect,
152  // k_RixBXBack = k_RixBXTransmit,
156 
157  k_RixBXVolume = 16 // light from all directions
158  // clang-format on
159 };
160 
161 PRMAN_INLINE bool RixVisibleToDomain(RixBXEvaluateDomain domain, RtVector3 const& L,
162  RtVector3 const& N, RtVector3 const& V)
163 {
164  // we've been told to sample everything, so don't reject
165  if (domain & k_RixBXVolume || domain == k_RixBXBoth) return true;
166  if (domain == k_RixBXEmptyDomain) return false;
167 #if 0
168  // reference implementation
169  float dpL = L.Dot(N);
170  float dpV = N.Dot(V);
171 
172  switch(domain){
173  case k_RixBXOutsideTransmit: // 2
174  return (dpL > 0.0f && dpV < 0.0f);
175  break;
176  case k_RixBXOutsideReflect: // 1
177  return (dpL > 0.0f && dpV > 0.0f);
178  break;
179  case k_RixBXInsideTransmit: // 8
180  return (dpL < 0.0f && dpV > 0.0f);
181  break;
182  case k_RixBXInsideReflect: // 4
183  return (dpL < 0.0f && dpV < 0.0f);
184  break;
185  case k_RixBXInside: // 12
186  return (dpL < 0.0f);
187  break;
188  case k_RixBXOutside: // 3
189  return (dpL > 0.0f);
190  break;
191  case k_RixBXReflect: // 5
192  return ((dpL > 0.0f) != (dpV < 0.0f));
193  break;
194  case k_RixBXTransmit: // 10
195  return ((dpL > 0.0f) == (dpV < 0.0f));
196  break;
197  case k_RixBXOutsideTransmit | k_RixBXInsideReflect: // 2 | 4 = 6
198  return ((dpL > 0.0f && dpV < 0.0f) || (dpL < 0.0f && dpV < 0.0f));
199  break;
200  case k_RixBXOutsideReflect | k_RixBXInsideTransmit: // 1 | 8 = 9
201  return ((dpL > 0.0f && dpV > 0.0f) || (dpL < 0.0f && dpV > 0.0f));
202  break;
204  return ((dpL > 0.0f && dpV < 0.0f) || (dpL > 0.0f && dpV > 0.0f) ||
205  (dpL < 0.0f && dpV < 0.0f));
206  break;
208  return ((dpL > 0.0f && dpV > 0.0f) || (dpL < 0.0f && dpV > 0.0f) ||
209  (dpL < 0.0f && dpV < 0.0f));
210  break;
212  return ((dpL > 0.0f && dpV < 0.0f) || (dpL < 0.0f && dpV > 0.0f) ||
213  (dpL < 0.0f && dpV < 0.0f));
214  break;
216  return ((dpL > 0.0f && dpV > 0.0f) || (dpL > 0.0f && dpV < 0.0f) ||
217  (dpL < 0.0f && dpV > 0.0f));
218  break;
219  default:
220  return false;
221  }
222 #else
223  float dpL = L.Dot(N);
224  if (domain == k_RixBXInside || domain == k_RixBXOutside)
225  {
226  // We can avoid the dot product with V in these two cases
227  if (domain == k_RixBXOutside) return (dpL > 0.0f);
228  if (domain == k_RixBXInside) return (dpL < 0.0f);
229  }
230  else
231  {
232  float dpV = N.Dot(V);
233  bool valid = false;
234  // clang-format off
235  valid = valid ||
236  ((domain & k_RixBXOutsideTransmit) && (dpL > 0.0f && dpV < 0.0f));
237  valid = valid ||
238  ((domain & k_RixBXOutsideReflect) && (dpL > 0.0f && dpV > 0.0f));
239  valid = valid ||
240  ((domain & k_RixBXInsideTransmit) && (dpL < 0.0f && dpV > 0.0f));
241  valid = valid ||
242  ((domain & k_RixBXInsideReflect) && (dpL < 0.0f && dpV < 0.0f));
243  return valid;
244  // clang-format on
245  }
246 #endif
247  return true;
248 }
249 
253 {
257 };
258 
262 {
267 };
268 
272 {
273 public:
274  int GetInterface() const override
275  {
276  return k_RixBxdfFactory;
277  }
278 
306  {
307  // clang-format off
309 
310  // returns RixOpacity for opacity
312  // do not set unless k_ComputesOpacity is set
314 
315  // returns RixOpacity for presence
317  // do not set unless k_ComputesPresence is set
319 
321 
322  // has interior integration requirements
324  // supports transmission
326  // requires volume, not surface, primvars
328  // supports overlapping of interiors
330  //
332  // subsurface interior integration
334 
335  // computes opacity for camera/indirect rays too
337 
338  // blocks volumes. Will only have an effect if
339  // kComputesInterior is also not set.
341 
342  // returns RixPostLighting
344 
345  // cannot support non-stochastic opacity
347 
348  // clang-format on
349  };
350 
351  virtual int GetInstanceHints(void* instanceData) const = 0;
352 
357  enum
358  {
360  };
361  virtual void RegisterTemporalVolumeParams(void* instanceData,
362  std::vector<int>& paramId) const = 0;
363 
392  virtual RixBxdf* BeginScatter(RixShadingContext const*, RixBXLobeTraits const& hints,
393  RixSCShadingMode, void* parentData, void* instanceData) = 0;
394 
395  // usually called by RixBxdf::Release()
396  virtual void EndScatter(class RixBxdf* bxdf) = 0;
397 
427  virtual RixOpacity* BeginOpacity(RixShadingContext const*, RixSCShadingMode, void* parentData,
428  void* instanceData) = 0;
429 
430  virtual void EndOpacity(class RixOpacity*) = 0;
431 
462  void* parentData, void* instanceData) = 0;
463 
464  virtual void EndInterior(RixVolumeIntegrator*) = 0;
465 
495  void* parentData, void* instanceData) = 0;
496 
497  virtual void EndSubsurface(RixVolumeIntegrator*) = 0;
498 
501  virtual float GetIndexOfRefraction(void* instanceData) const = 0;
502 
505  void* parentData, void* instanceData)
506  {
507  PIXAR_ARGUSED(parentData);
508  PIXAR_ARGUSED(instanceData);
509 
510  return NULL;
511  }
512 
513  virtual void EndPostLighting(class RixPostLighting*)
514  {}
515 
516 protected:
518  {}
519  ~RixBxdfFactory() override
520  {}
521 };
522 
523 // RixBxdf holds all state computed by BeginScatter, including
524 // the RixShadingContext.
525 class RixBxdf
526 {
527 public:
528  RixBxdf(RixShadingContext const* sCtx, RixBxdfFactory* factory)
529  : shadingCtx(sCtx), bxdfFactory(factory)
530  {}
531 
532  virtual ~RixBxdf()
533  {}
534 
536  {
537  return shadingCtx;
538  }
540  {
541  return bxdfFactory;
542  }
543 
548 
550  virtual void GetAggregateLobeTraits(RixBXLobeTraits* t) = 0;
551 
553  {
554  RixBXLobeTraits t;
555  this->GetAggregateLobeTraits(&t);
556  return t;
557  }
558 
563  {
566  };
567 
578  virtual RixSCDetail GetProperty(BxdfProperty property, void const** result) const = 0;
579 
590  virtual bool EmitLocal(RtColorRGB* result) = 0;
591 
637  virtual void GenerateSample(RixBXTransportTrait transportTrait,
638  RixBXLobeTraits const* lobesWanted, RixRNG* rng,
639  // results:
640  RixBXLobeSampled* lobesSampled, RtVector3* directions,
641  RixBXLobeWeights& weights, float* forwardPdfs, float* reversePdfs,
642  RtColorRGB* compTrans = NULL) = 0;
643 
676  virtual void EvaluateSample(RixBXTransportTrait transportTrait,
677  RixBXLobeTraits const* lobesWanted, RixRNG* rng,
678  RixBXLobeTraits* lobesEvaluated, // a result
679  RtVector3 const* directions,
680  // more results:
681  RixBXLobeWeights& weights, float* forwardPdfs,
682  float* reversePdfs) = 0;
683 
697  virtual void EvaluateSamplesAtIndex(RixBXTransportTrait transportTrait,
698  RixBXLobeTraits const& lobesWanted, RixRNG* rng, int index,
699  int numSamples,
700  // results:
701  RixBXLobeTraits* lobesEvaluated,
702  RtVector3 const* directions, RixBXLobeWeights& weights,
703  float* forwardPdfs, float* reversePdfs) = 0;
704 
709  virtual void Release()
710  {
711  if (bxdfFactory) bxdfFactory->EndScatter(this);
712  }
713 
714 protected:
717 };
718 
742 {
743 public:
745  : shadingCtx(sCtx), bxdfFactory(factory)
746  {}
747  virtual ~RixOpacity()
748  {}
750  {
751  return bxdfFactory;
752  }
754  {
755  return shadingCtx;
756  }
757 
769  virtual bool GetPresence(float* result) = 0;
770 
781  virtual bool GetOpacity(RtColorRGB* result) = 0;
782 
783  virtual void Release()
784  {
785  if (bxdfFactory) bxdfFactory->EndOpacity(this);
786  }
787 
788 protected:
791 };
792 
818 {
819 public:
820  RixVolumeIntegrator(RixShadingContext const* sCtx, RixBxdfFactory* f, void* _instanceData)
821  : bxdfFactory(f),
822  instanceData(_instanceData),
823  params(NULL),
824  surfaceCtx(sCtx),
825  volumeCtx(NULL)
826  {}
828  {}
829 
838  {
839  return surfaceCtx;
840  }
841 
844  {
845  return volumeCtx;
846  }
847 
849  {
850  return bxdfFactory;
851  }
852 
871  {
872  bxdfFactory = factory;
873  }
874 
875  void* GetInstanceData() const
876  {
877  return instanceData;
878  }
879 
882  void SetInstanceData(void* data)
883  {
884  instanceData = data;
885  }
886 
887  virtual void SetParameters(void const* subclassParams)
888  {
889  params = subclassParams;
890  }
891 
893  {
894  public:
895  virtual void PerformDirectLighting(RixShadingContext const&,
896  RixBXLobeTraits const* lobesWanted, int step) = 0;
897 
898  protected:
900  {}
901  };
902 
903  virtual void Release()
904  {
905  if (bxdfFactory) bxdfFactory->EndInterior(this);
906  }
907 
911  {
924  };
931  virtual RixSCDetail GetProperty(VolumeProperty, void const** /* result */) const
932  {
933  // Note: currently we offer a default implementation. We may
934  // choose to enforce implementing this in the future so we
935  // encourage you to implement this method.
936  return k_RixSCInvalidDetail;
937  }
938 
958  {
959  const RixShadingContext* sCtx = GetShadingCtx();
960  RixShadingContext* newCtx = sCtx->BeginVolumeSampling();
961  volumeCtx = newCtx;
962  return volumeCtx;
963  }
964 
966  RixShadingContext const* EndVolumeSampling(RixBXLobeTraits const* exposeVol = NULL,
967  int const* membership = NULL)
968  {
969  const RixShadingContext* sCtx = GetShadingCtx();
970  const RixShadingContext* newCtx = sCtx->EndVolumeSampling(volumeCtx, exposeVol, membership);
971  volumeCtx = NULL;
972 
973  return newCtx;
974  }
975 
976  virtual void GetNearestHits(int numRays, RtRayGeometry const* rays, RixRNG* rng,
977  RixBXLobeTraits const& lobesWanted, RixIntegratorContext& iCtx,
978  RixLightingServices* lightingServices,
979  // results: (per-ray transmission deposited
980  // on resulting ShadingContexts'
981  // transmission field). Inscattered
982  // radiance can be splatted directly to
983  // the screen.
984  IntegratorDelegate* lcb, int* numShadingCtxs,
985  RixShadingContext const** shadingCtxs,
986  // optional inputs:
987  RtUString const subset = US_NULL,
988  RtUString const excludeSubset = US_NULL, bool isLightPath = false,
989  RtHitSides hitSides = k_SidesBoth, bool isPrimary = false) = 0;
990 
996  virtual void GetTransmission(int numRays, RtRayGeometry const* rays, RixRNG* rng,
997  RixIntegratorContext& iCtx, RtColorRGB* transmissions,
998  // optional output
999  RtColorRGB* emission,
1000  // optional input;
1001  RtUString const subset = US_NULL,
1002  RtUString const excludeSubset = US_NULL)
1003  {
1004  PIXAR_ARGUSED(rays);
1005  PIXAR_ARGUSED(rng);
1006  PIXAR_ARGUSED(iCtx);
1007  PIXAR_ARGUSED(emission);
1008  PIXAR_ARGUSED(subset);
1009  PIXAR_ARGUSED(excludeSubset);
1010  for (int i = 0; i < numRays; ++i)
1011  {
1012  transmissions[i] = RtColorRGB(0.0f);
1013  }
1014  }
1015 
1016 protected:
1019  void const* params;
1020 
1021 private:
1022  RixShadingContext const* surfaceCtx;
1023  RixShadingContext* volumeCtx;
1024 };
1025 
1028 {
1029 public:
1031  : shadingCtx(sCtx), bxdfFactory(factory)
1032  {}
1033 
1035  {}
1036 
1037  // Release does any cleanup that might be needed (often none and the
1038  // base implementation is fine) and then calls the base implementation.
1039  virtual void Release()
1040  {
1042  }
1043 
1044  virtual void Filter(int const numLightSamples, RtVector3 const* directions,
1045  float const* distances, const RixLight** lights,
1046  RixBXLobeWeights* bxdfWeights, RixBXLobeWeights* lightWeights,
1047  RtColorRGB* transmissions) = 0;
1048 
1049 protected:
1052 };
1053 
1054 // clang-format off
1055 #define RIX_BXDFPLUGINCREATE \
1056  extern "C" PRMANEXPORT RixBxdfFactory* CreateRixBxdfFactory(const char* hint)
1057 
1058 #define RIX_BXDFPLUGINDESTROY \
1059  extern "C" PRMANEXPORT void DestroyRixBxdfFactory(RixBxdfFactory* bxdf)
1060 // clang-format on
1061 
1062 #endif