RenderManAPI  24.0
RixPhotonGuiding.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 _RIX_PHOTON_GUIDING_H_
38 #define _RIX_PHOTON_GUIDING_H_
39 
40 #include <algorithm> // for max, min
41 #include <cassert> // for assert
42 #include <cstddef> // for NULL
43 #include "prmanapi.h" // for PRMAN_INLINE
44 #include "RiTypesHelper.h" // for RtPoint3, RtVector3, Dot, etc
45 
46 // The size of one side of the projection can only be <x> smaller than distance
47 // from a projection plane to a projection point
48 #define SAMPLING_STABILITY_FACTOR 1e-4f
49 
50 // Handles photon guiding
52 {
53 public:
54  // The parameter probability sets with what chance will be photon guiding
55  // used during photon emission.
56  PRMAN_INLINE RixPhotonGuiding(float probability);
57 
58  // Sets the bounding box towards which we will guide the photons.
59  // Enlarge controls whether we should enlarge the bounding box for
60  // more robustness (default is 10%).
62  const RtBBox& boundingBox,
63  float enlarge = 0.1f);
64 
65  PRMAN_INLINE const RtBBox& getBoundingBox() const;
66 
67  // Returns probability of choosing photon guiding
68  PRMAN_INLINE float samplingPdf() const;
69 
70  // Returns true if photon guiding is enabled
71  PRMAN_INLINE bool isEnabled() const;
72 
73  // Returns true if photon guiding was chosen
74  // according to given random sample. Random
75  // sample is also rescaled to [0,1].
76  PRMAN_INLINE bool pickPhotonGuiding(float& sample) const;
77 
78  // Given a position and a normal of a light patch,
79  // this methods determines whether it is possible to generate
80  // photons towards bounding box.
81  // onesided parameter must be set false if photons can be
82  // generated from both sides of the light patch.
84  const RtPoint3& origin,
85  const RtNormal3& normal,
86  bool onesided) const;
87 
88  // Tests ray origin only (no normal test) against bounding box,
89  // if it is inside it returns false.
90  PRMAN_INLINE bool canSample(const RtPoint3& origin) const;
91 
92  // Holds a bounding box projection on a plane
94  {
95  friend class RixPhotonGuiding;
96 
97  public:
98  // RixPhotonGuiding pointer may be NULL, but then we can not call
99  // computeProjection methods.
101  const RixPhotonGuiding* photonGuiding);
102 
103  // Creates a bounding box projection on a plane
104  // which lies in the middle between projectionPoint and the center
105  // of the bounding box. The plane normal vector is parallel
106  // to vector given by projection Point and the center of
107  // the bounding box.
108  // Presumes that the projectionPoint is outside the bounding box!
109  // Used for direction sampling
110  PRMAN_INLINE void computeProjection(const RtPoint3& projectionPoint);
111 
112  // Creates a bounding box projection on a given plane
113  // Used for position sampling
115  const RtPoint3& projectionPoint,
116  const RtPoint3& c,
117  const RtNormal3& n,
118  const RtVector3& s,
119  const RtVector3& t);
120 
121  PRMAN_INLINE float projectionArea() const;
122 
123  // Given two random samples,
124  // it generates a point on a plane within bounds
125  PRMAN_INLINE RtPoint3 generatePositionOnPlane(float sx, float sy) const;
126 
127  // Given cs,ct coordinates in s,t basis,
128  // it returns corresponding point in 3D
129  PRMAN_INLINE RtPoint3 getPositionOnPlane(float cs, float ct) const;
130 
131  // Given cs,ct coordinates in s,t basis,
132  // it returns true if they are within bounds of
133  // the bounding box projection.
134  PRMAN_INLINE bool isPositionOnPlane(float cs, float ct) const;
135  // private:
136 
137  // Increases sampling area if projection failed due to
138  // extreme size of either scene or light source
139  PRMAN_INLINE void stabilizeSampling(float min);
140 
141  // RixPhotonGuiding reference
143  // Projection point
145  // Orthonormal basis of the projection plane
149  // Center of the projection plane
151  // Precomputed factor needed for plane intersection tests
152  // (also used by other function (e.g. directionPdf)
153  float m_d;
154  // Projection min & max coordinates in s,t basis
155  // [minS, minT, maxS, maxT]
156  float m_stCoords[4];
157  // Projection size in s,t basis
158  float m_sizeS;
159  float m_sizeT;
160  };
161 
162  // Given ray origin (+normal) and a bounding box projection it can
163  // generate random direction towards the bounding box (using two random
164  // samples provided by caller). Returns generated direction, cosTheta, pdf.
165  // The returned pdf is wrt to solid angle measure.
166  // Will return correct results only if canSampleTowardsBBox is true.
168  const RtPoint3& origin,
169  const RtNormal3& normal,
170  const BoundingBoxProjection& bbp,
171  float samplex,
172  float sampley,
173  // output
174  RtVector3& direction,
175  float& cosTheta,
176  float& pdf) const;
177 
178  // Returns pdf of direction towards the bounding box given ray origin
179  // and a bounding box projection.
180  // The returned pdf is wrt to solid angle measure.
182  const RtPoint3& origin,
183  const BoundingBoxProjection& bbp,
184  const RtVector3& direction) const;
185 
186  // Given a bounding box projection it can
187  // generate a random position on a plane facing the bounding box
188  // (using two random samples provided by caller).
189  // Returns generated position and pdf. The returned pdf is wrt to
190  // area measure.
192  const BoundingBoxProjection& bbp,
193  float samplex,
194  float sampley,
195  // output
196  RtPoint3& position,
197  float& pdf) const;
198 
199  // Returns pdf of position on the projected bounding box
200  // given a position and bounding box projection.
201  // The returned pdf is wrt to area measure.
202  // Assumes that the position is on the projection plane.
204  const RtPoint3& position,
205  const BoundingBoxProjection& bbp) const;
206 
207  // Uses MIS to combine supplied direction pdf with photon guiding
208  // pdf. It also requires position on a light source, corresponding
209  // normal and direction. Paramater onesided indicates whether
210  // light emits photons from only one side.
212  const RtPoint3& position,
213  const RtNormal3& normal,
214  const RtVector3& direction,
215  bool onesided,
216  float dirPdf) const;
217 
218  // Uses MIS to combine supplied position pdf with photon guiding
219  // pdf. It also requires direction to env. map, position in scene
220  // (path vertex prior to env.map), world/env map center and world/
221  // env map radius.
223  const RtVector3& dirToEnv,
224  const RtPoint3& posInScene,
225  const RtPoint3& center,
226  float radius,
227  float posPdf) const;
228 
229  // Normalizes n and then computes rest of the orthonormal basis
231  RtVector3& n,
232  // output
233  RtVector3& s,
234  RtVector3& t);
235 
236 private:
237  // Inits internal variables (should be called after each bbox change)
238  PRMAN_INLINE void init(float enlarge);
239 
240  // Photons preferred area bbox
241  RtBBox m_boundingBox;
242  // Probability of sampling according to the bbox
243  float m_probability;
244  // True if bounding box has volume
245  bool m_hasVolume;
246  // Stores corners of bounding box
247  RtPoint3 m_corners[8];
248  // Center of bounding box
249  RtPoint3 m_center;
250 };
251 
252 // The probability parameter sets with what chance photon guiding will be
253 // used during photon emission.
256  : m_probability(probability)
257 {
258  assert(m_probability >= 0.0f && m_probability <= 1.0f);
259  m_boundingBox.min = RtPoint3(0.0f);
260  m_boundingBox.max = RtPoint3(0.0f);
261  init(false);
262 }
263 
264 // Sets the bounding box towards which we will guide the photons.
265 // Enlarge controls whether we should enlarge the bounding box for
266 // more robustness (default is 10%).
267 PRMAN_INLINE void
268 RixPhotonGuiding::setBoundingBox(const RtBBox& boundingBox, float enlarge)
269 {
270  m_boundingBox = boundingBox;
271  init(enlarge);
272 }
273 
274 PRMAN_INLINE const RtBBox&
276 {
277  return m_boundingBox;
278 }
279 
280 // Returns probability of choosing photon guiding
281 PRMAN_INLINE float
283 {
284  return m_probability;
285 }
286 
287 // Returns true if photon guiding is enabled
288 PRMAN_INLINE bool
290 {
291  return m_hasVolume && m_probability > 0.0f;
292 }
293 
294 // Returns true if photon guiding was chosen
295 // according to given random sample. Random
296 // sample is also rescaled to [0,1].
297 PRMAN_INLINE bool
299 {
300  if (sample < m_probability)
301  {
302  sample = sample / m_probability;
303  return true;
304  }
305  else
306  {
307  sample = (sample - m_probability) / (1.0f - m_probability);
308  return false;
309  }
310 }
311 
312 // Given a position and a normal of a light patch,
313 // this methods determines whether it is possible to generate
314 // photons towards bounding box.
315 // onesided parameter must be set false if photons can be
316 // generated from both sides of the light patch.
317 PRMAN_INLINE bool
319  const RtPoint3& origin,
320  const RtNormal3& normal,
321  bool onesided) const
322 {
323  return !(m_boundingBox.Contains(origin)) &&
324  (!onesided ||
325  !(Dot(normal, m_boundingBox.min - origin) < 0.0f &&
326  Dot(normal, m_boundingBox.max - origin) < 0.0f));
327 }
328 
329 // Tests ray origin only (no normal test) against bounding box,
330 // if it is inside it returns false.
331 PRMAN_INLINE bool
333 {
334  return !m_boundingBox.Contains(origin);
335 }
336 
337 // Given ray origin (+normal) and a bounding box projection it can
338 // generate random direction towards the bounding box (using two random
339 // samples provided by caller). Returns generated direction, cosTheta, pdf.
340 // The returned pdf is wrt to solid angle measure.
341 // Will return correct results only if canSampleTowardsBBox is true.
342 PRMAN_INLINE void
344  const RtPoint3& origin,
345  const RtNormal3& normal,
346  const BoundingBoxProjection& bbp,
347  float samplex,
348  float sampley,
349  // output
350  RtVector3& direction,
351  float& cosTheta,
352  float& pdf) const
353 {
354  // finally sample inside projection
355  RtPoint3 posOnPlane = bbp.generatePositionOnPlane(samplex, sampley);
356  // compute direction from origin towards the sample
357  direction = posOnPlane - origin;
358  // compute distance^2
359  float dist2 = Dot(direction, direction);
360  direction.Normalize();
361  cosTheta = AbsDot(direction, normal);
362  // as a last step we need to compute pdf and convert it
363  // to solid angle measure
364  // pdf = dist2 / ( bbp.projectionArea() * Dot(direction, bbp.m_n) );
365  pdf = dist2 / (bbp.projectionArea() * Dot(direction, bbp.m_n));
366 }
367 
368 // Returns pdf of direction towards the bounding box given ray origin
369 // and a bounding box projection.
370 // The returned pdf is wrt to solid angle measure.
371 PRMAN_INLINE float
373  const RtPoint3& origin,
374  const BoundingBoxProjection& bbp,
375  const RtVector3& direction) const
376 {
377  // compute ray intersection with plane
378  float nvInv = 1.0f / Dot(bbp.m_n, direction);
379  // to compute intersection of ray and plane we need this precomputation
380  float dno = bbp.m_d - Dot(bbp.m_n, origin);
381  // ray from c to projection on plane
382  RtVector3 hitRay = dno * nvInv * direction + origin - bbp.m_c;
383  float hitS = Dot(hitRay, bbp.m_s);
384  float hitT = Dot(hitRay, bbp.m_t);
385  // is hit in 2d bbox
386  if (bbp.isPositionOnPlane(hitS, hitT))
387  {
388  RtPoint3 posOnPlane = bbp.getPositionOnPlane(hitS, hitT);
389  RtVector3 d = posOnPlane - origin;
390  return Dot(d, d) / (bbp.projectionArea() * Dot(direction, bbp.m_n));
391  }
392  else
393  return 0.0f;
394 }
395 
396 // Given a bounding box projection it can
397 // generate a random position on a plane facing the bounding box
398 // (using two random samples provided by caller).
399 // Returns generated position and pdf. The returned pdf is wrt to
400 // area measure.
401 PRMAN_INLINE void
403  const BoundingBoxProjection& bbp,
404  float samplex,
405  float sampley,
406  // output
407  RtPoint3& position,
408  float& pdf) const
409 {
410  // sample inside projection
411  position = bbp.generatePositionOnPlane(samplex, sampley);
412  pdf = 1.0f / bbp.projectionArea();
413 }
414 
415 // Returns pdf of position on the projected bounding box
416 // given a position and bounding box projection.
417 // The returned pdf is wrt to area measure.
418 // Assumes that the position is on the projection plane.
419 PRMAN_INLINE float
421  const RtPoint3& position,
422  const BoundingBoxProjection& bbp) const
423 {
424  RtVector3 hitRay = position - bbp.m_c;
425  hitRay -= bbp.m_n * bbp.m_n.Dot(hitRay);
426 #ifndef NDEBUG
427  RtVector3 hrn = hitRay;
428  hrn.Normalize();
429  assert(AbsDot(hrn, bbp.m_n) < 0.001f);
430 #endif
431  float hitS = Dot(hitRay, bbp.m_s);
432  float hitT = Dot(hitRay, bbp.m_t);
433  // is hit in 2d bbox
434  if (bbp.isPositionOnPlane(hitS, hitT))
435  return 1.0f / bbp.projectionArea();
436  else
437  return 0.0f;
438 }
439 
440 // Uses MIS to combine supplied direction pdf with photon guiding
441 // pdf. It also requires position on a light source, corresponding
442 // normal and direction. Paramater onesided indicates whether
443 // light emits photons from only one side.
444 PRMAN_INLINE float
446  const RtPoint3& position,
447  const RtNormal3& normal,
448  const RtVector3& direction,
449  bool onesided,
450  float dirPdf) const
451 {
452  if (isEnabled() && canSample(position, normal, onesided))
453  {
454  BoundingBoxProjection bboxProjection(this);
455  bboxProjection.computeProjection(position);
456  float otherPdf = directionPdf(position, bboxProjection, direction);
457  // Use multiple importance sampling
458  return otherPdf * samplingPdf() + dirPdf * (1.0f - samplingPdf());
459  }
460  return dirPdf;
461 }
462 
463 // Uses MIS to combine supplied position pdf with photon guiding
464 // pdf. It also requires direction to env. map, position in scene
465 // (path vertex prior to env.map), world/env map center and world/
466 // env map radius.
467 PRMAN_INLINE float
469  const RtVector3& dirToEnv,
470  const RtPoint3& posInScene,
471  const RtPoint3& center,
472  float radius,
473  float posPdf) const
474 {
475  RtVector3 v = dirToEnv * radius;
476  RtPoint3 centerPoint = v + center;
477  if (isEnabled() && canSample(centerPoint))
478  {
479  RtVector3 projectionPoint = v * 2.0f + center; // (actually a point)
480  RtVector3 t, s;
481  computeOrthonormalBasis(v, s, t);
482  BoundingBoxProjection bbp(this);
483  bbp.computeProjection(projectionPoint, centerPoint, -v, s, t);
484  // Now we have to compute position on the projection plane
485  float dno = bbp.m_d - Dot(bbp.m_n, posInScene);
486  RtVector3 hit = -dno * v + posInScene;
487  float otherPdf = positionPdf(hit, bbp);
488  // Use multiple importance sampling
489  return otherPdf * samplingPdf() + posPdf * (1.0f - samplingPdf());
490  }
491  return posPdf;
492 }
493 
494 // Normalizes n and then computes rest of the orthonormal basis
495 PRMAN_INLINE void
497  RtVector3& n,
498  // output
499  RtVector3& s,
500  RtVector3& t)
501 {
502  Normalize(n);
503  const RtVector3 t1 = (n.x * n.x > n.y * n.y) ? RtVector3(0.0f, 1.0f, 0.0f)
504  : RtVector3(1.0f, 0.0f, 0.0f);
505  s = Cross(t1, n);
506  Normalize(s);
507  t = Cross(n, s);
508  Normalize(t);
509 }
510 
511 // Inits internal variables (should be called after each bbox change)
512 PRMAN_INLINE void
513 RixPhotonGuiding::init(float enlarge)
514 {
515  // Enlarge bounding box for more robust guiding (only for auto mode)
516  if (enlarge > 0.0f)
517  {
518  // Expands the bounding by 10% on both sides
519  RtVector3 expand = (m_boundingBox.max - m_boundingBox.min) * enlarge;
520  m_boundingBox.min -= expand;
521  m_boundingBox.min += expand;
522  }
523  // Precompute important bbox properties
524  // clang-format off
525  m_corners[0] = m_boundingBox.min;
526  m_corners[1] = m_boundingBox.max,
527  m_corners[2] = RtPoint3(m_boundingBox.min.x, m_boundingBox.min.y, m_boundingBox.max.z);
528  m_corners[3] = RtPoint3(m_boundingBox.min.x, m_boundingBox.max.y, m_boundingBox.min.z);
529  m_corners[4] = RtPoint3(m_boundingBox.max.x, m_boundingBox.min.y, m_boundingBox.min.z);
530  m_corners[5] = RtPoint3(m_boundingBox.min.x, m_boundingBox.max.y, m_boundingBox.max.z);
531  m_corners[6] = RtPoint3(m_boundingBox.max.x, m_boundingBox.min.y, m_boundingBox.max.z);
532  m_corners[7] = RtPoint3(m_boundingBox.max.x, m_boundingBox.max.y, m_boundingBox.min.z);
533  m_center = (m_boundingBox.max + m_boundingBox.min) * 0.5f;
534  m_hasVolume = m_boundingBox.Volume() > 0.0f;
535  // clang-format on
536 }
537 
538 // RixPhotonGuiding pointer may be NULL, but then we can not call
539 // computeProjection methods.
542  const RixPhotonGuiding* photonGuiding)
543  : m_photonGuiding(photonGuiding) // Maybe NULL
544 {
545 }
546 
547 // Creates a bounding box projection on a plane
548 // which lies in the middle between projectionPoint and the center
549 // of the bounding box. The plane normal vector is parallel
550 // to vector given by projection Point and the center of
551 // the bounding box.
552 // Presumes that the projectionPoint is outside the bounding box!
553 // Used for direction sampling from area light
554 PRMAN_INLINE void
556  const RtPoint3& projectionPoint)
557 {
558  assert(!m_photonGuiding->m_boundingBox.Contains(projectionPoint));
559  assert(m_photonGuiding != NULL);
560 
561  m_projectionPoint = projectionPoint;
562  // compute plane normal
563  m_n = m_photonGuiding->m_center - projectionPoint;
564  // center of the plane facing bbox
565  RtPoint3 cpp = m_n * 0.5f; // c - projectionPoint
566  m_c = cpp + projectionPoint;
567  // compute two vectors perpendicular to n (and normalize n)
568  computeOrthonormalBasis(m_n, m_s, m_t);
569 
570  // d from plane equation n . p = d
571  m_d = Dot(m_n, m_c);
572  // to compute intersection of corners and plane we need this
573  // precomputation
574  float dno = m_d - Dot(m_n, projectionPoint);
575  // 2d bbox init
576  m_stCoords[0] = m_stCoords[1] = FLT_MAX; // min
577  m_stCoords[2] = m_stCoords[3] = -FLT_MAX; // max
578  // project each corner of the bbox and update stCoords
579  for (int i = 0; i < 8; ++i)
580  {
581  RtVector3 v = m_photonGuiding->m_corners[i] - projectionPoint;
582  // can't be inf (projectionPoint is outside bbox)
583  float nvInv = 1.0f / Dot(m_n, v);
584  // ray from c to projection on plane
585  RtVector3 hitRay = dno * nvInv * v - cpp;
586  float hitS = Dot(hitRay, m_s);
587  float hitT = Dot(hitRay, m_t);
588  m_stCoords[0] = std::min(m_stCoords[0], hitS);
589  m_stCoords[1] = std::min(m_stCoords[1], hitT);
590  m_stCoords[2] = std::max(m_stCoords[2], hitS);
591  m_stCoords[3] = std::max(m_stCoords[3], hitT);
592  }
593  // Compute projection size
594  m_sizeS = m_stCoords[2] - m_stCoords[0];
595  m_sizeT = m_stCoords[3] - m_stCoords[1];
596  stabilizeSampling(
597  (m_c - projectionPoint).Length() * SAMPLING_STABILITY_FACTOR);
598 }
599 
600 // Creates a bounding box projection on a given plane.
601 // Used for position sampling for environment light
602 PRMAN_INLINE void
604  const RtPoint3& projectionPoint, // only used to stabilize
605  const RtPoint3& c,
606  const RtNormal3& n,
607  const RtVector3& s,
608  const RtVector3& t)
609 {
610  assert(m_photonGuiding != NULL);
611  assert(!m_photonGuiding->m_boundingBox.Contains(projectionPoint));
612 
613  m_projectionPoint = projectionPoint;
614  m_c = c;
615  m_n = n;
616  m_s = s;
617  m_t = t;
618  // d from plane equation n . p = d
619  m_d = Dot(m_n, m_c);
620  // to compute intersection of corners and plane we need this
621  // precomputation
622 
623  // 2d bbox init
624  m_stCoords[0] = m_stCoords[1] = FLT_MAX; // min
625  m_stCoords[2] = m_stCoords[3] = -FLT_MAX; // max
626  // project each corner of the bbox and update stCoords
627  for (int i = 0; i < 8; ++i)
628  {
629  RtPoint3 cornerpt = m_photonGuiding->m_corners[i];
630  float dist = Dot(m_n, (cornerpt - c));
631  RtVector3 hitRay = cornerpt - dist * m_n - c;
632  float hitS = Dot(hitRay, m_s);
633  float hitT = Dot(hitRay, m_t);
634  m_stCoords[0] = std::min(m_stCoords[0], hitS);
635  m_stCoords[1] = std::min(m_stCoords[1], hitT);
636  m_stCoords[2] = std::max(m_stCoords[2], hitS);
637  m_stCoords[3] = std::max(m_stCoords[3], hitT);
638  }
639  // Compute projection size
640  m_sizeS = m_stCoords[2] - m_stCoords[0];
641  m_sizeT = m_stCoords[3] - m_stCoords[1];
642  stabilizeSampling(
643  (m_c - projectionPoint).Length() * SAMPLING_STABILITY_FACTOR);
644 }
645 
646 PRMAN_INLINE float
648 {
649  return m_sizeS * m_sizeT;
650 }
651 
652 // Given two random samples,
653 // generate a point on a plane within bounds
656  float sx,
657  float sy) const
658 {
659  return m_c + (m_sizeS * sx + m_stCoords[0]) * m_s +
660  (m_sizeT * sy + m_stCoords[1]) * m_t;
661 }
662 
663 // Given cs,ct coordinates in s,t basis,
664 // return corresponding point in 3D
667  float cs,
668  float ct) const
669 {
670  return m_c + cs * m_s + ct * m_t;
671 }
672 
673 // Given cs,ct coordinates in s,t basis,
674 // return true if they are within bounds of
675 // the bounding box projection.
676 PRMAN_INLINE bool
678  float cs,
679  float ct) const
680 {
681  return (cs >= m_stCoords[0] && cs <= m_stCoords[2] &&
682  ct >= m_stCoords[1] && ct <= m_stCoords[3]);
683 }
684 
685 // Increases sampling area if projection failed due to
686 // extreme size of either scene or light source
687 PRMAN_INLINE void
689 {
690  if (m_sizeS < min)
691  {
692  float mid = 0.5f * (m_stCoords[2] + m_stCoords[0]);
693  m_sizeS = min;
694  m_stCoords[2] = mid + min * 0.5f;
695  m_stCoords[0] = mid - min * 0.5f;
696  }
697  if (m_sizeT < min)
698  {
699  float mid = 0.5f * (m_stCoords[3] + m_stCoords[1]);
700  m_sizeT = min;
701  m_stCoords[3] = mid + min * 0.5f;
702  m_stCoords[1] = mid - min * 0.5f;
703  }
704 }
705 
706 #endif // _RIX_PHOTON_GUIDING_H_
#define SAMPLING_STABILITY_FACTOR
Definition: RixPhotonGuiding.h:48
Definition: RixPhotonGuiding.h:51
PRMAN_INLINE bool pickPhotonGuiding(float &sample) const
Definition: RixPhotonGuiding.h:298
PRMAN_INLINE float samplingPdf() const
Definition: RixPhotonGuiding.h:282
PRMAN_INLINE bool isPositionOnPlane(float cs, float ct) const
Definition: RixPhotonGuiding.h:677
RtPoint3 m_projectionPoint
Definition: RixPhotonGuiding.h:144
PRMAN_INLINE float MISEnvLightPdf(const RtVector3 &dirToEnv, const RtPoint3 &posInScene, const RtPoint3 &center, float radius, float posPdf) const
Definition: RixPhotonGuiding.h:468
PRMAN_INLINE bool isEnabled() const
Definition: RixPhotonGuiding.h:289
RtFloat3 RtPoint3
Definition: RiTypesHelper.h:70
PRMAN_INLINE RtPoint3 getPositionOnPlane(float cs, float ct) const
Definition: RixPhotonGuiding.h:666
float m_sizeT
Definition: RixPhotonGuiding.h:159
PRMAN_INLINE bool canSample(const RtPoint3 &origin, const RtNormal3 &normal, bool onesided) const
Definition: RixPhotonGuiding.h:318
RtVector3 m_s
Definition: RixPhotonGuiding.h:147
RtPoint3 min
Definition: RiTypesHelper.h:330
float Volume() const
Definition: RiTypesHelper.h:365
bool Contains(const RtPoint3 &pt) const
Definition: RiTypesHelper.h:430
RtVector3 m_t
Definition: RixPhotonGuiding.h:148
PRMAN_INLINE void samplePosition(const BoundingBoxProjection &bbp, float samplex, float sampley, RtPoint3 &position, float &pdf) const
Definition: RixPhotonGuiding.h:402
float m_d
Definition: RixPhotonGuiding.h:153
RtPoint3 max
Definition: RiTypesHelper.h:330
Definition: RiTypesHelper.h:327
PRMAN_INLINE void sampleDirection(const RtPoint3 &origin, const RtNormal3 &normal, const BoundingBoxProjection &bbp, float samplex, float sampley, RtVector3 &direction, float &cosTheta, float &pdf) const
Definition: RixPhotonGuiding.h:343
const RixPhotonGuiding * m_photonGuiding
Definition: RixPhotonGuiding.h:142
static PRMAN_INLINE void computeOrthonormalBasis(RtVector3 &n, RtVector3 &s, RtVector3 &t)
Definition: RixPhotonGuiding.h:496
PRMAN_INLINE void computeProjection(const RtPoint3 &projectionPoint)
Definition: RixPhotonGuiding.h:555
RtPoint3 m_c
Definition: RixPhotonGuiding.h:150
PRMAN_INLINE const RtBBox & getBoundingBox() const
Definition: RixPhotonGuiding.h:275
PRMAN_INLINE RtPoint3 generatePositionOnPlane(float sx, float sy) const
Definition: RixPhotonGuiding.h:655
float m_sizeS
Definition: RixPhotonGuiding.h:158
RtFloat3 RtNormal3
Definition: RiTypesHelper.h:73
#define PRMAN_INLINE
Definition: prmanapi.h:99
PRMAN_INLINE void setBoundingBox(const RtBBox &boundingBox, float enlarge=0.1f)
Definition: RixPhotonGuiding.h:268
PRMAN_INLINE float MISAreaLightPdf(const RtPoint3 &position, const RtNormal3 &normal, const RtVector3 &direction, bool onesided, float dirPdf) const
Definition: RixPhotonGuiding.h:445
float m_stCoords[4]
Definition: RixPhotonGuiding.h:156
PRMAN_INLINE float directionPdf(const RtPoint3 &origin, const BoundingBoxProjection &bbp, const RtVector3 &direction) const
Definition: RixPhotonGuiding.h:372
PRMAN_INLINE RixPhotonGuiding(float probability)
Definition: RixPhotonGuiding.h:255
RtVector3 m_n
Definition: RixPhotonGuiding.h:146
PRMAN_INLINE float projectionArea() const
Definition: RixPhotonGuiding.h:647
Definition: RixPhotonGuiding.h:93
PRMAN_INLINE void stabilizeSampling(float min)
Definition: RixPhotonGuiding.h:688
RtFloat3 RtVector3
Definition: RiTypesHelper.h:72
PRMAN_INLINE float positionPdf(const RtPoint3 &position, const BoundingBoxProjection &bbp) const
Definition: RixPhotonGuiding.h:420
PRMAN_INLINE BoundingBoxProjection(const RixPhotonGuiding *photonGuiding)
Definition: RixPhotonGuiding.h:541