OpenVDB  2.3.0
RayTracer.h
Go to the documentation of this file.
1 //
3 // Copyright (c) 2012-2013 DreamWorks Animation LLC
4 //
5 // All rights reserved. This software is distributed under the
6 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
7 //
8 // Redistributions of source code must retain the above copyright
9 // and license notice and the following restrictions and disclaimer.
10 //
11 // * Neither the name of DreamWorks Animation nor the names of
12 // its contributors may be used to endorse or promote products derived
13 // from this software without specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY INDIRECT, INCIDENTAL,
20 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 // IN NO EVENT SHALL THE COPYRIGHT HOLDERS' AND CONTRIBUTORS' AGGREGATE
27 // LIABILITY FOR ALL CLAIMS REGARDLESS OF THEIR BASIS EXCEED US$250.00.
28 //
44 
45 #ifndef OPENVDB_TOOLS_RAYTRACER_HAS_BEEN_INCLUDED
46 #define OPENVDB_TOOLS_RAYTRACER_HAS_BEEN_INCLUDED
47 
48 #include <openvdb/Types.h>
49 #include <openvdb/math/BBox.h>
50 #include <openvdb/math/Ray.h>
51 #include <openvdb/math/Math.h>
52 #include <openvdb/tools/RayIntersector.h>
53 #include <openvdb/tools/Interpolation.h>
54 #include <boost/scoped_ptr.hpp>
55 #include <boost/scoped_array.hpp>
56 #include <vector>
57 
58 #ifdef OPENVDB_TOOLS_RAYTRACER_USE_EXR
59 #include <OpenEXR/ImfPixelType.h>
60 #include <OpenEXR/ImfChannelList.h>
61 #include <OpenEXR/ImfOutputFile.h>
62 #include <OpenEXR/ImfHeader.h>
63 #include <OpenEXR/ImfFrameBuffer.h>
64 #endif
65 
66 namespace openvdb {
68 namespace OPENVDB_VERSION_NAME {
69 namespace tools {
70 
71 // Forward declarations
72 class BaseCamera;
73 class BaseShader;
74 
76 template<typename GridT>
77 inline void rayTrace(const GridT&,
78  const BaseShader&,
79  BaseCamera&,
80  size_t pixelSamples = 1,
81  unsigned int seed = 0,
82  bool threaded = true);
83 
85 template<typename GridT, typename IntersectorT>
86 inline void rayTrace(const GridT&,
87  const IntersectorT&,
88  const BaseShader&,
89  BaseCamera&,
90  size_t pixelSamples = 1,
91  unsigned int seed = 0,
92  bool threaded = true);
93 
94 
96 
99 template<typename GridT, typename IntersectorT = tools::LevelSetRayIntersector<GridT> >
101 {
102 public:
103  typedef GridT GridType;
104  typedef typename IntersectorT::Vec3Type Vec3Type;
105  typedef typename IntersectorT::RayType RayType;
106 
108  LevelSetRayTracer(const GridT& grid,
109  const BaseShader& shader,
110  BaseCamera& camera,
111  size_t pixelSamples = 1,
112  unsigned int seed = 0);
113 
116  LevelSetRayTracer(const IntersectorT& inter,
117  const BaseShader& shader,
118  BaseCamera& camera,
119  size_t pixelSamples = 1,
120  unsigned int seed = 0);
121 
123  LevelSetRayTracer(const LevelSetRayTracer& other);
124 
127 
129  void setGrid(const GridT& grid);
130 
133  void setIntersector(const IntersectorT& inter);
134 
142  void setShader(const BaseShader& shader);
143 
145  void setCamera(BaseCamera& camera);
146 
151  void setPixelSamples(size_t pixelSamples, unsigned int seed = 0);
152 
154  void render(bool threaded = true) const;
155 
158  void operator()(const tbb::blocked_range<size_t>& range) const;
159 
160 private:
161  const bool mIsMaster;
162  double* mRand;
163  IntersectorT mInter;
164  boost::scoped_ptr<const BaseShader> mShader;
165  BaseCamera* mCamera;
166  size_t mSubPixels;
167 };// LevelSetRayTracer
168 
169 
171 
176 template <typename IntersectorT, typename SamplerT = tools::BoxSampler>
178 {
179 public:
180 
181  typedef typename IntersectorT::GridType GridType;
182  typedef typename IntersectorT::RayType RayType;
183  typedef typename GridType::ValueType ValueType;
184  typedef typename GridType::ConstAccessor AccessorType;
186  BOOST_STATIC_ASSERT(boost::is_floating_point<ValueType>::value);
187 
189  VolumeRender(const IntersectorT& inter, BaseCamera& camera);
190 
192  VolumeRender(const VolumeRender& other);
193 
195  void render(bool threaded=true) const;
196 
198  void setCamera(BaseCamera& camera) { mCamera = &camera; }
199 
202  void setIntersector(const IntersectorT& inter);
203 
206  void setLightDir(Real x, Real y, Real z) { mLightDir = Vec3R(x,y,z).unit(); }
207 
209  void setLightColor(Real r, Real g, Real b) { mLightColor = Vec3R(r,g,b); }
210 
212  void setPrimaryStep(Real primaryStep) { mPrimaryStep = primaryStep; }
213 
215  void setShadowStep(Real shadowStep) { mShadowStep = shadowStep; }
216 
218  void setScattering(Real x, Real y, Real z) { mScattering = Vec3R(x,y,z); }
219 
221  void setAbsorption(Real x, Real y, Real z) { mAbsorption = Vec3R(x,y,z); }
222 
225  void setLightGain(Real gain) { mLightGain = gain; }
226 
228  void setCutOff(Real cutOff) { mCutOff = cutOff; }
229 
234  void print(std::ostream& os = std::cout, int verboseLevel = 1);
235 
238  void operator()(const tbb::blocked_range<size_t>& range) const;
239 
240 private:
241 
242  AccessorType mAccessor;
243  BaseCamera* mCamera;
244  boost::scoped_ptr<IntersectorT> mPrimary, mShadow;
245  Real mPrimaryStep, mShadowStep, mCutOff, mLightGain;
246  Vec3R mLightDir, mLightColor, mAbsorption, mScattering;
247 };//VolumeRender
248 
250 
253 class Film
254 {
255 public:
258  struct RGBA
259  {
260  typedef float ValueT;
261 
262  RGBA() : r(0), g(0), b(0), a(1) {}
263  explicit RGBA(ValueT intensity) : r(intensity), g(intensity), b(intensity), a(1) {}
264  RGBA(ValueT _r, ValueT _g, ValueT _b, ValueT _a=1.0f) : r(_r), g(_g), b(_b), a(_a) {}
265 
266  RGBA operator* (ValueT scale) const { return RGBA(r*scale, g*scale, b*scale);}
267  RGBA operator+ (const RGBA& rhs) const { return RGBA(r+rhs.r, g+rhs.g, b+rhs.b);}
268  RGBA operator* (const RGBA& rhs) const { return RGBA(r*rhs.r, g*rhs.g, b*rhs.b);}
269  RGBA& operator+=(const RGBA& rhs) { r+=rhs.r; g+=rhs.g; b+=rhs.b, a+=rhs.a; return *this;}
270 
271  void over(const RGBA& rhs)
272  {
273  const float s = rhs.a*(1.0f-a);
274  r = a*r+s*rhs.r;
275  g = a*g+s*rhs.g;
276  b = a*b+s*rhs.b;
277  a = a + s;
278  }
279 
280  ValueT r, g, b, a;
281  };
282 
283 
284  Film(size_t width, size_t height)
285  : mWidth(width), mHeight(height), mSize(width*height), mPixels(new RGBA[mSize])
286  {
287  }
288  Film(size_t width, size_t height, const RGBA& bg)
289  : mWidth(width), mHeight(height), mSize(width*height), mPixels(new RGBA[mSize])
290  {
291  this->fill(bg);
292  }
293 
294  const RGBA& pixel(size_t w, size_t h) const
295  {
296  assert(w < mWidth);
297  assert(h < mHeight);
298  return mPixels[w + h*mWidth];
299  }
300 
301  RGBA& pixel(size_t w, size_t h)
302  {
303  assert(w < mWidth);
304  assert(h < mHeight);
305  return mPixels[w + h*mWidth];
306  }
307 
308  void fill(const RGBA& rgb=RGBA(0)) { for (size_t i=0; i<mSize; ++i) mPixels[i] = rgb; }
309  void checkerboard(const RGBA& c1=RGBA(0.3f), const RGBA& c2=RGBA(0.6f), size_t size=32)
310  {
311  RGBA *p = mPixels.get();
312  for (size_t j = 0; j < mHeight; ++j) {
313  for (size_t i = 0; i < mWidth; ++i, ++p) {
314  *p = ((i & size) ^ (j & size)) ? c1 : c2;
315  }
316  }
317  }
318 
319  void savePPM(const std::string& fileName)
320  {
321  std::string name(fileName + ".ppm");
322  boost::scoped_array<unsigned char> buffer(new unsigned char[3*mSize]);
323  unsigned char *tmp = buffer.get(), *q = tmp;
324  RGBA* p = mPixels.get();
325  size_t n = mSize;
326  while (n--) {
327  *q++ = static_cast<unsigned char>(255.0f*(*p ).r);
328  *q++ = static_cast<unsigned char>(255.0f*(*p ).g);
329  *q++ = static_cast<unsigned char>(255.0f*(*p++).b);
330  }
331 
332  std::ofstream os(name.c_str(), std::ios_base::binary);
333  if (!os.is_open()) {
334  std::cerr << "Error opening PPM file \"" << name << "\"" << std::endl;
335  return;
336  }
337 
338  os << "P6\n" << mWidth << " " << mHeight << "\n255\n";
339  os.write((const char *)&(*tmp), 3*mSize*sizeof(unsigned char));
340  }
341 
342 #ifdef OPENVDB_TOOLS_RAYTRACER_USE_EXR
343  void saveEXR(const std::string& fileName, size_t compression = 2, size_t threads = 8)
344  {
345  std::string name(fileName + ".exr");
346 
347  if (threads>0) Imf::setGlobalThreadCount(threads);
348  Imf::Header header(mWidth, mHeight);
349  if (compression==0) header.compression() = Imf::NO_COMPRESSION;
350  if (compression==1) header.compression() = Imf::RLE_COMPRESSION;
351  if (compression>=2) header.compression() = Imf::ZIP_COMPRESSION;
352  header.channels().insert("R", Imf::Channel(Imf::FLOAT));
353  header.channels().insert("G", Imf::Channel(Imf::FLOAT));
354  header.channels().insert("B", Imf::Channel(Imf::FLOAT));
355  header.channels().insert("A", Imf::Channel(Imf::FLOAT));
356 
357  Imf::FrameBuffer framebuffer;
358  framebuffer.insert("R", Imf::Slice( Imf::FLOAT, (char *) &(mPixels[0].r),
359  sizeof (RGBA), sizeof (RGBA) * mWidth));
360  framebuffer.insert("G", Imf::Slice( Imf::FLOAT, (char *) &(mPixels[0].g),
361  sizeof (RGBA), sizeof (RGBA) * mWidth));
362  framebuffer.insert("B", Imf::Slice( Imf::FLOAT, (char *) &(mPixels[0].b),
363  sizeof (RGBA), sizeof (RGBA) * mWidth));
364  framebuffer.insert("A", Imf::Slice( Imf::FLOAT, (char *) &(mPixels[0].a),
365  sizeof (RGBA), sizeof (RGBA) * mWidth));
366 
367  Imf::OutputFile file(name.c_str(), header);
368  file.setFrameBuffer(framebuffer);
369  file.writePixels(mHeight);
370  }
371 #endif
372 
373  size_t width() const { return mWidth; }
374  size_t height() const { return mHeight; }
375  size_t numPixels() const { return mSize; }
376  const RGBA* pixels() const { return mPixels.get(); }
377 
378 private:
379  size_t mWidth, mHeight, mSize;
380  boost::scoped_array<RGBA> mPixels;
381 };// Film
382 
383 
385 
388 {
389 public:
390  BaseCamera(Film& film, const Vec3R& rotation, const Vec3R& translation,
391  double frameWidth, double nearPlane, double farPlane)
392  : mFilm(&film)
393  , mScaleWidth(frameWidth)
394  , mScaleHeight(frameWidth*film.height()/double(film.width()))
395  {
396  assert(nearPlane > 0 && farPlane > nearPlane);
397  mScreenToWorld.accumPostRotation(math::X_AXIS, rotation[0] * M_PI / 180.0);
398  mScreenToWorld.accumPostRotation(math::Y_AXIS, rotation[1] * M_PI / 180.0);
399  mScreenToWorld.accumPostRotation(math::Z_AXIS, rotation[2] * M_PI / 180.0);
400  mScreenToWorld.accumPostTranslation(translation);
401  this->initRay(nearPlane, farPlane);
402  }
403 
404  virtual ~BaseCamera() {}
405 
406  Film::RGBA& pixel(size_t i, size_t j) { return mFilm->pixel(i, j); }
407 
408  size_t width() const { return mFilm->width(); }
409  size_t height() const { return mFilm->height(); }
410 
415  void lookAt(const Vec3R& xyz, const Vec3R& up = Vec3R(0.0, 1.0, 0.0))
416  {
417  const Vec3R orig = mScreenToWorld.applyMap(Vec3R(0.0));
418  const Vec3R dir = orig - xyz;
419  try {
420  Mat4d xform = math::aim<Mat4d>(dir, up);
421  xform.postTranslate(orig);
422  mScreenToWorld = math::AffineMap(xform);
423  this->initRay(mRay.t0(), mRay.t1());
424  } catch (...) {}
425  }
426 
427  Vec3R rasterToScreen(double i, double j, double z) const
428  {
429  return Vec3R( (2 * i / mFilm->width() - 1) * mScaleWidth,
430  (1 - 2 * j / mFilm->height()) * mScaleHeight, z );
431  }
432 
436  virtual math::Ray<double> getRay(
437  size_t i, size_t j, double iOffset = 0.5, double jOffset = 0.5) const = 0;
438 
439 protected:
440  void initRay(double t0, double t1)
441  {
442  mRay.setTimes(t0, t1);
443  mRay.setEye(mScreenToWorld.applyMap(Vec3R(0.0)));
444  mRay.setDir(mScreenToWorld.applyJacobian(Vec3R(0.0, 0.0, -1.0)));
445  }
446 
448  double mScaleWidth, mScaleHeight;
451 };// BaseCamera
452 
453 
455 {
456  public:
473  const Vec3R& rotation = Vec3R(0.0),
474  const Vec3R& translation = Vec3R(0.0),
475  double focalLength = 50.0,
476  double aperture = 41.2136,
477  double nearPlane = 1e-3,
478  double farPlane = std::numeric_limits<double>::max())
479  : BaseCamera(film, rotation, translation, 0.5*aperture/focalLength, nearPlane, farPlane)
480  {
481  }
482 
483  virtual ~PerspectiveCamera() {}
484 
489  size_t i, size_t j, double iOffset = 0.5, double jOffset = 0.5) const
490  {
491  math::Ray<double> ray(mRay);
492  Vec3R dir = BaseCamera::rasterToScreen(i + iOffset, j + jOffset, -1.0);
493  dir = BaseCamera::mScreenToWorld.applyJacobian(dir);
494  dir.normalize();
495  ray.scaleTimes(1.0/dir.dot(ray.dir()));
496  ray.setDir(dir);
497  return ray;
498  }
499 
502  static double focalLengthToFieldOfView(double length, double aperture)
503  {
504  return 360.0 / M_PI * atan(aperture/(2.0*length));
505  }
508  static double fieldOfViewToFocalLength(double fov, double aperture)
509  {
510  return aperture/(2.0*(tan(fov * M_PI / 360.0)));
511  }
512 };// PerspectiveCamera
513 
514 
516 {
517 public:
531  const Vec3R& rotation = Vec3R(0.0),
532  const Vec3R& translation = Vec3R(0.0),
533  double frameWidth = 1.0,
534  double nearPlane = 1e-3,
535  double farPlane = std::numeric_limits<double>::max())
536  : BaseCamera(film, rotation, translation, 0.5*frameWidth, nearPlane, farPlane)
537  {
538  }
539  virtual ~OrthographicCamera() {}
540 
542  size_t i, size_t j, double iOffset = 0.5, double jOffset = 0.5) const
543  {
544  math::Ray<double> ray(mRay);
545  Vec3R eye = BaseCamera::rasterToScreen(i + iOffset, j + jOffset, 0.0);
546  ray.setEye(BaseCamera::mScreenToWorld.applyMap(eye));
547  return ray;
548  }
549 };// OrthographicCamera
550 
551 
553 
554 
557 {
558 public:
561  virtual ~BaseShader() {}
566  virtual Film::RGBA operator()(const Vec3R& xyz, const Vec3R& nml, const Vec3R& dir) const = 0;
567  virtual BaseShader* copy() const = 0;
568 };
569 
570 
572 class MatteShader: public BaseShader
573 {
574 public:
575  MatteShader(const Film::RGBA& c = Film::RGBA(1.0f)): mRGBA(c) {}
576  virtual ~MatteShader() {}
577  virtual Film::RGBA operator()(const Vec3R&, const Vec3R&, const Vec3R&) const
578  {
579  return mRGBA;
580  }
581  virtual BaseShader* copy() const { return new MatteShader(*this); }
582 
583 private:
584  const Film::RGBA mRGBA;
585 };
586 
587 
590 {
591 public:
592  NormalShader(const Film::RGBA& c = Film::RGBA(1.0f)) : mRGBA(c*0.5f) {}
593  virtual ~NormalShader() {}
594  virtual Film::RGBA operator()(const Vec3R&, const Vec3R& normal, const Vec3R&) const
595  {
596  return mRGBA*Film::RGBA(normal[0]+1.0f, normal[1]+1.0f, normal[2]+1.0f);
597  }
598  virtual BaseShader* copy() const { return new NormalShader(*this); }
599 
600 private:
601  const Film::RGBA mRGBA;
602 };
603 
604 
608 {
609 public:
610  PositionShader(const math::BBox<Vec3R>& bbox, const Film::RGBA& c = Film::RGBA(1.0f))
611  : mMin(bbox.min()), mInvDim(1.0/bbox.extents()), mRGBA(c) {}
612  virtual ~PositionShader() {}
613  virtual Film::RGBA operator()(const Vec3R& xyz, const Vec3R&, const Vec3R&) const
614  {
615  const Vec3R rgb = (xyz - mMin)*mInvDim;
616  return mRGBA*Film::RGBA(rgb[0], rgb[1], rgb[2]);
617  }
618  virtual BaseShader* copy() const { return new PositionShader(*this); }
619 
620  private:
621  const Vec3R mMin, mInvDim;
622  const Film::RGBA mRGBA;
623 };
624 
631 {
632 public:
633  DiffuseShader(const Film::RGBA& d = Film::RGBA(1.0f)): mRGBA(d) {}
634  virtual Film::RGBA operator()(const Vec3R&, const Vec3R& normal, const Vec3R& rayDir) const
635  {
636  // We assume a single directional light source at the camera,
637  // so the cosine of the angle between the surface normal and the
638  // direction of the light source becomes the dot product of the
639  // surface normal and inverse direction of the ray. We also ignore
640  // negative dot products, corresponding to strict one-sided shading.
641  //return mRGBA * math::Max(0.0, normal.dot(-rayDir));
642 
643  // We take the abs of the dot product corresponding to having
644  // light sources at +/- rayDir, i.e., two-sided shading.
645  return mRGBA * math::Abs(normal.dot(rayDir));
646  }
647  virtual BaseShader* copy() const { return new DiffuseShader(*this); }
648 
649 private:
650  const Film::RGBA mRGBA;
651 };
652 
653 
655 
656 template<typename GridT>
657 inline void rayTrace(const GridT& grid,
658  const BaseShader& shader,
659  BaseCamera& camera,
660  size_t pixelSamples,
661  unsigned int seed,
662  bool threaded)
663 {
665  tracer(grid, shader, camera, pixelSamples, seed);
666  tracer.render(threaded);
667 }
668 
669 
670 template<typename GridT, typename IntersectorT>
671 inline void rayTrace(const GridT&,
672  const IntersectorT& inter,
673  const BaseShader& shader,
674  BaseCamera& camera,
675  size_t pixelSamples,
676  unsigned int seed,
677  bool threaded)
678 {
679  LevelSetRayTracer<GridT, IntersectorT> tracer(inter, shader, camera, pixelSamples, seed);
680  tracer.render(threaded);
681 }
682 
683 
685 
686 
687 template<typename GridT, typename IntersectorT>
688 inline LevelSetRayTracer<GridT, IntersectorT>::
689 LevelSetRayTracer(const GridT& grid,
690  const BaseShader& shader,
691  BaseCamera& camera,
692  size_t pixelSamples,
693  unsigned int seed)
694  : mIsMaster(true),
695  mRand(NULL),
696  mInter(grid),
697  mShader(shader.copy()),
698  mCamera(&camera)
699 {
700  this->setPixelSamples(pixelSamples, seed);
701 }
702 
703 template<typename GridT, typename IntersectorT>
705 LevelSetRayTracer(const IntersectorT& inter,
706  const BaseShader& shader,
707  BaseCamera& camera,
708  size_t pixelSamples,
709  unsigned int seed)
710  : mIsMaster(true),
711  mRand(NULL),
712  mInter(inter),
713  mShader(shader.copy()),
714  mCamera(&camera)
715 {
716  this->setPixelSamples(pixelSamples, seed);
717 }
718 
719 template<typename GridT, typename IntersectorT>
722  mIsMaster(false),
723  mRand(other.mRand),
724  mInter(other.mInter),
725  mShader(other.mShader->copy()),
726  mCamera(other.mCamera),
727  mSubPixels(other.mSubPixels)
728 {
729 }
730 
731 template<typename GridT, typename IntersectorT>
734 {
735  if (mIsMaster) delete [] mRand;
736 }
737 
738 template<typename GridT, typename IntersectorT>
740 setGrid(const GridT& grid)
741 {
742  assert(mIsMaster);
743  mInter = IntersectorT(grid);
744 }
745 
746 template<typename GridT, typename IntersectorT>
748 setIntersector(const IntersectorT& inter)
749 {
750  assert(mIsMaster);
751  mInter = inter;
752 }
753 
754 template<typename GridT, typename IntersectorT>
756 setShader(const BaseShader& shader)
757 {
758  assert(mIsMaster);
759  mShader.reset(shader.copy());
760 }
761 
762 template<typename GridT, typename IntersectorT>
765 {
766  assert(mIsMaster);
767  mCamera = &camera;
768 }
769 
770 template<typename GridT, typename IntersectorT>
772 setPixelSamples(size_t pixelSamples, unsigned int seed)
773 {
774  assert(mIsMaster);
775  if (pixelSamples == 0) {
776  OPENVDB_THROW(ValueError, "pixelSamples must be larger then zero!");
777  }
778  mSubPixels = pixelSamples - 1;
779  delete [] mRand;
780  if (mSubPixels > 0) {
781  mRand = new double[16];
782  math::Rand01<double> rand(seed);//offsets for anti-aliaing by jittered super-sampling
783  for (size_t i=0; i<16; ++i) mRand[i] = rand();
784  } else {
785  mRand = NULL;
786  }
787 }
788 
789 template<typename GridT, typename IntersectorT>
791 render(bool threaded) const
792 {
793  tbb::blocked_range<size_t> range(0, mCamera->height());
794  threaded ? tbb::parallel_for(range, *this) : (*this)(range);
795 }
796 
797 template<typename GridT, typename IntersectorT>
799 operator()(const tbb::blocked_range<size_t>& range) const
800 {
801  const BaseShader& shader = *mShader;
802  Vec3Type xyz, nml;
803  const float frac = 1.0f / (1.0f + mSubPixels);
804  for (size_t j=range.begin(), n=0, je = range.end(); j<je; ++j) {
805  for (size_t i=0, ie = mCamera->width(); i<ie; ++i) {
806  Film::RGBA& bg = mCamera->pixel(i,j);
807  RayType ray = mCamera->getRay(i, j);//primary ray
808  Film::RGBA c = mInter.intersectsWS(ray, xyz, nml) ? shader(xyz, nml, ray.dir()) : bg;
809  for (size_t k=0; k<mSubPixels; ++k, n +=2 ) {
810  ray = mCamera->getRay(i, j, mRand[n & 15], mRand[(n+1) & 15]);
811  c += mInter.intersectsWS(ray, xyz, nml) ? shader(xyz, nml, ray.dir()) : bg;
812  }//loop over sub-pixels
813  bg = c*frac;
814  }//loop over image height
815  }//loop over image width
816 }
817 
819 
820 template<typename IntersectorT, typename SampleT>
822 VolumeRender(const IntersectorT& inter, BaseCamera& camera)
823  : mAccessor(inter.grid().getConstAccessor())
824  , mCamera(&camera)
825  , mPrimary(new IntersectorT(inter))
826  , mShadow(new IntersectorT(inter))
827  , mPrimaryStep(1.0)
828  , mShadowStep(3.0)
829  , mCutOff(0.005)
830  , mLightGain(0.2)
831  , mLightDir(Vec3R(0.3, 0.3, 0).unit())
832  , mLightColor(0.7, 0.7, 0.7)
833  , mAbsorption(0.1)
834  , mScattering(1.5)
835 {
836 }
837 
838 template<typename IntersectorT, typename SampleT>
841  : mAccessor(other.mAccessor)
842  , mCamera(other.mCamera)
843  , mPrimary(new IntersectorT(*(other.mPrimary)))
844  , mShadow(new IntersectorT(*(other.mShadow)))
845  , mPrimaryStep(other.mPrimaryStep)
846  , mShadowStep(other.mShadowStep)
847  , mCutOff(other.mCutOff)
848  , mLightGain(other.mLightGain)
849  , mLightDir(other.mLightDir)
850  , mLightColor(other.mLightColor)
851  , mAbsorption(other.mAbsorption)
852  , mScattering(other.mScattering)
853 {
854 }
855 
856 template<typename IntersectorT, typename SampleT>
858 print(std::ostream& os, int verboseLevel)
859 {
860  if (verboseLevel>0) {
861  os << "\nPrimary step: " << mPrimaryStep
862  << "\nShadow step: " << mShadowStep
863  << "\nCutoff: " << mCutOff
864  << "\nLightGain: " << mLightGain
865  << "\nLightDir: " << mLightDir
866  << "\nLightColor: " << mLightColor
867  << "\nAbsorption: " << mAbsorption
868  << "\nScattering: " << mScattering << std::endl;
869  }
870  mPrimary->print(os, verboseLevel);
871 }
872 
873 template<typename IntersectorT, typename SampleT>
875 setIntersector(const IntersectorT& inter)
876 {
877  mPrimary.reset(new IntersectorT(inter));
878  mShadow.reset( new IntersectorT(inter));
879 }
880 
881 template<typename IntersectorT, typename SampleT>
883 render(bool threaded) const
884 {
885  tbb::blocked_range<size_t> range(0, mCamera->height());
886  threaded ? tbb::parallel_for(range, *this) : (*this)(range);
887 }
888 
889 template<typename IntersectorT, typename SampleT>
891 operator()(const tbb::blocked_range<size_t>& range) const
892 {
893  SamplerType sampler(mAccessor, mShadow->grid().transform());//light-weight wrapper
894 
895  // Any variable prefixed with p (or s) means it's associate with a primay (or shadow) ray
896  const Vec3R extinction = -mScattering-mAbsorption, One(1.0);
897  const Vec3R albedo = mLightColor*mScattering/(mScattering+mAbsorption);//single scattering
898  const Real sGain = mLightGain;//in-scattering along shadow ray
899  const Real pStep = mPrimaryStep;//Integration step along primary ray in voxel units
900  const Real sStep = mShadowStep;//Integration step along shadow ray in voxel units
901  const Real cutoff = mCutOff;//Cutoff for density and transmittance
902 
903  // For the sake of completeness we show how to use two different
904  // methods (hits/march) in VolumeRayIntersector that produce
905  // segments along the ray that intersects active values. Comment out
906  // the line below to use VolumeRayIntersector::march instead of
907  // VolumeRayIntersector::hits.
908 #define USE_HITS
909 #ifdef USE_HITS
910  std::vector<typename RayType::TimeSpan> pTS, sTS;
911 #endif
912 
913  RayType sRay(Vec3R(0), mLightDir);//Shadow ray
914  for (size_t j=range.begin(), je = range.end(); j<je; ++j) {
915  for (size_t i=0, ie = mCamera->width(); i<ie; ++i) {
916  Film::RGBA& bg = mCamera->pixel(i, j);
917  bg.a = bg.r = bg.g = bg.b = 0;
918  RayType pRay = mCamera->getRay(i, j);// Primary ray
919  if( !mPrimary->setWorldRay(pRay)) continue;
920  Vec3R pTrans(1.0), pLumi(0.0);
921 #ifndef USE_HITS
922  Real pT0, pT1;
923  while (mPrimary->march(pT0, pT1)) {
924  for (Real pT = pStep*ceil(pT0/pStep); pT <= pT1; pT += pStep) {
925 #else
926  mPrimary->hits(pTS);
927  for (size_t k=0; k<pTS.size(); ++k) {
928  Real pT = pStep*ceil(pTS[k].t0/pStep), pT1=pTS[k].t1;
929  for (; pT <= pT1; pT += pStep) {
930 #endif
931  Vec3R pPos = mPrimary->getWorldPos(pT);
932  const Real density = sampler.wsSample(pPos);
933  if (density < cutoff) continue;
934  const Vec3R dT = math::Exp(extinction * density * pStep);
935  Vec3R sTrans(1.0);
936  sRay.setEye(pPos);
937  if( !mShadow->setWorldRay(sRay)) continue;
938 #ifndef USE_HITS
939  Real sT0, sT1;
940  while (mShadow->march(sT0, sT1)) {
941  for (Real sT = sStep*ceil(sT0/sStep); sT <= sT1; sT+= sStep) {
942 #else
943  mShadow->hits(sTS);
944  for (size_t l=0; l<sTS.size(); ++l) {
945  Real sT = sStep*ceil(sTS[l].t0/sStep), sT1=sTS[l].t1;
946  for (; sT <= sT1; sT+= sStep) {
947 #endif
948  const Real d = sampler.wsSample(mShadow->getWorldPos(sT));
949  if (d < cutoff) continue;
950  sTrans *= math::Exp(extinction * d * sStep/(1.0+sT*sGain));
951  if (sTrans.lengthSqr()<cutoff) goto Luminance;//Terminate sRay
952  }//Integration over shadow segment
953  }// Shadow ray march
954  Luminance:
955  pLumi += albedo * sTrans * pTrans * (One-dT);
956  pTrans *= dT;
957  if (pTrans.lengthSqr()<cutoff) goto Pixel; // Terminate Ray
958  }//Integration over primary segment
959  }// Primary ray march
960  Pixel:
961  bg.r = pLumi[0];
962  bg.g = pLumi[1];
963  bg.b = pLumi[2];
964  bg.a = 1.0f - pTrans.sum()/3.0f;
965  }//Horizontal pixel scan
966  }//Vertical pixel scan
967 }
968 
969 } // namespace tools
970 } // namespace OPENVDB_VERSION_NAME
971 } // namespace openvdb
972 
973 #endif // OPENVDB_TOOLS_RAYTRACER_HAS_BEEN_INCLUDED
974 
975 // Copyright (c) 2012-2013 DreamWorks Animation LLC
976 // All rights reserved. This software is distributed under the
977 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
OPENVDB_API Hermite min(const Hermite &, const Hermite &)
min and max operations done directly on the compressed data.
virtual Film::RGBA operator()(const Vec3R &, const Vec3R &normal, const Vec3R &rayDir) const
Defines the interface of the virtual function that returns a RGB color.
Definition: RayTracer.h:634
MatteShader(const Film::RGBA &c=Film::RGBA(1.0f))
Definition: RayTracer.h:575
Type Exp(const Type &x)
Return .
Definition: Math.h:620
math::Vec3< Real > Vec3R
Definition: Types.h:75
void initRay(double t0, double t1)
Definition: RayTracer.h:440
IntersectorT::Vec3Type Vec3Type
Definition: RayTracer.h:104
void setCamera(BaseCamera &camera)
Set the camera derived from the abstract BaseCamera class.
Definition: RayTracer.h:764
A simple class that allows for concurrent writes to pixels in an image, background initialization of ...
Definition: RayTracer.h:253
Film(size_t width, size_t height, const RGBA &bg)
Definition: RayTracer.h:288
void over(const RGBA &rhs)
Definition: RayTracer.h:271
RGBA(ValueT intensity)
Definition: RayTracer.h:263
virtual BaseShader * copy() const
Definition: RayTracer.h:618
ValueT a
Definition: RayTracer.h:280
float ValueT
Definition: RayTracer.h:260
Abstract base class for the shaders.
Definition: RayTracer.h:556
GridType::ValueType ValueType
Definition: RayTracer.h:183
void render(bool threaded=true) const
Perform the actual (potentially multithreaded) ray-tracing.
Definition: RayTracer.h:791
RGBA()
Definition: RayTracer.h:262
size_t width() const
Definition: RayTracer.h:373
virtual ~PositionShader()
Definition: RayTracer.h:612
Abstract base class for the perspective and orthographic cameras.
Definition: RayTracer.h:387
ValueT g
Definition: RayTracer.h:280
Color shader that treats the surface normal (x, y, z) as an RGB color.
Definition: RayTracer.h:589
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:97
bool normalize(T eps=T(1.0e-7))
this = normalized this
Definition: Vec3.h:344
void setLightDir(Real x, Real y, Real z)
Set the vector components of a directional light source.
Definition: RayTracer.h:206
void setGrid(const GridT &grid)
Set the level set grid to be ray-traced.
Definition: RayTracer.h:740
const Vec3T & dir() const
Definition: Ray.h:121
Floating-point RGBA components in the range [0, 1].
Definition: RayTracer.h:258
void setEye(const Vec3Type &eye)
Definition: Ray.h:88
int32_t Abs(int32_t i)
Return the absolute value of the given quantity.
Definition: Math.h:244
BaseCamera(Film &film, const Vec3R &rotation, const Vec3R &translation, double frameWidth, double nearPlane, double farPlane)
Definition: RayTracer.h:390
Definition: Math.h:769
A (very) simple multithreaded ray tracer specifically for narrow-band level sets. ...
Definition: RayTracer.h:100
Vec3R rasterToScreen(double i, double j, double z) const
Definition: RayTracer.h:427
T lengthSqr() const
Definition: Vec3.h:219
virtual math::Ray< double > getRay(size_t i, size_t j, double iOffset=0.5, double jOffset=0.5) const
Return a Ray in world space given the pixel indices and optional offsets in the range [0...
Definition: RayTracer.h:541
size_t height() const
Definition: RayTracer.h:409
Film(size_t width, size_t height)
Definition: RayTracer.h:284
Definition: Exceptions.h:88
Film::RGBA & pixel(size_t i, size_t j)
Definition: RayTracer.h:406
virtual BaseShader * copy() const
Definition: RayTracer.h:598
Definition: Math.h:768
void setLightGain(Real gain)
Set parameter that imitates multi-scattering. A value of zero implies no multi-scattering.
Definition: RayTracer.h:225
size_t width() const
Definition: RayTracer.h:408
void operator()(const tbb::blocked_range< size_t > &range) const
Public method required by tbb::parallel_for.
Definition: RayTracer.h:891
void print(std::ostream &os=std::cout, int verboseLevel=1)
Print parameters, statistics, memory usage and other information.
Definition: RayTracer.h:858
void lookAt(const Vec3R &xyz, const Vec3R &up=Vec3R(0.0, 1.0, 0.0))
Definition: RayTracer.h:415
NormalShader(const Film::RGBA &c=Film::RGBA(1.0f))
Definition: RayTracer.h:592
size_t numPixels() const
Definition: RayTracer.h:375
void savePPM(const std::string &fileName)
Definition: RayTracer.h:319
void scaleTimes(RealT scale)
Definition: Ray.h:107
ValueT r
Definition: RayTracer.h:280
BaseShader()
Definition: RayTracer.h:560
GridType::ConstAccessor AccessorType
Definition: RayTracer.h:184
#define OPENVDB_VERSION_NAME
Definition: version.h:45
math::AffineMap mScreenToWorld
Definition: RayTracer.h:450
MatType rotation(const Quat< typename MatType::value_type > &q, typename MatType::value_type eps=1.0e-8)
Return the rotation matrix specified by the given quaternion.
Definition: Mat.h:153
T dot(const Vec3< T > &v) const
Dot product.
Definition: Vec3.h:199
OrthographicCamera(Film &film, const Vec3R &rotation=Vec3R(0.0), const Vec3R &translation=Vec3R(0.0), double frameWidth=1.0, double nearPlane=1e-3, double farPlane=std::numeric_limits< double >::max())
Constructor.
Definition: RayTracer.h:530
OPENVDB_API Hermite max(const Hermite &, const Hermite &)
min and max operations done directly on the compressed data.
virtual ~OrthographicCamera()
Definition: RayTracer.h:539
PerspectiveCamera(Film &film, const Vec3R &rotation=Vec3R(0.0), const Vec3R &translation=Vec3R(0.0), double focalLength=50.0, double aperture=41.2136, double nearPlane=1e-3, double farPlane=std::numeric_limits< double >::max())
Constructor.
Definition: RayTracer.h:472
Simple generator of random numbers over the range [0, 1)
Definition: Math.h:134
tools::GridSampler< AccessorType, SamplerT > SamplerType
Definition: RayTracer.h:185
IntersectorT::GridType GridType
Definition: RayTracer.h:181
const RGBA * pixels() const
Definition: RayTracer.h:376
virtual BaseShader * copy() const
Definition: RayTracer.h:647
void rayTrace(const GridT &, const IntersectorT &, const BaseShader &, BaseCamera &, size_t pixelSamples=1, unsigned int seed=0, bool threaded=true)
Ray-trace a volume using a given ray intersector.
Definition: RayTracer.h:671
virtual ~MatteShader()
Definition: RayTracer.h:576
const RGBA & pixel(size_t w, size_t h) const
Definition: RayTracer.h:294
void setIntersector(const IntersectorT &inter)
Set the intersector that performs the actual intersection of the rays against the volume...
Definition: RayTracer.h:875
MatType scale(const Vec3< typename MatType::value_type > &s)
Return a matrix that scales by s.
Definition: Mat.h:593
virtual BaseShader * copy() const =0
LevelSetRayTracer(const GridT &grid, const BaseShader &shader, BaseCamera &camera, size_t pixelSamples=1, unsigned int seed=0)
Constructor based on an instance of the grid to be rendered.
Definition: RayTracer.h:689
PositionShader(const math::BBox< Vec3R > &bbox, const Film::RGBA &c=Film::RGBA(1.0f))
Definition: RayTracer.h:610
A (very) simple multithreaded volume render specifically for scalar density.
Definition: RayTracer.h:177
size_t height() const
Definition: RayTracer.h:374
void setPrimaryStep(Real primaryStep)
Set the integration step-size in voxel units for the primay ray.
Definition: RayTracer.h:212
void postTranslate(const Vec3< T0 > &tr)
Right multiplies by the specified translation matrix, i.e. (*this) * Trans.
Definition: Mat4.h:726
void checkerboard(const RGBA &c1=RGBA(0.3f), const RGBA &c2=RGBA(0.6f), size_t size=32)
Definition: RayTracer.h:309
virtual ~BaseCamera()
Definition: RayTracer.h:404
RGBA & operator+=(const RGBA &rhs)
Definition: RayTracer.h:269
Class that provides the interface for continuous sampling of values in a tree.
Definition: Interpolation.h:220
static double fieldOfViewToFocalLength(double fov, double aperture)
Return the focal length in mm given a horizontal field of view in degrees and the specified aperture ...
Definition: RayTracer.h:508
static double focalLengthToFieldOfView(double length, double aperture)
Return the horizontal field of view in degrees given a focal lenth in mm and the specified aperture i...
Definition: RayTracer.h:502
void operator()(const tbb::blocked_range< size_t > &range) const
Public method required by tbb::parallel_for.
Definition: RayTracer.h:799
void setShadowStep(Real shadowStep)
Set the integration step-size in voxel units for the primay ray.
Definition: RayTracer.h:215
Film * mFilm
Definition: RayTracer.h:447
ValueT b
Definition: RayTracer.h:280
Definition: RayTracer.h:607
Mat3< typename promote< T0, T1 >::type > operator*(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Matrix multiplication.
Definition: Mat3.h:608
GridT GridType
Definition: RayTracer.h:103
void setCutOff(Real cutOff)
Set the cut-off value for density and transmittance.
Definition: RayTracer.h:228
void fill(const RGBA &rgb=RGBA(0))
Definition: RayTracer.h:308
void setShader(const BaseShader &shader)
Set the shader derived from the abstract BaseShader class.
Definition: RayTracer.h:756
double Real
Definition: Types.h:63
Vec3< T > unit(T eps=0) const
return normalized this, throws if null vector
Definition: Vec3.h:356
A general linear transform using homogeneous coordinates to perform rotation, scaling, shear and translation.
Definition: Maps.h:323
virtual Film::RGBA operator()(const Vec3R &, const Vec3R &, const Vec3R &) const
Defines the interface of the virtual function that returns a RGB color.
Definition: RayTracer.h:577
void setDir(const Vec3Type &dir)
Definition: Ray.h:90
double mScaleWidth
Definition: RayTracer.h:448
DiffuseShader(const Film::RGBA &d=Film::RGBA(1.0f))
Definition: RayTracer.h:633
Vec3< typename promote< T, typename Coord::ValueType >::type > operator+(const Vec3< T > &v0, const Coord &v1)
Allow a Coord to be added to or subtracted from a Vec3.
Definition: Coord.h:382
void setIntersector(const IntersectorT &inter)
Set the intersector that performs the actual intersection of the rays against the narrow-band level s...
Definition: RayTracer.h:748
void setScattering(Real x, Real y, Real z)
Set Scattering coefficients.
Definition: RayTracer.h:218
Shader that produces a simple matte.
Definition: RayTracer.h:572
VolumeRender(const IntersectorT &inter, BaseCamera &camera)
Constructor taking an intersector and a base camera.
Definition: RayTracer.h:822
virtual math::Ray< double > getRay(size_t i, size_t j, double iOffset=0.5, double jOffset=0.5) const
Return a Ray in world space given the pixel indices and optional offsets in the range [0...
Definition: RayTracer.h:488
void setPixelSamples(size_t pixelSamples, unsigned int seed=0)
Set the number of pixel samples and the seed for jittered sub-rays. A value larger then one implies a...
Definition: RayTracer.h:772
MatType unit(const MatType &mat, typename MatType::value_type eps=1.0e-8)
Return a copy of the given matrix with its upper 3x3 rows normalized.
Definition: Mat.h:626
IntersectorT::RayType RayType
Definition: RayTracer.h:182
Definition: Math.h:770
virtual BaseShader * copy() const
Definition: RayTracer.h:581
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:67
Axis-aligned bounding box.
Definition: BBox.h:47
virtual ~BaseShader()
Definition: RayTracer.h:561
math::Ray< Real > RayT
Definition: RayTracer.h:559
virtual ~PerspectiveCamera()
Definition: RayTracer.h:483
virtual Film::RGBA operator()(const Vec3R &, const Vec3R &normal, const Vec3R &) const
Defines the interface of the virtual function that returns a RGB color.
Definition: RayTracer.h:594
~LevelSetRayTracer()
Destructor.
Definition: RayTracer.h:733
RGBA(ValueT _r, ValueT _g, ValueT _b, ValueT _a=1.0f)
Definition: RayTracer.h:264
void setCamera(BaseCamera &camera)
Set the camera derived from the abstract BaseCamera class.
Definition: RayTracer.h:198
IntersectorT::RayType RayType
Definition: RayTracer.h:105
virtual ~NormalShader()
Definition: RayTracer.h:593
math::Ray< double > mRay
Definition: RayTracer.h:449
void render(bool threaded=true) const
Perform the actual (potentially multithreaded) volume rendering.
Definition: RayTracer.h:883
RGBA & pixel(size_t w, size_t h)
Definition: RayTracer.h:301
void setLightColor(Real r, Real g, Real b)
Set the color of the direcitonal light source.
Definition: RayTracer.h:209
Simple diffuse Lambertian surface shader.
Definition: RayTracer.h:630
virtual Film::RGBA operator()(const Vec3R &xyz, const Vec3R &, const Vec3R &) const
Defines the interface of the virtual function that returns a RGB color.
Definition: RayTracer.h:613
void setAbsorption(Real x, Real y, Real z)
Set absorption coefficients.
Definition: RayTracer.h:221