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