OpenVDB  8.0.1
RayTracer.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3 
17 
18 #ifndef OPENVDB_TOOLS_RAYTRACER_HAS_BEEN_INCLUDED
19 #define OPENVDB_TOOLS_RAYTRACER_HAS_BEEN_INCLUDED
20 
21 #include <openvdb/Types.h>
22 #include <openvdb/math/BBox.h>
23 #include <openvdb/math/Ray.h>
24 #include <openvdb/math/Math.h>
27 #include <deque>
28 #include <iostream>
29 #include <fstream>
30 #include <limits>
31 #include <memory>
32 #include <string>
33 #include <type_traits>
34 #include <vector>
35 
36 #ifdef OPENVDB_TOOLS_RAYTRACER_USE_EXR
37 #include <OpenEXR/ImfPixelType.h>
38 #include <OpenEXR/ImfChannelList.h>
39 #include <OpenEXR/ImfOutputFile.h>
40 #include <OpenEXR/ImfHeader.h>
41 #include <OpenEXR/ImfFrameBuffer.h>
42 #endif
43 
44 namespace openvdb {
46 namespace OPENVDB_VERSION_NAME {
47 namespace tools {
48 
49 // Forward declarations
50 class BaseCamera;
51 class BaseShader;
52 
54 template<typename GridT>
55 inline void rayTrace(const GridT&,
56  const BaseShader&,
57  BaseCamera&,
58  size_t pixelSamples = 1,
59  unsigned int seed = 0,
60  bool threaded = true);
61 
63 template<typename GridT, typename IntersectorT>
64 inline void rayTrace(const GridT&,
65  const IntersectorT&,
66  const BaseShader&,
67  BaseCamera&,
68  size_t pixelSamples = 1,
69  unsigned int seed = 0,
70  bool threaded = true);
71 
72 
74 
77 template<typename GridT, typename IntersectorT = tools::LevelSetRayIntersector<GridT> >
79 {
80 public:
81  using GridType = GridT;
82  using Vec3Type = typename IntersectorT::Vec3Type;
83  using RayType = typename IntersectorT::RayType;
84 
86  LevelSetRayTracer(const GridT& grid,
87  const BaseShader& shader,
88  BaseCamera& camera,
89  size_t pixelSamples = 1,
90  unsigned int seed = 0);
91 
94  LevelSetRayTracer(const IntersectorT& inter,
95  const BaseShader& shader,
96  BaseCamera& camera,
97  size_t pixelSamples = 1,
98  unsigned int seed = 0);
99 
101  LevelSetRayTracer(const LevelSetRayTracer& other);
102 
105 
107  void setGrid(const GridT& grid);
108 
111  void setIntersector(const IntersectorT& inter);
112 
120  void setShader(const BaseShader& shader);
121 
123  void setCamera(BaseCamera& camera);
124 
129  void setPixelSamples(size_t pixelSamples, unsigned int seed = 0);
130 
132  void render(bool threaded = true) const;
133 
136  void operator()(const tbb::blocked_range<size_t>& range) const;
137 
138 private:
139  const bool mIsMaster;
140  double* mRand;
141  IntersectorT mInter;
142  std::unique_ptr<const BaseShader> mShader;
143  BaseCamera* mCamera;
144  size_t mSubPixels;
145 };// LevelSetRayTracer
146 
147 
149 
154 template <typename IntersectorT, typename SamplerT = tools::BoxSampler>
156 {
157 public:
158 
159  using GridType = typename IntersectorT::GridType;
160  using RayType = typename IntersectorT::RayType;
161  using ValueType = typename GridType::ValueType;
162  using AccessorType = typename GridType::ConstAccessor;
164  static_assert(std::is_floating_point<ValueType>::value,
165  "VolumeRender requires a floating-point-valued grid");
166 
168  VolumeRender(const IntersectorT& inter, BaseCamera& camera);
169 
171  VolumeRender(const VolumeRender& other);
172 
174  void render(bool threaded=true) const;
175 
177  void setCamera(BaseCamera& camera) { mCamera = &camera; }
178 
181  void setIntersector(const IntersectorT& inter);
182 
185  void setLightDir(Real x, Real y, Real z) { mLightDir = Vec3R(x,y,z).unit(); }
186 
188  void setLightColor(Real r, Real g, Real b) { mLightColor = Vec3R(r,g,b); }
189 
191  void setPrimaryStep(Real primaryStep) { mPrimaryStep = primaryStep; }
192 
194  void setShadowStep(Real shadowStep) { mShadowStep = shadowStep; }
195 
197  void setScattering(Real x, Real y, Real z) { mScattering = Vec3R(x,y,z); }
198 
200  void setAbsorption(Real x, Real y, Real z) { mAbsorption = Vec3R(x,y,z); }
201 
204  void setLightGain(Real gain) { mLightGain = gain; }
205 
207  void setCutOff(Real cutOff) { mCutOff = cutOff; }
208 
213  void print(std::ostream& os = std::cout, int verboseLevel = 1);
214 
217  void operator()(const tbb::blocked_range<size_t>& range) const;
218 
219 private:
220 
221  AccessorType mAccessor;
222  BaseCamera* mCamera;
223  std::unique_ptr<IntersectorT> mPrimary, mShadow;
224  Real mPrimaryStep, mShadowStep, mCutOff, mLightGain;
225  Vec3R mLightDir, mLightColor, mAbsorption, mScattering;
226 };//VolumeRender
227 
229 
232 class Film
233 {
234 public:
237  struct RGBA
238  {
239  using ValueT = float;
240 
241  RGBA() : r(0), g(0), b(0), a(1) {}
242  explicit RGBA(ValueT intensity) : r(intensity), g(intensity), b(intensity), a(1) {}
243  RGBA(ValueT _r, ValueT _g, ValueT _b, ValueT _a = static_cast<ValueT>(1.0)):
244  r(_r), g(_g), b(_b), a(_a)
245  {}
246  RGBA(double _r, double _g, double _b, double _a = 1.0)
247  : r(static_cast<ValueT>(_r))
248  , g(static_cast<ValueT>(_g))
249  , b(static_cast<ValueT>(_b))
250  , a(static_cast<ValueT>(_a))
251  {}
252 
253  RGBA operator* (ValueT scale) const { return RGBA(r*scale, g*scale, b*scale);}
254  RGBA operator+ (const RGBA& rhs) const { return RGBA(r+rhs.r, g+rhs.g, b+rhs.b);}
255  RGBA operator* (const RGBA& rhs) const { return RGBA(r*rhs.r, g*rhs.g, b*rhs.b);}
256  RGBA& operator+=(const RGBA& rhs) { r+=rhs.r; g+=rhs.g; b+=rhs.b; a+=rhs.a; return *this;}
257 
258  void over(const RGBA& rhs)
259  {
260  const float s = rhs.a*(1.0f-a);
261  r = a*r+s*rhs.r;
262  g = a*g+s*rhs.g;
263  b = a*b+s*rhs.b;
264  a = a + s;
265  }
266 
267  ValueT r, g, b, a;
268  };
269 
270 
271  Film(size_t width, size_t height)
272  : mWidth(width), mHeight(height), mSize(width*height), mPixels(new RGBA[mSize])
273  {
274  }
275  Film(size_t width, size_t height, const RGBA& bg)
276  : mWidth(width), mHeight(height), mSize(width*height), mPixels(new RGBA[mSize])
277  {
278  this->fill(bg);
279  }
280 
281  const RGBA& pixel(size_t w, size_t h) const
282  {
283  assert(w < mWidth);
284  assert(h < mHeight);
285  return mPixels[w + h*mWidth];
286  }
287 
288  RGBA& pixel(size_t w, size_t h)
289  {
290  assert(w < mWidth);
291  assert(h < mHeight);
292  return mPixels[w + h*mWidth];
293  }
294 
295  void fill(const RGBA& rgb=RGBA(0)) { for (size_t i=0; i<mSize; ++i) mPixels[i] = rgb; }
296  void checkerboard(const RGBA& c1=RGBA(0.3f), const RGBA& c2=RGBA(0.6f), size_t size=32)
297  {
298  RGBA *p = mPixels.get();
299  for (size_t j = 0; j < mHeight; ++j) {
300  for (size_t i = 0; i < mWidth; ++i, ++p) {
301  *p = ((i & size) ^ (j & size)) ? c1 : c2;
302  }
303  }
304  }
305 
306  void savePPM(const std::string& fileName)
307  {
308  std::string name(fileName);
309  if (name.find_last_of(".") == std::string::npos) name.append(".ppm");
310 
311  std::unique_ptr<unsigned char[]> buffer(new unsigned char[3*mSize]);
312  unsigned char *tmp = buffer.get(), *q = tmp;
313  RGBA* p = mPixels.get();
314  size_t n = mSize;
315  while (n--) {
316  *q++ = static_cast<unsigned char>(255.0f*(*p ).r);
317  *q++ = static_cast<unsigned char>(255.0f*(*p ).g);
318  *q++ = static_cast<unsigned char>(255.0f*(*p++).b);
319  }
320 
321  std::ofstream os(name.c_str(), std::ios_base::binary);
322  if (!os.is_open()) {
323  std::cerr << "Error opening PPM file \"" << name << "\"" << std::endl;
324  return;
325  }
326 
327  os << "P6\n" << mWidth << " " << mHeight << "\n255\n";
328  os.write(reinterpret_cast<const char*>(&(*tmp)), 3 * mSize * sizeof(unsigned char));
329  }
330 
331 #ifdef OPENVDB_TOOLS_RAYTRACER_USE_EXR
332  void saveEXR(const std::string& fileName, size_t compression = 2, size_t threads = 8)
333  {
334  std::string name(fileName);
335  if (name.find_last_of(".") == std::string::npos) name.append(".exr");
336 
337  if (threads>0) Imf::setGlobalThreadCount(threads);
338  Imf::Header header(mWidth, mHeight);
339  if (compression==0) header.compression() = Imf::NO_COMPRESSION;
340  if (compression==1) header.compression() = Imf::RLE_COMPRESSION;
341  if (compression>=2) header.compression() = Imf::ZIP_COMPRESSION;
342  header.channels().insert("R", Imf::Channel(Imf::FLOAT));
343  header.channels().insert("G", Imf::Channel(Imf::FLOAT));
344  header.channels().insert("B", Imf::Channel(Imf::FLOAT));
345  header.channels().insert("A", Imf::Channel(Imf::FLOAT));
346 
347  Imf::FrameBuffer framebuffer;
348  framebuffer.insert("R", Imf::Slice( Imf::FLOAT, (char *) &(mPixels[0].r),
349  sizeof (RGBA), sizeof (RGBA) * mWidth));
350  framebuffer.insert("G", Imf::Slice( Imf::FLOAT, (char *) &(mPixels[0].g),
351  sizeof (RGBA), sizeof (RGBA) * mWidth));
352  framebuffer.insert("B", Imf::Slice( Imf::FLOAT, (char *) &(mPixels[0].b),
353  sizeof (RGBA), sizeof (RGBA) * mWidth));
354  framebuffer.insert("A", Imf::Slice( Imf::FLOAT, (char *) &(mPixels[0].a),
355  sizeof (RGBA), sizeof (RGBA) * mWidth));
356 
357  Imf::OutputFile file(name.c_str(), header);
358  file.setFrameBuffer(framebuffer);
359  file.writePixels(mHeight);
360  }
361 #endif
362 
363  size_t width() const { return mWidth; }
364  size_t height() const { return mHeight; }
365  size_t numPixels() const { return mSize; }
366  const RGBA* pixels() const { return mPixels.get(); }
367 
368 private:
369  size_t mWidth, mHeight, mSize;
370  std::unique_ptr<RGBA[]> mPixels;
371 };// Film
372 
373 
375 
378 {
379 public:
380  BaseCamera(Film& film, const Vec3R& rotation, const Vec3R& translation,
381  double frameWidth, double nearPlane, double farPlane)
382  : mFilm(&film)
383  , mScaleWidth(frameWidth)
384  , mScaleHeight(frameWidth * double(film.height()) / double(film.width()))
385  {
386  assert(nearPlane > 0 && farPlane > nearPlane);
387  mScreenToWorld.accumPostRotation(math::X_AXIS, rotation[0] * M_PI / 180.0);
388  mScreenToWorld.accumPostRotation(math::Y_AXIS, rotation[1] * M_PI / 180.0);
389  mScreenToWorld.accumPostRotation(math::Z_AXIS, rotation[2] * M_PI / 180.0);
390  mScreenToWorld.accumPostTranslation(translation);
391  this->initRay(nearPlane, farPlane);
392  }
393 
394  virtual ~BaseCamera() {}
395 
396  Film::RGBA& pixel(size_t i, size_t j) { return mFilm->pixel(i, j); }
397 
398  size_t width() const { return mFilm->width(); }
399  size_t height() const { return mFilm->height(); }
400 
405  void lookAt(const Vec3R& xyz, const Vec3R& up = Vec3R(0.0, 1.0, 0.0))
406  {
407  const Vec3R orig = mScreenToWorld.applyMap(Vec3R(0.0));
408  const Vec3R dir = orig - xyz;
409  try {
410  Mat4d xform = math::aim<Mat4d>(dir, up);
411  xform.postTranslate(orig);
412  mScreenToWorld = math::AffineMap(xform);
413  this->initRay(mRay.t0(), mRay.t1());
414  } catch (...) {}
415  }
416 
417  Vec3R rasterToScreen(double i, double j, double z) const
418  {
419  return Vec3R( (2 * i / double(mFilm->width()) - 1) * mScaleWidth,
420  (1 - 2 * j / double(mFilm->height())) * mScaleHeight, z );
421  }
422 
426  virtual math::Ray<double> getRay(
427  size_t i, size_t j, double iOffset = 0.5, double jOffset = 0.5) const = 0;
428 
429 protected:
430  void initRay(double t0, double t1)
431  {
432  mRay.setTimes(t0, t1);
433  mRay.setEye(mScreenToWorld.applyMap(Vec3R(0.0)));
434  mRay.setDir(mScreenToWorld.applyJacobian(Vec3R(0.0, 0.0, -1.0)));
435  }
436 
438  double mScaleWidth, mScaleHeight;
441 };// BaseCamera
442 
443 
445 {
446  public:
463  const Vec3R& rotation = Vec3R(0.0),
464  const Vec3R& translation = Vec3R(0.0),
465  double focalLength = 50.0,
466  double aperture = 41.2136,
467  double nearPlane = 1e-3,
468  double farPlane = std::numeric_limits<double>::max())
469  : BaseCamera(film, rotation, translation, 0.5*aperture/focalLength, nearPlane, farPlane)
470  {
471  }
472 
473  ~PerspectiveCamera() override = default;
474 
479  size_t i, size_t j, double iOffset = 0.5, double jOffset = 0.5) const override
480  {
481  math::Ray<double> ray(mRay);
482  Vec3R dir = BaseCamera::rasterToScreen(Real(i) + iOffset, Real(j) + jOffset, -1.0);
483  dir = BaseCamera::mScreenToWorld.applyJacobian(dir);
484  dir.normalize();
485  ray.scaleTimes(1.0/dir.dot(ray.dir()));
486  ray.setDir(dir);
487  return ray;
488  }
489 
492  static double focalLengthToFieldOfView(double length, double aperture)
493  {
494  return 360.0 / M_PI * atan(aperture/(2.0*length));
495  }
498  static double fieldOfViewToFocalLength(double fov, double aperture)
499  {
500  return aperture/(2.0*(tan(fov * M_PI / 360.0)));
501  }
502 };// PerspectiveCamera
503 
504 
506 {
507 public:
521  const Vec3R& rotation = Vec3R(0.0),
522  const Vec3R& translation = Vec3R(0.0),
523  double frameWidth = 1.0,
524  double nearPlane = 1e-3,
525  double farPlane = std::numeric_limits<double>::max())
526  : BaseCamera(film, rotation, translation, 0.5*frameWidth, nearPlane, farPlane)
527  {
528  }
529  ~OrthographicCamera() override = default;
530 
532  size_t i, size_t j, double iOffset = 0.5, double jOffset = 0.5) const override
533  {
534  math::Ray<double> ray(mRay);
535  Vec3R eye = BaseCamera::rasterToScreen(Real(i) + iOffset, Real(j) + jOffset, 0.0);
536  ray.setEye(BaseCamera::mScreenToWorld.applyMap(eye));
537  return ray;
538  }
539 };// OrthographicCamera
540 
541 
543 
544 
547 {
548 public:
551  BaseShader(const BaseShader&) = default;
552  virtual ~BaseShader() = default;
557  virtual Film::RGBA operator()(const Vec3R& xyz, const Vec3R& nml, const Vec3R& dir) const = 0;
558  virtual BaseShader* copy() const = 0;
559 };
560 
561 
568 template<typename GridT = Film::RGBA,
569  typename SamplerType = tools::PointSampler>
570 class MatteShader: public BaseShader
571 {
572 public:
573  MatteShader(const GridT& grid) : mAcc(grid.getAccessor()), mXform(&grid.transform()) {}
574  MatteShader(const MatteShader&) = default;
575  ~MatteShader() override = default;
576  Film::RGBA operator()(const Vec3R& xyz, const Vec3R&, const Vec3R&) const override
577  {
578  typename GridT::ValueType v = zeroVal<typename GridT::ValueType>();
579  SamplerType::sample(mAcc, mXform->worldToIndex(xyz), v);
580  return Film::RGBA(v[0], v[1], v[2]);
581  }
582  BaseShader* copy() const override { return new MatteShader<GridT, SamplerType>(*this); }
583 
584 private:
585  typename GridT::ConstAccessor mAcc;
586  const math::Transform* mXform;
587 };
588 
589 // Template specialization using a constant color of the material.
590 template<typename SamplerType>
591 class MatteShader<Film::RGBA, SamplerType>: public BaseShader
592 {
593 public:
594  MatteShader(const Film::RGBA& c = Film::RGBA(1.0f)): mRGBA(c) {}
595  MatteShader(const MatteShader&) = default;
596  ~MatteShader() override = default;
597  Film::RGBA operator()(const Vec3R&, const Vec3R&, const Vec3R&) const override
598  {
599  return mRGBA;
600  }
601  BaseShader* copy() const override { return new MatteShader<Film::RGBA, SamplerType>(*this); }
602 
603 private:
604  const Film::RGBA mRGBA;
605 };
606 
607 
615 template<typename GridT = Film::RGBA,
616  typename SamplerType = tools::PointSampler>
618 {
619 public:
620  NormalShader(const GridT& grid) : mAcc(grid.getAccessor()), mXform(&grid.transform()) {}
621  NormalShader(const NormalShader&) = default;
622  ~NormalShader() override = default;
623  Film::RGBA operator()(const Vec3R& xyz, const Vec3R& normal, const Vec3R&) const override
624  {
625  typename GridT::ValueType v = zeroVal<typename GridT::ValueType>();
626  SamplerType::sample(mAcc, mXform->worldToIndex(xyz), v);
627  return Film::RGBA(v[0]*(normal[0]+1.0), v[1]*(normal[1]+1.0), v[2]*(normal[2]+1.0));
628  }
629  BaseShader* copy() const override { return new NormalShader<GridT, SamplerType>(*this); }
630 
631 private:
632  typename GridT::ConstAccessor mAcc;
633  const math::Transform* mXform;
634 };
635 
636 // Template specialization using a constant color of the material.
637 template<typename SamplerType>
638 class NormalShader<Film::RGBA, SamplerType>: public BaseShader
639 {
640 public:
641  NormalShader(const Film::RGBA& c = Film::RGBA(1.0f)) : mRGBA(c*0.5f) {}
642  NormalShader(const NormalShader&) = default;
643  ~NormalShader() override = default;
644  Film::RGBA operator()(const Vec3R&, const Vec3R& normal, const Vec3R&) const override
645  {
646  return mRGBA * Film::RGBA(normal[0] + 1.0, normal[1] + 1.0, normal[2] + 1.0);
647  }
648  BaseShader* copy() const override { return new NormalShader<Film::RGBA, SamplerType>(*this); }
649 
650 private:
651  const Film::RGBA mRGBA;
652 };
653 
654 
662 template<typename GridT = Film::RGBA,
663  typename SamplerType = tools::PointSampler>
665 {
666 public:
667  PositionShader(const math::BBox<Vec3R>& bbox, const GridT& grid)
668  : mMin(bbox.min())
669  , mInvDim(1.0/bbox.extents())
670  , mAcc(grid.getAccessor())
671  , mXform(&grid.transform())
672  {
673  }
674  PositionShader(const PositionShader&) = default;
675  ~PositionShader() override = default;
676  Film::RGBA operator()(const Vec3R& xyz, const Vec3R&, const Vec3R&) const override
677  {
678  typename GridT::ValueType v = zeroVal<typename GridT::ValueType>();
679  SamplerType::sample(mAcc, mXform->worldToIndex(xyz), v);
680  const Vec3R rgb = (xyz - mMin) * mInvDim;
681  return Film::RGBA(v[0],v[1],v[2]) * Film::RGBA(rgb[0], rgb[1], rgb[2]);
682  }
683  BaseShader* copy() const override { return new PositionShader<GridT, SamplerType>(*this); }
684 
685 private:
686  const Vec3R mMin, mInvDim;
687  typename GridT::ConstAccessor mAcc;
688  const math::Transform* mXform;
689 };
690 
691 // Template specialization using a constant color of the material.
692 template<typename SamplerType>
693 class PositionShader<Film::RGBA, SamplerType>: public BaseShader
694 {
695 public:
696  PositionShader(const math::BBox<Vec3R>& bbox, const Film::RGBA& c = Film::RGBA(1.0f))
697  : mMin(bbox.min()), mInvDim(1.0/bbox.extents()), mRGBA(c) {}
698  PositionShader(const PositionShader&) = default;
699  ~PositionShader() override = default;
700  Film::RGBA operator()(const Vec3R& xyz, const Vec3R&, const Vec3R&) const override
701  {
702  const Vec3R rgb = (xyz - mMin)*mInvDim;
703  return mRGBA*Film::RGBA(rgb[0], rgb[1], rgb[2]);
704  }
705  BaseShader* copy() const override { return new PositionShader<Film::RGBA, SamplerType>(*this); }
706 
707 private:
708  const Vec3R mMin, mInvDim;
709  const Film::RGBA mRGBA;
710 };
711 
712 
722 template<typename GridT = Film::RGBA,
723  typename SamplerType = tools::PointSampler>
725 {
726 public:
727  DiffuseShader(const GridT& grid): mAcc(grid.getAccessor()), mXform(&grid.transform()) {}
728  DiffuseShader(const DiffuseShader&) = default;
729  ~DiffuseShader() override = default;
730  Film::RGBA operator()(const Vec3R& xyz, const Vec3R& normal, const Vec3R& rayDir) const override
731  {
732  typename GridT::ValueType v = zeroVal<typename GridT::ValueType>();
733  SamplerType::sample(mAcc, mXform->worldToIndex(xyz), v);
734  // We take the abs of the dot product corresponding to having
735  // light sources at +/- rayDir, i.e., two-sided shading.
736  return Film::RGBA(v[0],v[1],v[2])
737  * static_cast<Film::RGBA::ValueT>(math::Abs(normal.dot(rayDir)));
738  }
739  BaseShader* copy() const override { return new DiffuseShader<GridT, SamplerType>(*this); }
740 
741 private:
742  typename GridT::ConstAccessor mAcc;
743  const math::Transform* mXform;
744 };
745 
746 // Template specialization using a constant color of the material.
747 template <typename SamplerType>
748 class DiffuseShader<Film::RGBA, SamplerType>: public BaseShader
749 {
750 public:
751  DiffuseShader(const Film::RGBA& d = Film::RGBA(1.0f)): mRGBA(d) {}
752  DiffuseShader(const DiffuseShader&) = default;
753  ~DiffuseShader() override = default;
754  Film::RGBA operator()(const Vec3R&, const Vec3R& normal, const Vec3R& rayDir) const override
755  {
756  // We assume a single directional light source at the camera,
757  // so the cosine of the angle between the surface normal and the
758  // direction of the light source becomes the dot product of the
759  // surface normal and inverse direction of the ray. We also ignore
760  // negative dot products, corresponding to strict one-sided shading.
761  //return mRGBA * math::Max(0.0, normal.dot(-rayDir));
762 
763  // We take the abs of the dot product corresponding to having
764  // light sources at +/- rayDir, i.e., two-sided shading.
765  return mRGBA * static_cast<Film::RGBA::ValueT>(math::Abs(normal.dot(rayDir)));
766  }
767  BaseShader* copy() const override { return new DiffuseShader<Film::RGBA, SamplerType>(*this); }
768 
769 private:
770  const Film::RGBA mRGBA;
771 };
772 
773 
775 
776 template<typename GridT>
777 inline void rayTrace(const GridT& grid,
778  const BaseShader& shader,
779  BaseCamera& camera,
780  size_t pixelSamples,
781  unsigned int seed,
782  bool threaded)
783 {
785  tracer(grid, shader, camera, pixelSamples, seed);
786  tracer.render(threaded);
787 }
788 
789 
790 template<typename GridT, typename IntersectorT>
791 inline void rayTrace(const GridT&,
792  const IntersectorT& inter,
793  const BaseShader& shader,
794  BaseCamera& camera,
795  size_t pixelSamples,
796  unsigned int seed,
797  bool threaded)
798 {
799  LevelSetRayTracer<GridT, IntersectorT> tracer(inter, shader, camera, pixelSamples, seed);
800  tracer.render(threaded);
801 }
802 
803 
805 
806 
807 template<typename GridT, typename IntersectorT>
809 LevelSetRayTracer(const GridT& grid,
810  const BaseShader& shader,
811  BaseCamera& camera,
812  size_t pixelSamples,
813  unsigned int seed)
814  : mIsMaster(true),
815  mRand(nullptr),
816  mInter(grid),
817  mShader(shader.copy()),
818  mCamera(&camera)
819 {
820  this->setPixelSamples(pixelSamples, seed);
821 }
822 
823 template<typename GridT, typename IntersectorT>
825 LevelSetRayTracer(const IntersectorT& inter,
826  const BaseShader& shader,
827  BaseCamera& camera,
828  size_t pixelSamples,
829  unsigned int seed)
830  : mIsMaster(true),
831  mRand(nullptr),
832  mInter(inter),
833  mShader(shader.copy()),
834  mCamera(&camera)
835 {
836  this->setPixelSamples(pixelSamples, seed);
837 }
838 
839 template<typename GridT, typename IntersectorT>
842  mIsMaster(false),
843  mRand(other.mRand),
844  mInter(other.mInter),
845  mShader(other.mShader->copy()),
846  mCamera(other.mCamera),
847  mSubPixels(other.mSubPixels)
848 {
849 }
850 
851 template<typename GridT, typename IntersectorT>
854 {
855  if (mIsMaster) delete [] mRand;
856 }
857 
858 template<typename GridT, typename IntersectorT>
860 setGrid(const GridT& grid)
861 {
862  assert(mIsMaster);
863  mInter = IntersectorT(grid);
864 }
865 
866 template<typename GridT, typename IntersectorT>
868 setIntersector(const IntersectorT& inter)
869 {
870  assert(mIsMaster);
871  mInter = inter;
872 }
873 
874 template<typename GridT, typename IntersectorT>
876 setShader(const BaseShader& shader)
877 {
878  assert(mIsMaster);
879  mShader.reset(shader.copy());
880 }
881 
882 template<typename GridT, typename IntersectorT>
885 {
886  assert(mIsMaster);
887  mCamera = &camera;
888 }
889 
890 template<typename GridT, typename IntersectorT>
892 setPixelSamples(size_t pixelSamples, unsigned int seed)
893 {
894  assert(mIsMaster);
895  if (pixelSamples == 0) {
896  OPENVDB_THROW(ValueError, "pixelSamples must be larger than zero!");
897  }
898  mSubPixels = pixelSamples - 1;
899  delete [] mRand;
900  if (mSubPixels > 0) {
901  mRand = new double[16];
902  math::Rand01<double> rand(seed);//offsets for anti-aliaing by jittered super-sampling
903  for (size_t i=0; i<16; ++i) mRand[i] = rand();
904  } else {
905  mRand = nullptr;
906  }
907 }
908 
909 template<typename GridT, typename IntersectorT>
911 render(bool threaded) const
912 {
913  tbb::blocked_range<size_t> range(0, mCamera->height());
914  threaded ? tbb::parallel_for(range, *this) : (*this)(range);
915 }
916 
917 template<typename GridT, typename IntersectorT>
919 operator()(const tbb::blocked_range<size_t>& range) const
920 {
921  const BaseShader& shader = *mShader;
922  Vec3Type xyz, nml;
923  const float frac = 1.0f / (1.0f + float(mSubPixels));
924  for (size_t j=range.begin(), n=0, je = range.end(); j<je; ++j) {
925  for (size_t i=0, ie = mCamera->width(); i<ie; ++i) {
926  Film::RGBA& bg = mCamera->pixel(i,j);
927  RayType ray = mCamera->getRay(i, j);//primary ray
928  Film::RGBA c = mInter.intersectsWS(ray, xyz, nml) ? shader(xyz, nml, ray.dir()) : bg;
929  for (size_t k=0; k<mSubPixels; ++k, n +=2 ) {
930  ray = mCamera->getRay(i, j, mRand[n & 15], mRand[(n+1) & 15]);
931  c += mInter.intersectsWS(ray, xyz, nml) ? shader(xyz, nml, ray.dir()) : bg;
932  }//loop over sub-pixels
933  bg = c*frac;
934  }//loop over image height
935  }//loop over image width
936 }
937 
939 
940 template<typename IntersectorT, typename SampleT>
942 VolumeRender(const IntersectorT& inter, BaseCamera& camera)
943  : mAccessor(inter.grid().getConstAccessor())
944  , mCamera(&camera)
945  , mPrimary(new IntersectorT(inter))
946  , mShadow(new IntersectorT(inter))
947  , mPrimaryStep(1.0)
948  , mShadowStep(3.0)
949  , mCutOff(0.005)
950  , mLightGain(0.2)
951  , mLightDir(Vec3R(0.3, 0.3, 0).unit())
952  , mLightColor(0.7, 0.7, 0.7)
953  , mAbsorption(0.1)
954  , mScattering(1.5)
955 {
956 }
957 
958 template<typename IntersectorT, typename SampleT>
961  : mAccessor(other.mAccessor)
962  , mCamera(other.mCamera)
963  , mPrimary(new IntersectorT(*(other.mPrimary)))
964  , mShadow(new IntersectorT(*(other.mShadow)))
965  , mPrimaryStep(other.mPrimaryStep)
966  , mShadowStep(other.mShadowStep)
967  , mCutOff(other.mCutOff)
968  , mLightGain(other.mLightGain)
969  , mLightDir(other.mLightDir)
970  , mLightColor(other.mLightColor)
971  , mAbsorption(other.mAbsorption)
972  , mScattering(other.mScattering)
973 {
974 }
975 
976 template<typename IntersectorT, typename SampleT>
978 print(std::ostream& os, int verboseLevel)
979 {
980  if (verboseLevel>0) {
981  os << "\nPrimary step: " << mPrimaryStep
982  << "\nShadow step: " << mShadowStep
983  << "\nCutoff: " << mCutOff
984  << "\nLightGain: " << mLightGain
985  << "\nLightDir: " << mLightDir
986  << "\nLightColor: " << mLightColor
987  << "\nAbsorption: " << mAbsorption
988  << "\nScattering: " << mScattering << std::endl;
989  }
990  mPrimary->print(os, verboseLevel);
991 }
992 
993 template<typename IntersectorT, typename SampleT>
995 setIntersector(const IntersectorT& inter)
996 {
997  mPrimary.reset(new IntersectorT(inter));
998  mShadow.reset( new IntersectorT(inter));
999 }
1000 
1001 template<typename IntersectorT, typename SampleT>
1003 render(bool threaded) const
1004 {
1005  tbb::blocked_range<size_t> range(0, mCamera->height());
1006  threaded ? tbb::parallel_for(range, *this) : (*this)(range);
1007 }
1008 
1009 template<typename IntersectorT, typename SampleT>
1011 operator()(const tbb::blocked_range<size_t>& range) const
1012 {
1013  SamplerType sampler(mAccessor, mShadow->grid().transform());//light-weight wrapper
1014 
1015  // Any variable prefixed with p (or s) means it's associated with a primary (or shadow) ray
1016  const Vec3R extinction = -mScattering-mAbsorption, One(1.0);
1017  const Vec3R albedo = mLightColor*mScattering/(mScattering+mAbsorption);//single scattering
1018  const Real sGain = mLightGain;//in-scattering along shadow ray
1019  const Real pStep = mPrimaryStep;//Integration step along primary ray in voxel units
1020  const Real sStep = mShadowStep;//Integration step along shadow ray in voxel units
1021  const Real cutoff = mCutOff;//Cutoff for density and transmittance
1022 
1023  // For the sake of completeness we show how to use two different
1024  // methods (hits/march) in VolumeRayIntersector that produce
1025  // segments along the ray that intersects active values. Comment out
1026  // the line below to use VolumeRayIntersector::march instead of
1027  // VolumeRayIntersector::hits.
1028 #define USE_HITS
1029 #ifdef USE_HITS
1030  std::vector<typename RayType::TimeSpan> pTS, sTS;
1031  //std::deque<typename RayType::TimeSpan> pTS, sTS;
1032 #endif
1033 
1034  RayType sRay(Vec3R(0), mLightDir);//Shadow ray
1035  for (size_t j=range.begin(), je = range.end(); j<je; ++j) {
1036  for (size_t i=0, ie = mCamera->width(); i<ie; ++i) {
1037  Film::RGBA& bg = mCamera->pixel(i, j);
1038  bg.a = bg.r = bg.g = bg.b = 0;
1039  RayType pRay = mCamera->getRay(i, j);// Primary ray
1040  if( !mPrimary->setWorldRay(pRay)) continue;
1041  Vec3R pTrans(1.0), pLumi(0.0);
1042 #ifndef USE_HITS
1043  Real pT0, pT1;
1044  while (mPrimary->march(pT0, pT1)) {
1045  for (Real pT = pStep*ceil(pT0/pStep); pT <= pT1; pT += pStep) {
1046 #else
1047  mPrimary->hits(pTS);
1048  for (size_t k=0; k<pTS.size(); ++k) {
1049  Real pT = pStep*ceil(pTS[k].t0/pStep), pT1=pTS[k].t1;
1050  for (; pT <= pT1; pT += pStep) {
1051 #endif
1052  Vec3R pPos = mPrimary->getWorldPos(pT);
1053  const Real density = sampler.wsSample(pPos);
1054  if (density < cutoff) continue;
1055  const Vec3R dT = math::Exp(extinction * density * pStep);
1056  Vec3R sTrans(1.0);
1057  sRay.setEye(pPos);
1058  if( !mShadow->setWorldRay(sRay)) continue;
1059 #ifndef USE_HITS
1060  Real sT0, sT1;
1061  while (mShadow->march(sT0, sT1)) {
1062  for (Real sT = sStep*ceil(sT0/sStep); sT <= sT1; sT+= sStep) {
1063 #else
1064  mShadow->hits(sTS);
1065  for (size_t l=0; l<sTS.size(); ++l) {
1066  Real sT = sStep*ceil(sTS[l].t0/sStep), sT1=sTS[l].t1;
1067  for (; sT <= sT1; sT+= sStep) {
1068 #endif
1069  const Real d = sampler.wsSample(mShadow->getWorldPos(sT));
1070  if (d < cutoff) continue;
1071  sTrans *= math::Exp(extinction * d * sStep/(1.0+sT*sGain));
1072  if (sTrans.lengthSqr()<cutoff) goto Luminance;//Terminate sRay
1073  }//Integration over shadow segment
1074  }// Shadow ray march
1075  Luminance:
1076  pLumi += albedo * sTrans * pTrans * (One-dT);
1077  pTrans *= dT;
1078  if (pTrans.lengthSqr()<cutoff) goto Pixel; // Terminate Ray
1079  }//Integration over primary segment
1080  }// Primary ray march
1081  Pixel:
1082  bg.r = static_cast<Film::RGBA::ValueT>(pLumi[0]);
1083  bg.g = static_cast<Film::RGBA::ValueT>(pLumi[1]);
1084  bg.b = static_cast<Film::RGBA::ValueT>(pLumi[2]);
1085  bg.a = static_cast<Film::RGBA::ValueT>(1.0f - pTrans.sum()/3.0f);
1086  }//Horizontal pixel scan
1087  }//Vertical pixel scan
1088 }
1089 
1090 } // namespace tools
1091 } // namespace OPENVDB_VERSION_NAME
1092 } // namespace openvdb
1093 
1094 #endif // OPENVDB_TOOLS_RAYTRACER_HAS_BEEN_INCLUDED
void setShadowStep(Real shadowStep)
Set the integration step-size in voxel units for the primay ray.
Definition: RayTracer.h:194
const Vec3T & dir() const
Definition: Ray.h:99
BaseShader * copy() const override
Definition: RayTracer.h:601
Simple generator of random numbers over the range [0, 1)
Definition: Math.h:165
double Real
Definition: openvdb/Types.h:38
ValueT r
Definition: RayTracer.h:267
size_t width() const
Definition: RayTracer.h:398
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:525
ValueT b
Definition: RayTracer.h:267
Film::RGBA operator()(const Vec3R &, const Vec3R &normal, const Vec3R &rayDir) const override
Defines the interface of the virtual function that returns a RGB color.
Definition: RayTracer.h:754
#define OPENVDB_THROW(exception, message)
Definition: openvdb/Exceptions.h:74
A simple class that allows for concurrent writes to pixels in an image, background initialization of ...
Definition: RayTracer.h:232
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
RGBA & pixel(size_t w, size_t h)
Definition: RayTracer.h:288
void setLightDir(Real x, Real y, Real z)
Set the vector components of a directional light source.
Definition: RayTracer.h:185
VolumeRender(const IntersectorT &inter, BaseCamera &camera)
Constructor taking an intersector and a base camera.
Definition: RayTracer.h:942
PositionShader(const math::BBox< Vec3R > &bbox, const GridT &grid)
Definition: RayTracer.h:667
Mat4< double > Mat4d
Definition: Mat4.h:1368
GridT GridType
Definition: RayTracer.h:81
Film * mFilm
Definition: RayTracer.h:437
BaseShader()
Definition: RayTracer.h:550
const RGBA * pixels() const
Definition: RayTracer.h:366
Class that provides the interface for continuous sampling of values in a tree.
Definition: Interpolation.h:283
const std::enable_if<!VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:107
Definition: RayTracer.h:444
void setShader(const BaseShader &shader)
Set the shader derived from the abstract BaseShader class.
Definition: RayTracer.h:876
BaseCamera(Film &film, const Vec3R &rotation, const Vec3R &translation, double frameWidth, double nearPlane, double farPlane)
Definition: RayTracer.h:380
void setDir(const Vec3Type &dir)
Definition: Ray.h:66
math::Ray< double > getRay(size_t i, size_t j, double iOffset=0.5, double jOffset=0.5) const override
Return a Ray in world space given the pixel indices and optional offsets in the range [0...
Definition: RayTracer.h:478
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:498
size_t height() const
Definition: RayTracer.h:364
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:492
BaseShader * copy() const override
Definition: RayTracer.h:767
virtual BaseShader * copy() const =0
BaseShader * copy() const override
Definition: RayTracer.h:629
Film(size_t width, size_t height, const RGBA &bg)
Definition: RayTracer.h:275
void setCutOff(Real cutOff)
Set the cut-off value for density and transmittance.
Definition: RayTracer.h:207
MatType scale(const Vec3< typename MatType::value_type > &s)
Return a matrix that scales by s.
Definition: Mat.h:637
Type Exp(const Type &x)
Return ex.
Definition: Math.h:713
RGBA & operator+=(const RGBA &rhs)
Definition: RayTracer.h:256
Film::RGBA operator()(const Vec3R &, const Vec3R &normal, const Vec3R &) const override
Defines the interface of the virtual function that returns a RGB color.
Definition: RayTracer.h:644
void setIntersector(const IntersectorT &inter)
Set the intersector that performs the actual intersection of the rays against the volume...
Definition: RayTracer.h:995
bool normalize(T eps=T(1.0e-7))
this = normalized this
Definition: Vec3.h:366
math::Ray< double > mRay
Definition: RayTracer.h:439
float ValueT
Definition: RayTracer.h:239
~LevelSetRayTracer()
Destructor.
Definition: RayTracer.h:853
void print(const ast::Node &node, const bool numberStatements=true, std::ostream &os=std::cout, const char *indent=" ")
Writes a descriptive printout of a Node hierarchy into a target stream.
virtual math::Ray< double > getRay(size_t i, size_t j, double iOffset=0.5, double jOffset=0.5) const =0
Return a Ray in world space given the pixel indices and optional offsets in the range [0...
void fill(const RGBA &rgb=RGBA(0))
Definition: RayTracer.h:295
virtual ~BaseCamera()
Definition: RayTracer.h:394
RGBA()
Definition: RayTracer.h:241
Coord Abs(const Coord &xyz)
Definition: Coord.h:515
void setEye(const Vec3Type &eye)
Definition: Ray.h:64
Film::RGBA operator()(const Vec3R &xyz, const Vec3R &, const Vec3R &) const override
Defines the interface of the virtual function that returns a RGB color.
Definition: RayTracer.h:700
MatType rotation(const Quat< typename MatType::value_type > &q, typename MatType::value_type eps=static_cast< typename MatType::value_type >(1.0e-8))
Return the rotation matrix specified by the given quaternion.
Definition: Mat.h:194
BaseShader * copy() const override
Definition: RayTracer.h:582
void operator()(const tbb::blocked_range< size_t > &range) const
Public method required by tbb::parallel_for.
Definition: RayTracer.h:1011
Definition: Math.h:907
T lengthSqr() const
Definition: Vec3.h:215
Film::RGBA operator()(const Vec3R &xyz, const Vec3R &normal, const Vec3R &) const override
Defines the interface of the virtual function that returns a RGB color.
Definition: RayTracer.h:623
Accelerated intersection of a ray with a narrow-band level set or a generic (e.g. density) volume...
MatteShader(const GridT &grid)
Definition: RayTracer.h:573
size_t numPixels() const
Definition: RayTracer.h:365
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:101
Definition: RayTracer.h:505
Abstract base class for the shaders.
Definition: RayTracer.h:546
BaseShader * copy() const override
Definition: RayTracer.h:683
void render(bool threaded=true) const
Perform the actual (potentially multithreaded) volume rendering.
Definition: RayTracer.h:1003
A general linear transform using homogeneous coordinates to perform rotation, scaling, shear and translation.
Definition: Maps.h:309
typename GridType::ValueType ValueType
Definition: RayTracer.h:161
void operator()(const tbb::blocked_range< size_t > &range) const
Public method required by tbb::parallel_for.
Definition: RayTracer.h:919
void lookAt(const Vec3R &xyz, const Vec3R &up=Vec3R(0.0, 1.0, 0.0))
Definition: RayTracer.h:405
Simple diffuse Lambertian surface shader.
Definition: RayTracer.h:724
const RGBA & pixel(size_t w, size_t h) const
Definition: RayTracer.h:281
math::Ray< double > getRay(size_t i, size_t j, double iOffset=0.5, double jOffset=0.5) const override
Return a Ray in world space given the pixel indices and optional offsets in the range [0...
Definition: RayTracer.h:531
size_t width() const
Definition: RayTracer.h:363
void render(bool threaded=true) const
Perform the actual (potentially multithreaded) ray-tracing.
Definition: RayTracer.h:911
Definition: openvdb/Exceptions.h:13
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:809
void setPrimaryStep(Real primaryStep)
Set the integration step-size in voxel units for the primay ray.
Definition: RayTracer.h:191
NormalShader(const GridT &grid)
Definition: RayTracer.h:620
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:791
Definition: Math.h:905
Axis-aligned bounding box.
Definition: BBox.h:23
typename GridType::ConstAccessor AccessorType
Definition: RayTracer.h:162
void setLightGain(Real gain)
Set parameter that imitates multi-scattering. A value of zero implies no multi-scattering.
Definition: RayTracer.h:204
void setGrid(const GridT &grid)
Set the level set grid to be ray-traced.
Definition: RayTracer.h:860
void initRay(double t0, double t1)
Definition: RayTracer.h:430
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:462
Abstract base class for the perspective and orthographic cameras.
Definition: RayTracer.h:377
RGBA(double _r, double _g, double _b, double _a=1.0)
Definition: RayTracer.h:246
void setCamera(BaseCamera &camera)
Set the camera derived from the abstract BaseCamera class.
Definition: RayTracer.h:177
void savePPM(const std::string &fileName)
Definition: RayTracer.h:306
void over(const RGBA &rhs)
Definition: RayTracer.h:258
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 than one implies a...
Definition: RayTracer.h:892
BaseShader * copy() const override
Definition: RayTracer.h:705
double mScaleWidth
Definition: RayTracer.h:438
A (very) simple multithreaded ray tracer specifically for narrow-band level sets. ...
Definition: RayTracer.h:78
Film::RGBA operator()(const Vec3R &xyz, const Vec3R &, const Vec3R &) const override
Defines the interface of the virtual function that returns a RGB color.
Definition: RayTracer.h:676
typename IntersectorT::RayType RayType
Definition: RayTracer.h:83
void setAbsorption(Real x, Real y, Real z)
Set absorption coefficients.
Definition: RayTracer.h:200
size_t height() const
Definition: RayTracer.h:399
Vec3< T > unit(T eps=0) const
return normalized this, throws if null vector
Definition: Vec3.h:378
void checkerboard(const RGBA &c1=RGBA(0.3f), const RGBA &c2=RGBA(0.6f), size_t size=32)
Definition: RayTracer.h:296
Floating-point RGBA components in the range [0, 1].
Definition: RayTracer.h:237
DiffuseShader(const GridT &grid)
Definition: RayTracer.h:727
ValueT a
Definition: RayTracer.h:267
RGBA(ValueT intensity)
Definition: RayTracer.h:242
Definition: openvdb/Exceptions.h:65
math::AffineMap mScreenToWorld
Definition: RayTracer.h:440
Color shader that treats the surface normal (x, y, z) as an RGB color.
Definition: RayTracer.h:617
typename IntersectorT::GridType GridType
Definition: RayTracer.h:159
void setCamera(BaseCamera &camera)
Set the camera derived from the abstract BaseCamera class.
Definition: RayTracer.h:884
NormalShader(const Film::RGBA &c=Film::RGBA(1.0f))
Definition: RayTracer.h:641
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:868
Mat3< typename promote< T0, T1 >::type > operator*(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Multiply m0 by m1 and return the resulting matrix.
Definition: Mat3.h:611
MatteShader(const Film::RGBA &c=Film::RGBA(1.0f))
Definition: RayTracer.h:594
PositionShader(const math::BBox< Vec3R > &bbox, const Film::RGBA &c=Film::RGBA(1.0f))
Definition: RayTracer.h:696
Shader that produces a simple matte.
Definition: RayTracer.h:570
Film::RGBA operator()(const Vec3R &xyz, const Vec3R &, const Vec3R &) const override
Defines the interface of the virtual function that returns a RGB color.
Definition: RayTracer.h:576
Film::RGBA operator()(const Vec3R &, const Vec3R &, const Vec3R &) const override
Defines the interface of the virtual function that returns a RGB color.
Definition: RayTracer.h:597
RGBA(ValueT _r, ValueT _g, ValueT _b, ValueT _a=static_cast< ValueT >(1.0))
Definition: RayTracer.h:243
const std::enable_if<!VecTraits< T >::IsVec, T >::type & min(const T &a, const T &b)
Definition: Composite.h:103
void print(std::ostream &os=std::cout, int verboseLevel=1)
Print parameters, statistics, memory usage and other information.
Definition: RayTracer.h:978
void postTranslate(const Vec3< T0 > &tr)
Right multiplies by the specified translation matrix, i.e. (*this) * Trans.
Definition: Mat4.h:728
Definition: axparser.h:75
Film::RGBA & pixel(size_t i, size_t j)
Definition: RayTracer.h:396
MatType unit(const MatType &mat, typename MatType::value_type eps=1.0e-8)
Return a copy of the given matrix with its upper 3×3 rows normalized.
Definition: Mat.h:670
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:153
Film(size_t width, size_t height)
Definition: RayTracer.h:271
void setScattering(Real x, Real y, Real z)
Set Scattering coefficients.
Definition: RayTracer.h:197
Definition: Math.h:906
A Ray class.
void setLightColor(Real r, Real g, Real b)
Set the color of the directional light source.
Definition: RayTracer.h:188
ValueT g
Definition: RayTracer.h:267
T dot(const Vec3< T > &v) const
Dot product.
Definition: Vec3.h:195
Definition: Transform.h:39
BaseShader * copy() const override
Definition: RayTracer.h:739
Vec3R rasterToScreen(double i, double j, double z) const
Definition: RayTracer.h:417
typename IntersectorT::RayType RayType
Definition: RayTracer.h:160
A (very) simple multithreaded volume render specifically for scalar density.
Definition: RayTracer.h:155
BaseShader * copy() const override
Definition: RayTracer.h:648
math::Vec3< Real > Vec3R
Definition: openvdb/Types.h:50
typename IntersectorT::Vec3Type Vec3Type
Definition: RayTracer.h:82
void scaleTimes(RealT scale)
Definition: Ray.h:84
Definition: Interpolation.h:96
Color shader that treats position (x, y, z) as an RGB color in a cube defined from an axis-aligned bo...
Definition: RayTracer.h:664
Film::RGBA operator()(const Vec3R &xyz, const Vec3R &normal, const Vec3R &rayDir) const override
Defines the interface of the virtual function that returns a RGB color.
Definition: RayTracer.h:730
DiffuseShader(const Film::RGBA &d=Film::RGBA(1.0f))
Definition: RayTracer.h:751
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:520