RenderMan  26.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
RixIntegrator.h
Go to the documentation of this file.
1 /*
2 # ------------------------------------------------------------------------------
3 #
4 # Copyright (c) 2023 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 RixIntegrator_h
38 #define RixIntegrator_h
39 
40 #include <math.h> // for sqrtf
41 #include <algorithm> // for max
42 #include <cassert> // for assert
43 #include <cstddef> // for size_t
44 #include "RixBxdfLobe.h" // for RixBXLobeSampled, etc
45 #include "RixInterfaces.h" // for RixContext
46 #include "RixShading.h" // for RixShadingContext, etc
47 #include "RixShadingUtils.h" // for RixIsFinite
48 #include "prmanapi.h" // for PRMANEXPORT, PRMAN_INLINE
49 #include "RiTypesHelper.h" // for RtNormal3, Dot, RtPoint3, etc
50 
51 class RixLPE;
52 class RixLPEState;
54 class RixRNG;
56 
57 typedef unsigned int RixChannelId;
58 static const RixChannelId k_InvalidChannelId = 2147483647;
59 
69 {
72  {
75  } style;
77  {
83  } type;
84  RtUString channel;
85 };
86 
98 {
99 public:
111  //
112  virtual bool Splat(RixChannelId id, int iCtxIndex, float const value) = 0;
114  virtual bool Splat(RixChannelId id, int iCtxIndex, RtColorRGB const value) = 0;
115 
127  virtual bool SplatMulti(
128  int nChans, RixChannelId const* ids, int iCtxIndex, float const value) = 0;
130  virtual bool SplatMulti(
131  int nChans, RixChannelId const* id, int iCtxIndex, RtColorRGB const value) = 0;
132 
146  virtual bool Write(RixChannelId id, int iCtxIndex, float const value) = 0;
148  virtual bool Write(RixChannelId id, int iCtxIndex, RtColorRGB const value) = 0;
150  virtual bool Write(RixChannelId id, int iCtxIndex, int const value) = 0;
151 
169  virtual void WriteDistance(
170  int const iCtxIndex,
171  float const distance,
172  bool const isVolume = true,
173  RixShadingContext const* sCtx = nullptr) = 0;
174 
182  virtual void WriteOpacity(RixChannelId id, int iCtxIndex, float const value) = 0;
183  virtual void WriteOpacity(RixChannelId id, int iCtxIndex, RtColorRGB& value) = 0;
184 
192  virtual void SplatOpacity(RixChannelId id, int iCtxIndex, float const opacity) = 0;
193  virtual void SplatOpacity(RixChannelId id, int iCtxIndex, RtColorRGB& opacity) = 0;
194 
208  virtual int AddSample(int iCtxIndex) = 0;
209 
219  virtual void GetDisplayChannels(int* numDisplays, RixDisplayChannel const** displays) = 0;
220 
228  virtual void DiscardIteration(bool redo = false) = 0;
229 
230 protected:
231  virtual ~RixDisplayServices() {}
232 
233 public:
249  virtual bool Read(RixChannelId id, int iCtxIndex, float& value) = 0;
251  virtual bool Read(RixChannelId id, int iCtxIndex, RtColorRGB& value) = 0;
253  virtual bool Read(RixChannelId id, int iCtxIndex, int& value) = 0;
254 };
255 
256 struct PRMAN_ALIGNED_16 RtRayGeometry
257 {
258  enum RayType
259  {
260  k_rtInvalid = 0,
261  k_rtCamera = 1, /* primary visibility ray from a camera */
262  k_rtLight = 2, /* photon ray directly from a light source */
263  k_rtTransmission = 3, /* shadow ray */
264  k_rtDirectlight = 4, /* directlighting ray */
265  k_rtIndirect = 5, /* indirect ray */
266  k_rtNumRayTypes = 6
267  };
268 
269  RtPoint3 origin;
270  float originRadius;
271  RtVector3 direction;
272 
273  float raySpread;
274  float minDist;
278  float maxDist;
279  float time;
280 
281  uint16_t raytype;
285  uint16_t shadingCtxIndex;
286  uint16_t rayId;
288 
290  uint32_t privateData[4];
292  mutable uint16_t hitId;
295  uint16_t flags;
296 
300  uint16_t wavelength;
301 
304 
317  void InitOrigination(RixShadingContext const* sCtx, RtNormal3 const* Ngn, int _shadingCtxIndex)
318  {
319  this->shadingCtxId = sCtx->shadingCtxId;
320  this->shadingCtxIndex = _shadingCtxIndex;
321  this->integratorCtxIndex = sCtx->integratorCtxIndex[_shadingCtxIndex];
322  if (this->lobeSampled.GetTransmit())
323  {
324  bool const entering = Dot(Ngn[_shadingCtxIndex], this->direction) <= 0.f;
325  this->lobeSampled.SetEntering(entering);
326  }
327  }
328 
337  void InitTransmitOrigination(RixShadingContext const* sCtx, int _shadingCtxIndex)
338  {
339  this->shadingCtxId = sCtx->shadingCtxId;
340  this->shadingCtxIndex = _shadingCtxIndex;
341  this->integratorCtxIndex = sCtx->integratorCtxIndex[_shadingCtxIndex];
342  this->lobeSampled.Set(
343  true, // discrete
344  false, // specular
345  false, // transmit, not reflect
346  false, // scattering
347  false, // not user
348  0, // lpeid
349  0 // lobeid (unused)
350  );
351  this->lobeSampled.SetEntering(true);
352  }
353 
379  RixBXLobeSampled lobe,
380  float rayOriginRadius,
381  float rayOriginSpread,
382  float curvature,
383  float fPdf,
384  bool lightPath = false)
385  {
386  float pdfSpread = 0.0f;
387  float newSpread;
388 
389  // Compute ray spread based on pdf (and hence surface roughness). If Dirac delta, don't use
390  // pdf -- it is 1.0 by convention.
391  if (!lightPath && lobe.GetSolidAngle() && fPdf > 0.0f)
392  {
393  // Inverse square root of pdf is a heuristic that seems to work.
394  assert(fPdf > 0.0f); // Avoid division by 0 (fPdf=inf is okay here).
395  pdfSpread = 0.125f / sqrtf(fPdf);
396  assert(RixIsFinite(pdfSpread));
397  }
398 
399  // Compute ray spread based on surface curvature.
400  if (lobe.GetReflect())
401  {
402  // Treat this as reflection:
403  // - `k_RixBXReflectSpecular`
404  // - `k_RixBXReflectGlossy`
405  // - `k_RixBXReflectDiffuse`
406 
407  // Spread for specular reflection: The new ray spread is the incident ray spread plus
408  // change induced by local curvature. The factor of 2 comes from differentiating the
409  // formula for mirror reflection direction -- see [Igehy99].
410  // Note that we clamp the spread so it doesn't become negative for highly negative
411  // curvature, for example a concave mirror.
412  float curvatureSpread = rayOriginSpread + 2.0f * curvature * rayOriginRadius;
413  newSpread = std::max(curvatureSpread, pdfSpread);
414  }
415  else if (lobe.GetTransmit())
416  {
417  // Treat this as refraction:
418  // - `k_RixBXTransmitSpecular`
419  // - `k_RixBXTransmitGlossy`
420 
421  // Spread for specular transmission -- simpler than [Igehy99] since we only need spread
422  // amount, not differential direction vector:
423  // - newSpread = eta * raySpread - (1.0f - eta) * curvature * rayOriginRadius;
424  //
425  // This can give negative spread and focusing of the ray, with the width of the ray
426  // increasing beyond the focus distance. This is all good and fine, but we skip this
427  // effect for now. For now: simply copy parent ray spread to avoid having to deal with
428  // ior vs. 1/ior
429  newSpread = std::max(rayOriginSpread, pdfSpread);
430 
431  // - `k_RixBXTransmitDiffuse`
432 
433  // Use very conservative spread for diffuse reflection and transmission: same as for
434  // specular/glossy reflection.
435  // (Could do better if we know PixelSamples and diffusemultfactor: compute ray solid
436  // angle = 2pi / (pixsam*diffmultfac)
437  }
438  else
439  {
440  // We have no idea what this ray is, let's use the provided ray spread.
441  newSpread = rayOriginSpread;
442  }
443 
444  // Disallow |newSpread| > 1 or newSpread == nan
445  if (!(newSpread <= 1.0f)) newSpread = 1.0f;
446  if (newSpread < -1.0f) newSpread = -1.0f;
447  assert(-1.0f <= newSpread && newSpread <= 1.0f);
448 
449  this->raySpread = newSpread;
450  }
451 
459  static PRMAN_INLINE uint16_t EncodeWavelength(float wavelength)
460  {
461  return wavelength != 0.0f ?
462  (int((wavelength - 380.0f) * (65534.0f / (780.0f - 380.0f)) + 0.5f) + 1) :
463  0;
464  }
465 
473  static PRMAN_INLINE float DecodeWavelength(uint16_t encodedWavelength)
474  {
475  return encodedWavelength != 0 ?
476  (float(encodedWavelength - 1) * ((780.0f - 380.0f) / 65534.0f) + 380.0f) :
477  0.0f;
478  }
479 };
480 
482 {
483  RtPoint3 P;
484  RtNormal3 Ng;
485  float dist;
486  RtPoint2 uv;
487  float filterSize;
488  float mpSize;
489  uint16_t groupingId;
490  uint16_t unused;
491 };
492 
497 {
498 public:
501  {
503  k_Fixed = 1,
506 
508  };
509 
512  {
515  };
516 
518  : m_version(2),
519  maxIntegrateSize(1024),
520  maxShadingCtxSize(1024),
523  numDisplays(0),
524  displays(0),
525  wantsEmptyIntegrate(false),
526  wantsIncrementBarrier(false),
528  numIncrements(0),
530  lobesWanted(k_RixBXTraitsAllLobe),
531  cameraMediumIOR(1.f),
533  wantsTransmission(false),
534  usesLightingServices(true),
538  {}
539 
549  PRMAN_INLINE RixDisplayChannel const* GetDisplayChannel(RtUString name) const
550  {
551  for (int i = 0; i < numDisplays; ++i)
552  if (displays[i].channel == name) return &displays[i];
553  return nullptr;
554  }
555 
558 
559  // Some of the following quantities can be modified by the integrator on the object provided to
560  // `RixIntegrator::RenderBegin()`.
561 
576 
578  int const numDisplays;
580 
589 
594  int const numIncrements;
595 
598 
611 
616  bool unused1;
617  bool unused2;
619 
622 
628 #ifdef PIXAR_ANIM
629  // The offset of `manifoldWalkMaxSamples` is at byte 64.
630  // Due to padding, excludeSubset's offset is at byte 72, and RtUString is 8 bytes long.
631  // The length of the `_reserved` array puts the size of the struct at 96.
632 #endif
633  char _reserved[15];
634 };
635 
636 namespace RixConstants
637 {
640  static const int k_MaxRaysPerBatch = 32768;
641 }
642 
644 {
645 public:
647  int numRays;
648  int numActiveRays;
658  float* time;
659 
660  virtual RixDisplayServices* GetDisplayServices(int version = 1) const = 0;
661  virtual RixLightingServices* GetLightingServices(int version = 1) const = 0;
662  virtual RixVolumeServices* GetVolumeServices(int version = 1) const = 0;
663  virtual RixRefCntPtr<RixLPE> GetRixLPE(int version = 1) const = 0;
664  virtual RixIntegratorEnvironment const& GetEnv(int version = 1) const = 0;
665 
667  {
668  k_None = 0,
669  k_Primary = 0x01,
670  k_IncludeMisses = 0x02,
671  k_ConstrainToVolume = 0x04,
672  k_ContinuationOpacity = 0x08,
673  k_SkipVolumes = 0x10,
674  k_Reserved1 = 0x20
675  };
676 
715  virtual void GetNearestHits(
716  int nRays,
717  RtRayGeometry const* rays,
719  RtRayGeometry::RayType rayType,
720  int nearestHitFlags,
721  RtUString const subset,
722  RtUString const excludeSubset,
723  RtHitSides hitSides,
724  int* numShadingCtxs,
725  RixShadingContext const** shadingCtxs) = 0;
726 
754  virtual void GetNearestHits(
755  int nRays,
756  RtRayGeometry const* rays,
757  RtRayGeometry::RayType rayType,
758  int nearestHitFlags,
759  RtUString const subset,
760  RtUString const excludeSubset,
761  RtHitSides hitSides,
762  RtHitPoint* hits) = 0;
763 
807  virtual void GetNearestHits(
808  int nRays,
809  RtRayGeometry const* rays,
811  bool wantsMisses,
812  int* numShadingCtxs,
813  RixShadingContext const** shadingCtxs,
814  // optional inputs:
815  RtUString const subset = US_NULL,
816  RtUString const excludeSubset = US_NULL,
817  bool isLightPath = false,
818  RtHitSides hitSides = k_SidesBoth,
819  bool isPrimary = false,
820  bool isVolume = false,
821  bool stochasticMode = true)
822  {
823  int nearestHitFlags =
824  (isPrimary ? k_Primary : k_None) |
825  (wantsMisses ? k_IncludeMisses : k_None) |
826  (isVolume ? k_ConstrainToVolume : k_None) |
827  (stochasticMode ? k_None : k_ContinuationOpacity);
828  RtRayGeometry::RayType raytype =
829  (isLightPath ? RtRayGeometry::k_rtLight :
831  GetNearestHits(nRays, rays, lobesWanted,
832  raytype, nearestHitFlags, subset, excludeSubset, hitSides, numShadingCtxs, shadingCtxs);
833  }
834 
841  virtual void GetNearestHits(
842  int nRays,
843  RtRayGeometry const* rays,
844  RtHitPoint* hits,
845  // optional inputs:
846  RtUString const subset = US_NULL,
847  RtUString const excludeSubset = US_NULL,
848  RtHitSides hitSides = k_SidesBoth,
849  bool isPrimary = false,
850  bool isVolume = false,
851  bool stochasticMode = true)
852  {
853  int nearestHitFlags =
854  (isPrimary ? k_Primary : k_None) |
855  (isVolume ? k_ConstrainToVolume : k_None) |
856  (stochasticMode ? k_None : k_ContinuationOpacity);
858  GetNearestHits(nRays, rays, raytype,
859  nearestHitFlags, subset, excludeSubset, hitSides, hits);
860  }
861 
893  virtual void GetTransmission(
894  int nRays,
895  RtRayGeometry const* rays,
896  RtColorRGB* transmissions,
897  RtColorRGB* volumeEmissions,
898  // optional input:
899  RtUString const subset = US_NULL,
900  RtUString const excludeSubset = US_NULL) = 0;
901 
910  virtual void ReleaseShadingContexts(
911  int numShadingCtxs, RixShadingContext const** shadingCtxs) = 0;
912 
919  {
920  k_IntegratorMem
921  };
922  virtual void* Allocate(size_t nObjs, size_t objSize, MemCategory) = 0;
923 
924  // contexts for ray misses
925  template <class T> T* Allocate(size_t nObjs)
926  {
927  T* mem = static_cast<T*>(Allocate(nObjs, sizeof(T), k_IntegratorMem));
928  return mem;
929  }
930 
931  template <class T> T* New(size_t nObjs)
932  {
933  T* mem = static_cast<T*>(Allocate(nObjs, sizeof(T), k_IntegratorMem));
934  return new (mem) T[nObjs];
935  }
936 
937 protected:
938  ~RixIntegratorContext() override {}
939 
940 public:
941 };
942 
944 {
945 public:
956  virtual void RenderBegin(
957  RixContext& rCtx,
958  RixIntegratorEnvironment& rixIntegratorEnv,
959  RixParameterList const* rixParameterList) = 0;
960  virtual void RenderEnd(RixContext& ctx) = 0;
961 
969  virtual void Synchronize(
970  RixContext& rCtx,
971  RixSCSyncMsg rixSCSyncMsg,
972  RixParameterList const* rixParameterList)
973  {
974  PIXAR_ARGUSED(rCtx);
975  PIXAR_ARGUSED(rixSCSyncMsg);
976  PIXAR_ARGUSED(rixParameterList);
977  }
978 
979 
997  virtual void IntegrateRays(
999  int* numShadingCtxs,
1000  RixShadingContext const** shadingCtxs,
1001  RixIntegratorContext& iCtx)
1002  {
1003  if (iCtx.numActiveRays)
1004  {
1005  iCtx.GetNearestHits(
1006  iCtx.numActiveRays,
1007  iCtx.primaryRays,
1008  lobesWanted,
1011  US_NULL, /*subset*/
1012  US_NULL, /*excludeSubset*/
1013  k_SidesFront,
1014  numShadingCtxs,
1015  shadingCtxs);
1016  RixDisplayServices* displayServices = iCtx.GetDisplayServices();
1017  for (int i = 0; i < *numShadingCtxs; ++i)
1018  {
1019  RixShadingContext const* sCtx = shadingCtxs[i];
1020  float const* VLen;
1022  for (int j = 0; j < sCtx->numPts; ++j)
1023  {
1024  int ctxIdx = sCtx->integratorCtxIndex[j];
1025  displayServices->WriteDistance(ctxIdx, VLen[j], false);
1026  }
1027  }
1028  Integrate(*numShadingCtxs, shadingCtxs, iCtx);
1029  }
1030  }
1031 
1046  virtual void Integrate(
1047  int numShadingCtxs, RixShadingContext const* shadingCtxs[], RixIntegratorContext& iCtx) = 0;
1048 
1062  virtual void GetTransmission(
1063  int nRays,
1064  RtRayGeometry const* rays,
1065  RtColorRGB* transmissions,
1066  RtColorRGB* volumeEmissions,
1067  RtUString const subset,
1068  RtUString const excludeSubset,
1069  RixLight const** lights,
1070  RixIntegratorContext& iCtx)
1071  {
1072  PIXAR_ARGUSED(nRays);
1073  PIXAR_ARGUSED(rays);
1074  PIXAR_ARGUSED(transmissions);
1075  PIXAR_ARGUSED(volumeEmissions);
1076  PIXAR_ARGUSED(subset);
1077  PIXAR_ARGUSED(excludeSubset);
1078  PIXAR_ARGUSED(lights);
1079  PIXAR_ARGUSED(iCtx);
1080  }
1081 
1101  virtual bool GetProperty(
1102  RixIntegratorContext& iCtx,
1103  const int* rayIds,
1104  int nRays,
1105  RayProperty rayProperty,
1106  void const* results)
1107  {
1108  PIXAR_ARGUSED(iCtx);
1109  PIXAR_ARGUSED(rayIds);
1110  PIXAR_ARGUSED(nRays);
1111  PIXAR_ARGUSED(rayProperty);
1112  PIXAR_ARGUSED(results);
1113 
1114  return false;
1115  }
1116 
1140  virtual bool SetProperty(
1141  RixIntegratorContext& iCtx,
1142  const int* rayIds,
1143  int nRays,
1144  RayProperty rayProperty,
1145  void const* values)
1146  {
1147  PIXAR_ARGUSED(iCtx);
1148  PIXAR_ARGUSED(rayIds);
1149  PIXAR_ARGUSED(nRays);
1150  PIXAR_ARGUSED(rayProperty);
1151  PIXAR_ARGUSED(values);
1152 
1153  return false;
1154  }
1155 
1156 protected:
1157  virtual ~RixIntegrator() {}
1158 };
1159 
1161 {
1162 public:
1163  int GetInterface() const override
1164  {
1165  return k_RixIntegratorFactory;
1166  }
1167 
1168  // Integrator plugins do not support InstanceData. As a consequence, the following methods are
1169  // not expected to be implemented and won't be called by the renderer.
1170  void CreateInstanceData(RixContext& rixCtx, RtUString const handle,
1171  RixParameterList const* instanceParams,
1172  InstanceData* instanceData) final
1173  {
1174  PIXAR_ARGUSED(rixCtx);
1175  PIXAR_ARGUSED(handle);
1176  PIXAR_ARGUSED(instanceParams);
1177  PIXAR_ARGUSED(instanceData);
1178  }
1179 
1180  void SynchronizeInstanceData(RixContext& rixCtx, RtUString const handle,
1181  RixParameterList const* instanceParams, uint32_t const editHints,
1182  InstanceData* instanceData) final
1183  {
1184  PIXAR_ARGUSED(rixCtx);
1185  PIXAR_ARGUSED(handle);
1186  PIXAR_ARGUSED(instanceParams);
1187  PIXAR_ARGUSED(editHints);
1188  PIXAR_ARGUSED(instanceData);
1189  }
1190 
1191  virtual RixIntegrator* CreateIntegrator(RixContext& rCtx, RtUString const handle,
1192  RixParameterList const* pList) = 0;
1193 
1194  virtual void DestroyIntegrator(RixIntegrator const* integrator) = 0;
1195 
1196 protected:
1198  {}
1200  {}
1201 };
1202 
1203 #define RIX_INTEGRATORFACTORYCREATE \
1204  extern "C" PRMANEXPORT RixIntegratorFactory* CreateRixIntegratorFactory(const char* hint)
1205 
1206 #define RIX_INTEGRATORFACTORYDESTROY \
1207  extern "C" PRMANEXPORT void DestroyRixIntegratorFactory(RixIntegratorFactory* factory)
1208 
1209 #endif