OpenVDB  12.0.0
RayTracer.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: Apache-2.0
3 
4 /// @file RayTracer.h
5 ///
6 /// @author Ken Museth
7 ///
8 /// @brief Defines two simple but multithreaded renders, a level-set
9 /// ray tracer and a volume render. To support these renders we also define
10 /// perspective and orthographic cameras (both designed to mimic a Houdini camera),
11 /// a Film class and some rather naive shaders.
12 ///
13 /// @note These classes are included mainly as reference implementations for
14 /// ray-tracing of OpenVDB volumes. In other words they are not intended for
15 /// production-quality rendering, but could be used for fast pre-visualization
16 /// or as a starting point for a more serious render.
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 <openvdb/util/Assert.h>
28 #include <openvdb/openvdb.h>
29 #include <deque>
30 #include <iostream>
31 #include <fstream>
32 #include <limits>
33 #include <memory>
34 #include <string>
35 #include <type_traits>
36 #include <vector>
37 
38 namespace openvdb {
40 namespace OPENVDB_VERSION_NAME {
41 namespace tools {
42 
43 // Forward declarations
44 class BaseCamera;
45 class BaseShader;
46 
47 /// @brief Ray-trace a volume.
48 template<typename GridT>
49 void rayTrace(const GridT&,
50  const BaseShader&,
51  BaseCamera&,
52  size_t pixelSamples = 1,
53  unsigned int seed = 0,
54  bool threaded = true);
55 
56 /// @brief Ray-trace a volume using a given ray intersector.
57 template<typename GridT, typename IntersectorT>
58 void rayTrace(const GridT&,
59  const IntersectorT&,
60  const BaseShader&,
61  BaseCamera&,
62  size_t pixelSamples = 1,
63  unsigned int seed = 0,
64  bool threaded = true);
65 
66 
67 ///////////////////////////////LEVEL SET RAY TRACER ///////////////////////////////////////
68 
69 /// @brief A (very) simple multithreaded ray tracer specifically for narrow-band level sets.
70 /// @details Included primarily as a reference implementation.
71 template<typename GridT, typename IntersectorT = tools::LevelSetRayIntersector<GridT> >
73 {
74 public:
75  using GridType = GridT;
76  using Vec3Type = typename IntersectorT::Vec3Type;
77  using RayType = typename IntersectorT::RayType;
78 
79  /// @brief Constructor based on an instance of the grid to be rendered.
80  LevelSetRayTracer(const GridT& grid,
81  const BaseShader& shader,
82  BaseCamera& camera,
83  size_t pixelSamples = 1,
84  unsigned int seed = 0);
85 
86  /// @brief Constructor based on an instance of the intersector
87  /// performing the ray-intersections.
88  LevelSetRayTracer(const IntersectorT& inter,
89  const BaseShader& shader,
90  BaseCamera& camera,
91  size_t pixelSamples = 1,
92  unsigned int seed = 0);
93 
94  /// @brief Copy constructor
96 
97  /// @brief Destructor
99 
100  /// @brief Set the level set grid to be ray-traced
101  void setGrid(const GridT& grid);
102 
103  /// @brief Set the intersector that performs the actual
104  /// intersection of the rays against the narrow-band level set.
105  void setIntersector(const IntersectorT& inter);
106 
107  /// @brief Set the shader derived from the abstract BaseShader class.
108  ///
109  /// @note The shader is not assumed to be thread-safe so each
110  /// thread will get its only deep copy. For instance it could
111  /// contains a ValueAccessor into another grid with auxiliary
112  /// shading information. Thus, make sure it is relatively
113  /// light-weight and efficient to copy (which is the case for ValueAccesors).
114  void setShader(const BaseShader& shader);
115 
116  /// @brief Set the camera derived from the abstract BaseCamera class.
117  void setCamera(BaseCamera& camera);
118 
119  /// @brief Set the number of pixel samples and the seed for
120  /// jittered sub-rays. A value larger than one implies
121  /// anti-aliasing by jittered super-sampling.
122  /// @throw ValueError if pixelSamples is equal to zero.
123  void setPixelSamples(size_t pixelSamples, unsigned int seed = 0);
124 
125  /// @brief Perform the actual (potentially multithreaded) ray-tracing.
126  void render(bool threaded = true) const;
127 
128  /// @brief Public method required by tbb::parallel_for.
129  /// @warning Never call it directly.
130  void operator()(const tbb::blocked_range<size_t>& range) const;
131 
132 private:
133  const bool mIsMaster;
134  double* mRand;
135  IntersectorT mInter;
136  std::unique_ptr<const BaseShader> mShader;
137  BaseCamera* mCamera;
138  size_t mSubPixels;
139 };// LevelSetRayTracer
140 
141 
142 ///////////////////////////////VOLUME RENDER ///////////////////////////////////////
143 
144 /// @brief A (very) simple multithreaded volume render specifically for scalar density.
145 /// @details Included primarily as a reference implementation.
146 /// @note It will only compile if the IntersectorT is templated on a Grid with a
147 /// floating-point voxel type.
148 template <typename IntersectorT, typename SamplerT = tools::BoxSampler>
150 {
151 public:
152 
154  using RayType = typename IntersectorT::RayType;
155  using ValueType = typename GridType::ValueType;
156  using AccessorType = typename GridType::ConstAccessor;
158  static_assert(std::is_floating_point<ValueType>::value,
159  "VolumeRender requires a floating-point-valued grid");
160 
161  /// @brief Constructor taking an intersector and a base camera.
162  VolumeRender(const IntersectorT& inter, BaseCamera& camera);
163 
164  /// @brief Copy constructor which creates a thread-safe clone
165  VolumeRender(const VolumeRender& other);
166 
167  /// @brief Perform the actual (potentially multithreaded) volume rendering.
168  void render(bool threaded=true) const;
169 
170  /// @brief Set the camera derived from the abstract BaseCamera class.
171  void setCamera(BaseCamera& camera) { mCamera = &camera; }
172 
173  /// @brief Set the intersector that performs the actual
174  /// intersection of the rays against the volume.
175  void setIntersector(const IntersectorT& inter);
176 
177  /// @brief Set the vector components of a directional light source
178  /// @throw ArithmeticError if input is a null vector.
179  void setLightDir(Real x, Real y, Real z) { mLightDir = Vec3R(x,y,z).unit(); }
180 
181  /// @brief Set the color of the directional light source.
182  void setLightColor(Real r, Real g, Real b) { mLightColor = Vec3R(r,g,b); }
183 
184  /// @brief Set the integration step-size in voxel units for the primay ray.
185  void setPrimaryStep(Real primaryStep) { mPrimaryStep = primaryStep; }
186 
187  /// @brief Set the integration step-size in voxel units for the primay ray.
188  void setShadowStep(Real shadowStep) { mShadowStep = shadowStep; }
189 
190  /// @brief Set Scattering coefficients.
191  void setScattering(Real x, Real y, Real z) { mScattering = Vec3R(x,y,z); }
192 
193  /// @brief Set absorption coefficients.
194  void setAbsorption(Real x, Real y, Real z) { mAbsorption = Vec3R(x,y,z); }
195 
196  /// @brief Set parameter that imitates multi-scattering. A value
197  /// of zero implies no multi-scattering.
198  void setLightGain(Real gain) { mLightGain = gain; }
199 
200  /// @brief Set the cut-off value for density and transmittance.
201  void setCutOff(Real cutOff) { mCutOff = cutOff; }
202 
203  /// @brief Print parameters, statistics, memory usage and other information.
204  /// @param os a stream to which to write textual information
205  /// @param verboseLevel 1: print parameters only; 2: include grid
206  /// statistics; 3: include memory usage
207  void print(std::ostream& os = std::cout, int verboseLevel = 1);
208 
209  /// @brief Public method required by tbb::parallel_for.
210  /// @warning Never call it directly.
211  void operator()(const tbb::blocked_range<size_t>& range) const;
212 
213 private:
214 
215  AccessorType mAccessor;
216  BaseCamera* mCamera;
217  std::unique_ptr<IntersectorT> mPrimary, mShadow;
218  Real mPrimaryStep, mShadowStep, mCutOff, mLightGain;
219  Vec3R mLightDir, mLightColor, mAbsorption, mScattering;
220 };//VolumeRender
221 
222 //////////////////////////////////////// FILM ////////////////////////////////////////
223 
224 /// @brief A simple class that allows for concurrent writes to pixels in an image,
225 /// background initialization of the image, and PPM file output.
226 class Film
227 {
228 public:
229  /// @brief Floating-point RGBA components in the range [0, 1].
230  /// @details This is our preferred representation for color processing.
231  struct RGBA
232  {
233  using ValueT = float;
234 
235  RGBA() : r(0), g(0), b(0), a(1) {}
236  explicit RGBA(ValueT intensity) : r(intensity), g(intensity), b(intensity), a(1) {}
237  RGBA(ValueT _r, ValueT _g, ValueT _b, ValueT _a = static_cast<ValueT>(1.0)):
238  r(_r), g(_g), b(_b), a(_a)
239  {}
240  RGBA(double _r, double _g, double _b, double _a = 1.0)
241  : r(static_cast<ValueT>(_r))
242  , g(static_cast<ValueT>(_g))
243  , b(static_cast<ValueT>(_b))
244  , a(static_cast<ValueT>(_a))
245  {}
246 
247  RGBA operator* (ValueT scale) const { return RGBA(r*scale, g*scale, b*scale);}
248  RGBA operator+ (const RGBA& rhs) const { return RGBA(r+rhs.r, g+rhs.g, b+rhs.b);}
249  RGBA operator* (const RGBA& rhs) const { return RGBA(r*rhs.r, g*rhs.g, b*rhs.b);}
250  RGBA& operator+=(const RGBA& rhs) { r+=rhs.r; g+=rhs.g; b+=rhs.b; a+=rhs.a; return *this;}
251 
252  void over(const RGBA& rhs)
253  {
254  const float s = rhs.a*(1.0f-a);
255  r = a*r+s*rhs.r;
256  g = a*g+s*rhs.g;
257  b = a*b+s*rhs.b;
258  a = a + s;
259  }
260 
261  ValueT r, g, b, a;
262  };
263 
264 
265  Film(size_t width, size_t height)
266  : mWidth(width), mHeight(height), mSize(width*height), mPixels(new RGBA[mSize])
267  {
268  }
269  Film(size_t width, size_t height, const RGBA& bg)
270  : mWidth(width), mHeight(height), mSize(width*height), mPixels(new RGBA[mSize])
271  {
272  this->fill(bg);
273  }
274 
275  const RGBA& pixel(size_t w, size_t h) const
276  {
277  OPENVDB_ASSERT(w < mWidth);
278  OPENVDB_ASSERT(h < mHeight);
279  return mPixels[w + h*mWidth];
280  }
281 
282  RGBA& pixel(size_t w, size_t h)
283  {
284  OPENVDB_ASSERT(w < mWidth);
285  OPENVDB_ASSERT(h < mHeight);
286  return mPixels[w + h*mWidth];
287  }
288 
289  void fill(const RGBA& rgb=RGBA(0)) { for (size_t i=0; i<mSize; ++i) mPixels[i] = rgb; }
290  void checkerboard(const RGBA& c1=RGBA(0.3f), const RGBA& c2=RGBA(0.6f), size_t size=32)
291  {
292  RGBA *p = mPixels.get();
293  for (size_t j = 0; j < mHeight; ++j) {
294  for (size_t i = 0; i < mWidth; ++i, ++p) {
295  *p = ((i & size) ^ (j & size)) ? c1 : c2;
296  }
297  }
298  }
299 
300  template <typename Type = unsigned char>
301  std::unique_ptr<Type[]> convertToBitBuffer(const bool alpha = true) const
302  {
303  const size_t totalSize = mSize * (alpha ? 4 : 3);
304  std::unique_ptr<Type[]> buffer(new Type[totalSize]);
305  Type *q = buffer.get();
306  const RGBA* p = this->pixels();
307  size_t n = mSize;
308  while (n--) {
309  *q++ = static_cast<Type>(255.0f*(*p).r);
310  *q++ = static_cast<Type>(255.0f*(*p).g);
311  *q++ = static_cast<Type>(255.0f*(*p).b);
312  if(alpha)
313  *q++ = static_cast<Type>(255.0f*(*p).a);
314  ++p;
315  }
316  return buffer;
317  }
318 
319  void savePPM(const std::string& fileName)
320  {
321  std::string name(fileName);
322  if (name.find_last_of(".") == std::string::npos) name.append(".ppm");
323 
324  std::ofstream os(name.c_str(), std::ios_base::binary);
325  if (!os.is_open()) {
326  std::cerr << "Error opening PPM file \"" << name << "\"" << std::endl;
327  return;
328  }
329 
330  auto buf = this->convertToBitBuffer<unsigned char>(/*alpha=*/false);
331  unsigned char* tmp = buf.get();
332 
333  os << "P6\n" << mWidth << " " << mHeight << "\n255\n";
334  os.write(reinterpret_cast<const char*>(&(*tmp)), 3 * mSize * sizeof(unsigned char));
335  }
336 
337  size_t width() const { return mWidth; }
338  size_t height() const { return mHeight; }
339  size_t numPixels() const { return mSize; }
340  const RGBA* pixels() const { return mPixels.get(); }
341 
342 private:
343  size_t mWidth, mHeight, mSize;
344  std::unique_ptr<RGBA[]> mPixels;
345 };// Film
346 
347 
348 //////////////////////////////////////// CAMERAS ////////////////////////////////////////
349 
350 /// Abstract base class for the perspective and orthographic cameras
352 {
353 public:
354  BaseCamera(Film& film, const Vec3R& rotation, const Vec3R& translation,
355  double frameWidth, double nearPlane, double farPlane)
356  : mFilm(&film)
357  , mScaleWidth(frameWidth)
358  , mScaleHeight(frameWidth * double(film.height()) / double(film.width()))
359  {
360  OPENVDB_ASSERT(nearPlane > 0 && farPlane > nearPlane);
361  mScreenToWorld.accumPostRotation(math::X_AXIS, rotation[0] * math::pi<double>() / 180.0);
362  mScreenToWorld.accumPostRotation(math::Y_AXIS, rotation[1] * math::pi<double>() / 180.0);
363  mScreenToWorld.accumPostRotation(math::Z_AXIS, rotation[2] * math::pi<double>() / 180.0);
364  mScreenToWorld.accumPostTranslation(translation);
365  this->initRay(nearPlane, farPlane);
366  }
367 
368  virtual ~BaseCamera() {}
369 
370  Film::RGBA& pixel(size_t i, size_t j) { return mFilm->pixel(i, j); }
371 
372  size_t width() const { return mFilm->width(); }
373  size_t height() const { return mFilm->height(); }
374 
375  /// Rotate the camera so its negative z-axis points at xyz and its
376  /// y axis is in the plane of the xyz and up vectors. In other
377  /// words the camera will look at xyz and use up as the
378  /// horizontal direction.
379  void lookAt(const Vec3R& xyz, const Vec3R& up = Vec3R(0.0, 1.0, 0.0))
380  {
381  const Vec3R orig = mScreenToWorld.applyMap(Vec3R(0.0));
382  const Vec3R dir = orig - xyz;
383  try {
384  Mat4d xform = math::aim<Mat4d>(dir, up);
385  xform.postTranslate(orig);
386  mScreenToWorld = math::AffineMap(xform);
387  this->initRay(mRay.t0(), mRay.t1());
388  } catch (...) {}
389  }
390 
391  Vec3R rasterToScreen(double i, double j, double z) const
392  {
393  return Vec3R( (2 * i / double(mFilm->width()) - 1) * mScaleWidth,
394  (1 - 2 * j / double(mFilm->height())) * mScaleHeight, z );
395  }
396 
397  /// @brief Return a Ray in world space given the pixel indices and
398  /// optional offsets in the range [0, 1]. An offset of 0.5 corresponds
399  /// to the center of the pixel.
400  virtual math::Ray<double> getRay(
401  size_t i, size_t j, double iOffset = 0.5, double jOffset = 0.5) const = 0;
402 
403 protected:
404  void initRay(double t0, double t1)
405  {
406  mRay.setTimes(t0, t1);
407  mRay.setEye(mScreenToWorld.applyMap(Vec3R(0.0)));
408  mRay.setDir(mScreenToWorld.applyJacobian(Vec3R(0.0, 0.0, -1.0)));
409  }
410 
412  double mScaleWidth, mScaleHeight;
415 };// BaseCamera
416 
417 
419 {
420  public:
421  /// @brief Constructor
422  /// @param film film (i.e. image) defining the pixel resolution
423  /// @param rotation rotation in degrees of the camera in world space
424  /// (applied in x, y, z order)
425  /// @param translation translation of the camera in world-space units,
426  /// applied after rotation
427  /// @param focalLength focal length of the camera in mm
428  /// (the default of 50mm corresponds to Houdini's default camera)
429  /// @param aperture width in mm of the frame, i.e., the visible field
430  /// (the default 41.2136 mm corresponds to Houdini's default camera)
431  /// @param nearPlane depth of the near clipping plane in world-space units
432  /// @param farPlane depth of the far clipping plane in world-space units
433  ///
434  /// @details If no rotation or translation is provided, the camera is placed
435  /// at (0,0,0) in world space and points in the direction of the negative z axis.
437  const Vec3R& rotation = Vec3R(0.0),
438  const Vec3R& translation = Vec3R(0.0),
439  double focalLength = 50.0,
440  double aperture = 41.2136,
441  double nearPlane = 1e-3,
442  double farPlane = std::numeric_limits<double>::max())
443  : BaseCamera(film, rotation, translation, 0.5*aperture/focalLength, nearPlane, farPlane)
444  {
445  }
446 
447  ~PerspectiveCamera() override = default;
448 
449  /// @brief Return a Ray in world space given the pixel indices and
450  /// optional offsets in the range [0,1]. An offset of 0.5 corresponds
451  /// to the center of the pixel.
453  size_t i, size_t j, double iOffset = 0.5, double jOffset = 0.5) const override
454  {
455  math::Ray<double> ray(mRay);
456  Vec3R dir = BaseCamera::rasterToScreen(Real(i) + iOffset, Real(j) + jOffset, -1.0);
457  dir = BaseCamera::mScreenToWorld.applyJacobian(dir);
458  dir.normalize();
459  ray.scaleTimes(1.0/dir.dot(ray.dir()));
460  ray.setDir(dir);
461  return ray;
462  }
463 
464  /// @brief Return the horizontal field of view in degrees given a
465  /// focal lenth in mm and the specified aperture in mm.
466  static double focalLengthToFieldOfView(double length, double aperture)
467  {
468  return 360.0 / math::pi<double>() * atan(aperture/(2.0*length));
469  }
470  /// @brief Return the focal length in mm given a horizontal field of
471  /// view in degrees and the specified aperture in mm.
472  static double fieldOfViewToFocalLength(double fov, double aperture)
473  {
474  return aperture/(2.0*(tan(fov * math::pi<double>() / 360.0)));
475  }
476 };// PerspectiveCamera
477 
478 
480 {
481 public:
482  /// @brief Constructor
483  /// @param film film (i.e. image) defining the pixel resolution
484  /// @param rotation rotation in degrees of the camera in world space
485  /// (applied in x, y, z order)
486  /// @param translation translation of the camera in world-space units,
487  /// applied after rotation
488  /// @param frameWidth width in of the frame in world-space units
489  /// @param nearPlane depth of the near clipping plane in world-space units
490  /// @param farPlane depth of the far clipping plane in world-space units
491  ///
492  /// @details If no rotation or translation is provided, the camera is placed
493  /// at (0,0,0) in world space and points in the direction of the negative z axis.
495  const Vec3R& rotation = Vec3R(0.0),
496  const Vec3R& translation = Vec3R(0.0),
497  double frameWidth = 1.0,
498  double nearPlane = 1e-3,
499  double farPlane = std::numeric_limits<double>::max())
500  : BaseCamera(film, rotation, translation, 0.5*frameWidth, nearPlane, farPlane)
501  {
502  }
503  ~OrthographicCamera() override = default;
504 
506  size_t i, size_t j, double iOffset = 0.5, double jOffset = 0.5) const override
507  {
508  math::Ray<double> ray(mRay);
509  Vec3R eye = BaseCamera::rasterToScreen(Real(i) + iOffset, Real(j) + jOffset, 0.0);
510  ray.setEye(BaseCamera::mScreenToWorld.applyMap(eye));
511  return ray;
512  }
513 };// OrthographicCamera
514 
515 
516 //////////////////////////////////////// SHADERS ////////////////////////////////////////
517 
518 
519 /// Abstract base class for the shaders
521 {
522 public:
525  BaseShader(const BaseShader&) = default;
526  virtual ~BaseShader() = default;
527  /// @brief Defines the interface of the virtual function that returns a RGB color.
528  /// @param xyz World position of the intersection point.
529  /// @param nml Normal in world space at the intersection point.
530  /// @param dir Direction of the ray in world space.
531  virtual Film::RGBA operator()(const Vec3R& xyz, const Vec3R& nml, const Vec3R& dir) const = 0;
532  virtual BaseShader* copy() const = 0;
533 };
534 
535 
536 /// @brief Shader that produces a simple matte.
537 ///
538 /// @details The color can either be constant (if GridT =
539 /// Film::RGBA which is the default) or defined in a separate Vec3
540 /// color grid. Use SamplerType to define the order of interpolation
541 /// (default is zero order, i.e. closes-point).
542 template<typename GridT = Film::RGBA,
543  typename SamplerType = tools::PointSampler>
544 class MatteShader: public BaseShader
545 {
546 public:
547  MatteShader(const GridT& grid) : mAcc(grid.getAccessor()), mXform(&grid.transform()) {}
548  MatteShader(const MatteShader&) = default;
549  ~MatteShader() override = default;
550  Film::RGBA operator()(const Vec3R& xyz, const Vec3R&, const Vec3R&) const override
551  {
552  typename GridT::ValueType v = zeroVal<typename GridT::ValueType>();
553  SamplerType::sample(mAcc, mXform->worldToIndex(xyz), v);
554  return Film::RGBA(v[0], v[1], v[2]);
555  }
556  BaseShader* copy() const override { return new MatteShader<GridT, SamplerType>(*this); }
557 
558 private:
559  typename GridT::ConstAccessor mAcc;
560  const math::Transform* mXform;
561 };
562 
563 // Template specialization using a constant color of the material.
564 template<typename SamplerType>
565 class MatteShader<Film::RGBA, SamplerType>: public BaseShader
566 {
567 public:
568  MatteShader(const Film::RGBA& c = Film::RGBA(1.0f)): mRGBA(c) {}
569  MatteShader(const MatteShader&) = default;
570  ~MatteShader() override = default;
571  Film::RGBA operator()(const Vec3R&, const Vec3R&, const Vec3R&) const override
572  {
573  return mRGBA;
574  }
575  BaseShader* copy() const override { return new MatteShader<Film::RGBA, SamplerType>(*this); }
576 
577 private:
578  const Film::RGBA mRGBA;
579 };
580 
581 
582 /// @brief Color shader that treats the surface normal (x, y, z) as an
583 /// RGB color.
584 ///
585 /// @details The color can either be constant (if GridT =
586 /// Film::RGBA which is the default) or defined in a separate Vec3
587 /// color grid. Use SamplerType to define the order of interpolation
588 /// (default is zero order, i.e. closes-point).
589 template<typename GridT = Film::RGBA,
590  typename SamplerType = tools::PointSampler>
592 {
593 public:
594  NormalShader(const GridT& grid) : mAcc(grid.getAccessor()), mXform(&grid.transform()) {}
595  NormalShader(const NormalShader&) = default;
596  ~NormalShader() override = default;
597  Film::RGBA operator()(const Vec3R& xyz, const Vec3R& normal, const Vec3R&) const override
598  {
599  typename GridT::ValueType v = zeroVal<typename GridT::ValueType>();
600  SamplerType::sample(mAcc, mXform->worldToIndex(xyz), v);
601  return Film::RGBA(v[0]*(normal[0]+1.0), v[1]*(normal[1]+1.0), v[2]*(normal[2]+1.0));
602  }
603  BaseShader* copy() const override { return new NormalShader<GridT, SamplerType>(*this); }
604 
605 private:
606  typename GridT::ConstAccessor mAcc;
607  const math::Transform* mXform;
608 };
609 
610 // Template specialization using a constant color of the material.
611 template<typename SamplerType>
612 class NormalShader<Film::RGBA, SamplerType>: public BaseShader
613 {
614 public:
615  NormalShader(const Film::RGBA& c = Film::RGBA(1.0f)) : mRGBA(c*0.5f) {}
616  NormalShader(const NormalShader&) = default;
617  ~NormalShader() override = default;
618  Film::RGBA operator()(const Vec3R&, const Vec3R& normal, const Vec3R&) const override
619  {
620  return mRGBA * Film::RGBA(normal[0] + 1.0, normal[1] + 1.0, normal[2] + 1.0);
621  }
622  BaseShader* copy() const override { return new NormalShader<Film::RGBA, SamplerType>(*this); }
623 
624 private:
625  const Film::RGBA mRGBA;
626 };
627 
628 
629 /// @brief Color shader that treats position (x, y, z) as an RGB color in a
630 /// cube defined from an axis-aligned bounding box in world space.
631 ///
632 /// @details The color can either be constant (if GridT =
633 /// Film::RGBA which is the default) or defined in a separate Vec3
634 /// color grid. Use SamplerType to define the order of interpolation
635 /// (default is zero order, i.e. closes-point).
636 template<typename GridT = Film::RGBA,
637  typename SamplerType = tools::PointSampler>
639 {
640 public:
641  PositionShader(const math::BBox<Vec3R>& bbox, const GridT& grid)
642  : mMin(bbox.min())
643  , mInvDim(1.0/bbox.extents())
644  , mAcc(grid.getAccessor())
645  , mXform(&grid.transform())
646  {
647  }
648  PositionShader(const PositionShader&) = default;
649  ~PositionShader() override = default;
650  Film::RGBA operator()(const Vec3R& xyz, const Vec3R&, const Vec3R&) const override
651  {
652  typename GridT::ValueType v = zeroVal<typename GridT::ValueType>();
653  SamplerType::sample(mAcc, mXform->worldToIndex(xyz), v);
654  const Vec3R rgb = (xyz - mMin) * mInvDim;
655  return Film::RGBA(v[0],v[1],v[2]) * Film::RGBA(rgb[0], rgb[1], rgb[2]);
656  }
657  BaseShader* copy() const override { return new PositionShader<GridT, SamplerType>(*this); }
658 
659 private:
660  const Vec3R mMin, mInvDim;
661  typename GridT::ConstAccessor mAcc;
662  const math::Transform* mXform;
663 };
664 
665 // Template specialization using a constant color of the material.
666 template<typename SamplerType>
667 class PositionShader<Film::RGBA, SamplerType>: public BaseShader
668 {
669 public:
670  PositionShader(const math::BBox<Vec3R>& bbox, const Film::RGBA& c = Film::RGBA(1.0f))
671  : mMin(bbox.min()), mInvDim(1.0/bbox.extents()), mRGBA(c) {}
672  PositionShader(const PositionShader&) = default;
673  ~PositionShader() override = default;
674  Film::RGBA operator()(const Vec3R& xyz, const Vec3R&, const Vec3R&) const override
675  {
676  const Vec3R rgb = (xyz - mMin)*mInvDim;
677  return mRGBA*Film::RGBA(rgb[0], rgb[1], rgb[2]);
678  }
679  BaseShader* copy() const override { return new PositionShader<Film::RGBA, SamplerType>(*this); }
680 
681 private:
682  const Vec3R mMin, mInvDim;
683  const Film::RGBA mRGBA;
684 };
685 
686 
687 /// @brief Simple diffuse Lambertian surface shader.
688 ///
689 /// @details The diffuse color can either be constant (if GridT =
690 /// Film::RGBA which is the default) or defined in a separate Vec3
691 /// color grid. Lambertian implies that the (radiant) intensity is
692 /// directly proportional to the cosine of the angle between the
693 /// surface normal and the direction of the light source. Use
694 /// SamplerType to define the order of interpolation (default is
695 /// zero order, i.e. closes-point).
696 template<typename GridT = Film::RGBA,
697  typename SamplerType = tools::PointSampler>
699 {
700 public:
701  DiffuseShader(const GridT& grid): mAcc(grid.getAccessor()), mXform(&grid.transform()) {}
702  DiffuseShader(const DiffuseShader&) = default;
703  ~DiffuseShader() override = default;
704  Film::RGBA operator()(const Vec3R& xyz, const Vec3R& normal, const Vec3R& rayDir) const override
705  {
706  typename GridT::ValueType v = zeroVal<typename GridT::ValueType>();
707  SamplerType::sample(mAcc, mXform->worldToIndex(xyz), v);
708  // We take the abs of the dot product corresponding to having
709  // light sources at +/- rayDir, i.e., two-sided shading.
710  return Film::RGBA(v[0],v[1],v[2])
711  * static_cast<Film::RGBA::ValueT>(math::Abs(normal.dot(rayDir)));
712  }
713  BaseShader* copy() const override { return new DiffuseShader<GridT, SamplerType>(*this); }
714 
715 private:
716  typename GridT::ConstAccessor mAcc;
717  const math::Transform* mXform;
718 };
719 
720 // Template specialization using a constant color of the material.
721 template <typename SamplerType>
722 class DiffuseShader<Film::RGBA, SamplerType>: public BaseShader
723 {
724 public:
725  DiffuseShader(const Film::RGBA& d = Film::RGBA(1.0f)): mRGBA(d) {}
726  DiffuseShader(const DiffuseShader&) = default;
727  ~DiffuseShader() override = default;
728  Film::RGBA operator()(const Vec3R&, const Vec3R& normal, const Vec3R& rayDir) const override
729  {
730  // We assume a single directional light source at the camera,
731  // so the cosine of the angle between the surface normal and the
732  // direction of the light source becomes the dot product of the
733  // surface normal and inverse direction of the ray. We also ignore
734  // negative dot products, corresponding to strict one-sided shading.
735  //return mRGBA * math::Max(0.0, normal.dot(-rayDir));
736 
737  // We take the abs of the dot product corresponding to having
738  // light sources at +/- rayDir, i.e., two-sided shading.
739  return mRGBA * static_cast<Film::RGBA::ValueT>(math::Abs(normal.dot(rayDir)));
740  }
741  BaseShader* copy() const override { return new DiffuseShader<Film::RGBA, SamplerType>(*this); }
742 
743 private:
744  const Film::RGBA mRGBA;
745 };
746 
747 
748 //////////////////////////////////////// RAYTRACER ////////////////////////////////////////
749 
750 template<typename GridT>
751 void rayTrace(const GridT& grid,
752  const BaseShader& shader,
753  BaseCamera& camera,
754  size_t pixelSamples,
755  unsigned int seed,
756  bool threaded)
757 {
759  tracer(grid, shader, camera, pixelSamples, seed);
760  tracer.render(threaded);
761 }
762 
763 
764 template<typename GridT, typename IntersectorT>
765 void rayTrace(const GridT&,
766  const IntersectorT& inter,
767  const BaseShader& shader,
768  BaseCamera& camera,
769  size_t pixelSamples,
770  unsigned int seed,
771  bool threaded)
772 {
773  LevelSetRayTracer<GridT, IntersectorT> tracer(inter, shader, camera, pixelSamples, seed);
774  tracer.render(threaded);
775 }
776 
777 
778 //////////////////////////////////////// LevelSetRayTracer ////////////////////////////////////////
779 
780 
781 template<typename GridT, typename IntersectorT>
783 LevelSetRayTracer(const GridT& grid,
784  const BaseShader& shader,
785  BaseCamera& camera,
786  size_t pixelSamples,
787  unsigned int seed)
788  : mIsMaster(true),
789  mRand(nullptr),
790  mInter(grid),
791  mShader(shader.copy()),
792  mCamera(&camera)
793 {
794  this->setPixelSamples(pixelSamples, seed);
795 }
796 
797 template<typename GridT, typename IntersectorT>
799 LevelSetRayTracer(const IntersectorT& inter,
800  const BaseShader& shader,
801  BaseCamera& camera,
802  size_t pixelSamples,
803  unsigned int seed)
804  : mIsMaster(true),
805  mRand(nullptr),
806  mInter(inter),
807  mShader(shader.copy()),
808  mCamera(&camera)
809 {
810  this->setPixelSamples(pixelSamples, seed);
811 }
812 
813 template<typename GridT, typename IntersectorT>
816  mIsMaster(false),
817  mRand(other.mRand),
818  mInter(other.mInter),
819  mShader(other.mShader->copy()),
820  mCamera(other.mCamera),
821  mSubPixels(other.mSubPixels)
822 {
823 }
824 
825 template<typename GridT, typename IntersectorT>
828 {
829  if (mIsMaster) delete [] mRand;
830 }
831 
832 template<typename GridT, typename IntersectorT>
834 setGrid(const GridT& grid)
835 {
836  OPENVDB_ASSERT(mIsMaster);
837  mInter = IntersectorT(grid);
838 }
839 
840 template<typename GridT, typename IntersectorT>
842 setIntersector(const IntersectorT& inter)
843 {
844  OPENVDB_ASSERT(mIsMaster);
845  mInter = inter;
846 }
847 
848 template<typename GridT, typename IntersectorT>
850 setShader(const BaseShader& shader)
851 {
852  OPENVDB_ASSERT(mIsMaster);
853  mShader.reset(shader.copy());
854 }
855 
856 template<typename GridT, typename IntersectorT>
859 {
860  OPENVDB_ASSERT(mIsMaster);
861  mCamera = &camera;
862 }
863 
864 template<typename GridT, typename IntersectorT>
866 setPixelSamples(size_t pixelSamples, unsigned int seed)
867 {
868  OPENVDB_ASSERT(mIsMaster);
869  if (pixelSamples == 0) {
870  OPENVDB_THROW(ValueError, "pixelSamples must be larger than zero!");
871  }
872  mSubPixels = pixelSamples - 1;
873  delete [] mRand;
874  if (mSubPixels > 0) {
875  mRand = new double[16];
876  math::Rand01<double> rand(seed);//offsets for anti-aliaing by jittered super-sampling
877  for (size_t i=0; i<16; ++i) mRand[i] = rand();
878  } else {
879  mRand = nullptr;
880  }
881 }
882 
883 template<typename GridT, typename IntersectorT>
885 render(bool threaded) const
886 {
887  tbb::blocked_range<size_t> range(0, mCamera->height());
888  threaded ? tbb::parallel_for(range, *this) : (*this)(range);
889 }
890 
891 template<typename GridT, typename IntersectorT>
893 operator()(const tbb::blocked_range<size_t>& range) const
894 {
895  const BaseShader& shader = *mShader;
896  Vec3Type xyz, nml;
897  const float frac = 1.0f / (1.0f + float(mSubPixels));
898  for (size_t j=range.begin(), n=0, je = range.end(); j<je; ++j) {
899  for (size_t i=0, ie = mCamera->width(); i<ie; ++i) {
900  Film::RGBA& bg = mCamera->pixel(i,j);
901  RayType ray = mCamera->getRay(i, j);//primary ray
902  Film::RGBA c = mInter.intersectsWS(ray, xyz, nml) ? shader(xyz, nml, ray.dir()) : bg;
903  for (size_t k=0; k<mSubPixels; ++k, n +=2 ) {
904  ray = mCamera->getRay(i, j, mRand[n & 15], mRand[(n+1) & 15]);
905  c += mInter.intersectsWS(ray, xyz, nml) ? shader(xyz, nml, ray.dir()) : bg;
906  }//loop over sub-pixels
907  bg = c*frac;
908  }//loop over image height
909  }//loop over image width
910 }
911 
912 //////////////////////////////////////// VolumeRender ////////////////////////////////////////
913 
914 template<typename IntersectorT, typename SampleT>
916 VolumeRender(const IntersectorT& inter, BaseCamera& camera)
917  : mAccessor(inter.grid().getConstAccessor())
918  , mCamera(&camera)
919  , mPrimary(new IntersectorT(inter))
920  , mShadow(new IntersectorT(inter))
921  , mPrimaryStep(1.0)
922  , mShadowStep(3.0)
923  , mCutOff(0.005)
924  , mLightGain(0.2)
925  , mLightDir(Vec3R(0.3, 0.3, 0).unit())
926  , mLightColor(0.7, 0.7, 0.7)
927  , mAbsorption(0.1)
928  , mScattering(1.5)
929 {
930 }
931 
932 template<typename IntersectorT, typename SampleT>
935  : mAccessor(other.mAccessor)
936  , mCamera(other.mCamera)
937  , mPrimary(new IntersectorT(*(other.mPrimary)))
938  , mShadow(new IntersectorT(*(other.mShadow)))
939  , mPrimaryStep(other.mPrimaryStep)
940  , mShadowStep(other.mShadowStep)
941  , mCutOff(other.mCutOff)
942  , mLightGain(other.mLightGain)
943  , mLightDir(other.mLightDir)
944  , mLightColor(other.mLightColor)
945  , mAbsorption(other.mAbsorption)
946  , mScattering(other.mScattering)
947 {
948 }
949 
950 template<typename IntersectorT, typename SampleT>
952 print(std::ostream& os, int verboseLevel)
953 {
954  if (verboseLevel>0) {
955  os << "\nPrimary step: " << mPrimaryStep
956  << "\nShadow step: " << mShadowStep
957  << "\nCutoff: " << mCutOff
958  << "\nLightGain: " << mLightGain
959  << "\nLightDir: " << mLightDir
960  << "\nLightColor: " << mLightColor
961  << "\nAbsorption: " << mAbsorption
962  << "\nScattering: " << mScattering << std::endl;
963  }
964  mPrimary->print(os, verboseLevel);
965 }
966 
967 template<typename IntersectorT, typename SampleT>
969 setIntersector(const IntersectorT& inter)
970 {
971  mPrimary.reset(new IntersectorT(inter));
972  mShadow.reset( new IntersectorT(inter));
973 }
974 
975 template<typename IntersectorT, typename SampleT>
977 render(bool threaded) const
978 {
979  tbb::blocked_range<size_t> range(0, mCamera->height());
980  threaded ? tbb::parallel_for(range, *this) : (*this)(range);
981 }
982 
983 template<typename IntersectorT, typename SampleT>
985 operator()(const tbb::blocked_range<size_t>& range) const
986 {
987  SamplerType sampler(mAccessor, mShadow->grid().transform());//light-weight wrapper
988 
989  // Any variable prefixed with p (or s) means it's associated with a primary (or shadow) ray
990  const Vec3R extinction = -mScattering-mAbsorption, One(1.0);
991  const Vec3R albedo = mLightColor*mScattering/(mScattering+mAbsorption);//single scattering
992  const Real sGain = mLightGain;//in-scattering along shadow ray
993  const Real pStep = mPrimaryStep;//Integration step along primary ray in voxel units
994  const Real sStep = mShadowStep;//Integration step along shadow ray in voxel units
995  const Real cutoff = mCutOff;//Cutoff for density and transmittance
996 
997  // For the sake of completeness we show how to use two different
998  // methods (hits/march) in VolumeRayIntersector that produce
999  // segments along the ray that intersects active values. Comment out
1000  // the line below to use VolumeRayIntersector::march instead of
1001  // VolumeRayIntersector::hits.
1002 #define USE_HITS
1003 #ifdef USE_HITS
1004  std::vector<typename RayType::TimeSpan> pTS, sTS;
1005  //std::deque<typename RayType::TimeSpan> pTS, sTS;
1006 #endif
1007 
1008  RayType sRay(Vec3R(0), mLightDir);//Shadow ray
1009  for (size_t j=range.begin(), je = range.end(); j<je; ++j) {
1010  for (size_t i=0, ie = mCamera->width(); i<ie; ++i) {
1011  Film::RGBA& bg = mCamera->pixel(i, j);
1012  bg.a = bg.r = bg.g = bg.b = 0;
1013  RayType pRay = mCamera->getRay(i, j);// Primary ray
1014  if( !mPrimary->setWorldRay(pRay)) continue;
1015  Vec3R pTrans(1.0), pLumi(0.0);
1016 #ifndef USE_HITS
1017  Real pT0, pT1;
1018  while (mPrimary->march(pT0, pT1)) {
1019  for (Real pT = pStep*ceil(pT0/pStep); pT <= pT1; pT += pStep) {
1020 #else
1021  mPrimary->hits(pTS);
1022  for (size_t k=0; k<pTS.size(); ++k) {
1023  Real pT = pStep*ceil(pTS[k].t0/pStep), pT1=pTS[k].t1;
1024  for (; pT <= pT1; pT += pStep) {
1025 #endif
1026  Vec3R pPos = mPrimary->getWorldPos(pT);
1027  const Real density = sampler.wsSample(pPos);
1028  if (density < cutoff) continue;
1029  const Vec3R dT = math::Exp(extinction * density * pStep);
1030  Vec3R sTrans(1.0);
1031  sRay.setEye(pPos);
1032  if( !mShadow->setWorldRay(sRay)) continue;
1033 #ifndef USE_HITS
1034  Real sT0, sT1;
1035  while (mShadow->march(sT0, sT1)) {
1036  for (Real sT = sStep*ceil(sT0/sStep); sT <= sT1; sT+= sStep) {
1037 #else
1038  mShadow->hits(sTS);
1039  for (size_t l=0; l<sTS.size(); ++l) {
1040  Real sT = sStep*ceil(sTS[l].t0/sStep), sT1=sTS[l].t1;
1041  for (; sT <= sT1; sT+= sStep) {
1042 #endif
1043  const Real d = sampler.wsSample(mShadow->getWorldPos(sT));
1044  if (d < cutoff) continue;
1045  sTrans *= math::Exp(extinction * d * sStep/(1.0+sT*sGain));
1046  if (sTrans.lengthSqr()<cutoff) goto Luminance;//Terminate sRay
1047  }//Integration over shadow segment
1048  }// Shadow ray march
1049  Luminance:
1050  pLumi += albedo * sTrans * pTrans * (One-dT);
1051  pTrans *= dT;
1052  if (pTrans.lengthSqr()<cutoff) goto Pixel; // Terminate Ray
1053  }//Integration over primary segment
1054  }// Primary ray march
1055  Pixel:
1056  bg.r = static_cast<Film::RGBA::ValueT>(pLumi[0]);
1057  bg.g = static_cast<Film::RGBA::ValueT>(pLumi[1]);
1058  bg.b = static_cast<Film::RGBA::ValueT>(pLumi[2]);
1059  bg.a = static_cast<Film::RGBA::ValueT>(1.0f - pTrans.sum()/3.0f);
1060  }//Horizontal pixel scan
1061  }//Vertical pixel scan
1062 }
1063 
1064 
1065 ////////////////////////////////////////
1066 
1067 
1068 // Explicit Template Instantiation
1069 
1070 #ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION
1071 
1072 #ifdef OPENVDB_INSTANTIATE_RAYTRACER
1074 #endif
1075 
1076 #define _FUNCTION(TreeT) \
1077  void rayTrace(const Grid<TreeT>&, const BaseShader&, BaseCamera&, size_t, unsigned int, bool)
1079 #undef _FUNCTION
1080 
1081 #define _FUNCTION(TreeT) \
1082  void rayTrace(const Grid<TreeT>&, const tools::LevelSetRayIntersector<Grid<TreeT>>&, const BaseShader&, BaseCamera&, size_t, unsigned int, bool)
1084 #undef _FUNCTION
1085 
1088 
1089 #endif // OPENVDB_USE_EXPLICIT_INSTANTIATION
1090 
1091 
1092 } // namespace tools
1093 } // namespace OPENVDB_VERSION_NAME
1094 } // namespace openvdb
1095 
1096 #endif // OPENVDB_TOOLS_RAYTRACER_HAS_BEEN_INCLUDED
BaseShader * copy() const override
Definition: RayTracer.h:575
RGBA(ValueT _r, ValueT _g, ValueT _b, ValueT _a=static_cast< ValueT >(1.0))
Definition: RayTracer.h:237
const RGBA * pixels() const
Definition: RayTracer.h:340
Vec3< T > unit(T eps=0) const
return normalized this, throws if null vector
Definition: Vec3.h:375
const Vec3T & dir() const
Definition: Ray.h:100
Vec3R rasterToScreen(double i, double j, double z) const
Definition: RayTracer.h:391
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:597
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:674
void setShader(const BaseShader &shader)
Set the shader derived from the abstract BaseShader class.
Definition: RayTracer.h:850
void setDir(const Vec3Type &dir)
Definition: Ray.h:67
Floating-point RGBA components in the range [0, 1].
Definition: RayTracer.h:231
void setScattering(Real x, Real y, Real z)
Set Scattering coefficients.
Definition: RayTracer.h:191
VolumeRender(const IntersectorT &inter, BaseCamera &camera)
Constructor taking an intersector and a base camera.
Definition: RayTracer.h:916
size_t width() const
Definition: RayTracer.h:337
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
Coord Abs(const Coord &xyz)
Definition: Coord.h:518
void operator()(const tbb::blocked_range< size_t > &range) const
Public method required by tbb::parallel_for.
Definition: RayTracer.h:985
void checkerboard(const RGBA &c1=RGBA(0.3f), const RGBA &c2=RGBA(0.6f), size_t size=32)
Definition: RayTracer.h:290
BaseCamera(Film &film, const Vec3R &rotation, const Vec3R &translation, double frameWidth, double nearPlane, double farPlane)
Definition: RayTracer.h:354
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
Mat4< double > Mat4d
Definition: Mat4.h:1355
RGBA & pixel(size_t w, size_t h)
Definition: RayTracer.h:282
Abstract base class for the shaders.
Definition: RayTracer.h:520
NormalShader(const Film::RGBA &c=Film::RGBA(1.0f))
Definition: RayTracer.h:615
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:866
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:704
Type Exp(const Type &x)
Return ex.
Definition: Math.h:710
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:728
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:783
typename IntersectorT::RayType RayType
Definition: RayTracer.h:77
RGBA(ValueT intensity)
Definition: RayTracer.h:236
void setCutOff(Real cutOff)
Set the cut-off value for density and transmittance.
Definition: RayTracer.h:201
Definition: Math.h:903
Abstract base class for the perspective and orthographic cameras.
Definition: RayTracer.h:351
Film(size_t width, size_t height)
Definition: RayTracer.h:265
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:571
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:505
A simple class that allows for concurrent writes to pixels in an image, background initialization of ...
Definition: RayTracer.h:226
PositionShader(const math::BBox< Vec3R > &bbox, const Film::RGBA &c=Film::RGBA(1.0f))
Definition: RayTracer.h:670
void render(bool threaded=true) const
Perform the actual (potentially multithreaded) ray-tracing.
Definition: RayTracer.h:885
BaseShader * copy() const override
Definition: RayTracer.h:657
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:466
ValueT b
Definition: RayTracer.h:261
BaseShader * copy() const override
Definition: RayTracer.h:603
BaseShader * copy() const override
Definition: RayTracer.h:741
Class that provides the interface for continuous sampling of values in a tree.
Definition: Interpolation.h:284
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:452
OPENVDB_AX_API 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.
GridT GridType
Definition: RayTracer.h:75
Definition: Math.h:904
Axis-aligned bounding box.
Definition: BBox.h:23
virtual BaseShader * copy() const =0
void setEye(const Vec3Type &eye)
Definition: Ray.h:65
void setLightColor(Real r, Real g, Real b)
Set the color of the directional light source.
Definition: RayTracer.h:182
Film * mFilm
Definition: RayTracer.h:411
const std::enable_if<!VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:110
math::Ray< double > mRay
Definition: RayTracer.h:413
void scaleTimes(RealT scale)
Definition: Ray.h:85
double mScaleWidth
Definition: RayTracer.h:412
PositionShader(const math::BBox< Vec3R > &bbox, const GridT &grid)
Definition: RayTracer.h:641
DiffuseShader(const GridT &grid)
Definition: RayTracer.h:701
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:597
Definition: RayTracer.h:418
Definition: Exceptions.h:65
typename IntersectorT::RayType RayType
Definition: RayTracer.h:154
bool normalize(T eps=T(1.0e-7))
this = normalized this
Definition: Vec3.h:363
Definition: Interpolation.h:120
Accelerated intersection of a ray with a narrow-band level set or a generic (e.g. density) volume...
Color shader that treats position (x, y, z) as an RGB color in a cube defined from an axis-aligned bo...
Definition: RayTracer.h:638
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:528
RGBA()
Definition: RayTracer.h:235
#define OPENVDB_ASSERT(X)
Definition: Assert.h:41
BaseShader * copy() const override
Definition: RayTracer.h:679
MatType scale(const Vec3< typename MatType::value_type > &s)
Return a matrix that scales by s.
Definition: Mat.h:615
void setCamera(BaseCamera &camera)
Set the camera derived from the abstract BaseCamera class.
Definition: RayTracer.h:858
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:650
DiffuseShader(const Film::RGBA &d=Film::RGBA(1.0f))
Definition: RayTracer.h:725
typename IntersectorT::Vec3Type Vec3Type
Definition: RayTracer.h:76
void setGrid(const GridT &grid)
Set the level set grid to be ray-traced.
Definition: RayTracer.h:834
MatteShader(const GridT &grid)
Definition: RayTracer.h:547
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:494
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:618
A (very) simple multithreaded volume render specifically for scalar density.
Definition: RayTracer.h:149
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:765
void setAbsorption(Real x, Real y, Real z)
Set absorption coefficients.
Definition: RayTracer.h:194
OutGridT XformOp bool threaded
Definition: ValueTransformer.h:140
NormalShader(const GridT &grid)
Definition: RayTracer.h:594
void setIntersector(const IntersectorT &inter)
Set the intersector that performs the actual intersection of the rays against the volume...
Definition: RayTracer.h:969
void setLightGain(Real gain)
Set parameter that imitates multi-scattering. A value of zero implies no multi-scattering.
Definition: RayTracer.h:198
void fill(const RGBA &rgb=RGBA(0))
Definition: RayTracer.h:289
float ValueT
Definition: RayTracer.h:233
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:648
RGBA & operator+=(const RGBA &rhs)
Definition: RayTracer.h:250
Definition: Exceptions.h:13
void print(std::ostream &os=std::cout, int verboseLevel=1)
Print parameters, statistics, memory usage and other information.
Definition: RayTracer.h:952
size_t numPixels() const
Definition: RayTracer.h:339
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:436
typename GridType::ValueType ValueType
Definition: RayTracer.h:155
void initRay(double t0, double t1)
Definition: RayTracer.h:404
size_t height() const
Definition: RayTracer.h:373
void savePPM(const std::string &fileName)
Definition: RayTracer.h:319
void lookAt(const Vec3R &xyz, const Vec3R &up=Vec3R(0.0, 1.0, 0.0))
Definition: RayTracer.h:379
typename GridType::ConstAccessor AccessorType
Definition: RayTracer.h:156
A (very) simple multithreaded ray tracer specifically for narrow-band level sets. ...
Definition: RayTracer.h:72
Simple generator of random numbers over the range [0, 1)
Definition: Math.h:166
void over(const RGBA &rhs)
Definition: RayTracer.h:252
BaseShader * copy() const override
Definition: RayTracer.h:622
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:550
double Real
Definition: Types.h:60
RGBA(double _r, double _g, double _b, double _a=1.0)
Definition: RayTracer.h:240
#define OPENVDB_INSTANTIATE_CLASS
Definition: version.h.in:158
void setLightDir(Real x, Real y, Real z)
Set the vector components of a directional light source.
Definition: RayTracer.h:179
void setCamera(BaseCamera &camera)
Set the camera derived from the abstract BaseCamera class.
Definition: RayTracer.h:171
const RGBA & pixel(size_t w, size_t h) const
Definition: RayTracer.h:275
Color shader that treats the surface normal (x, y, z) as an RGB color.
Definition: RayTracer.h:591
typename IntersectorT::GridType GridType
Definition: RayTracer.h:153
Shader that produces a simple matte.
Definition: RayTracer.h:544
Definition: Math.h:902
GridType
List of types that are currently supported by NanoVDB.
Definition: NanoVDB.h:219
math::AffineMap mScreenToWorld
Definition: RayTracer.h:414
ValueT a
Definition: RayTracer.h:261
BaseShader * copy() const override
Definition: RayTracer.h:713
void setShadowStep(Real shadowStep)
Set the integration step-size in voxel units for the primay ray.
Definition: RayTracer.h:188
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...
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:172
Definition: Transform.h:39
#define OPENVDB_REAL_TREE_INSTANTIATE(Function)
Definition: version.h.in:162
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:472
~LevelSetRayTracer()
Destructor.
Definition: RayTracer.h:827
void postTranslate(const Vec3< T0 > &tr)
Right multiplies by the specified translation matrix, i.e. (*this) * Trans.
Definition: Mat4.h:714
size_t width() const
Definition: RayTracer.h:372
Film::RGBA & pixel(size_t i, size_t j)
Definition: RayTracer.h:370
Simple diffuse Lambertian surface shader.
Definition: RayTracer.h:698
size_t height() const
Definition: RayTracer.h:338
A general linear transform using homogeneous coordinates to perform rotation, scaling, shear and translation.
Definition: Maps.h:295
ValueT r
Definition: RayTracer.h:261
void setPrimaryStep(Real primaryStep)
Set the integration step-size in voxel units for the primay ray.
Definition: RayTracer.h:185
MatteShader(const Film::RGBA &c=Film::RGBA(1.0f))
Definition: RayTracer.h:568
const std::enable_if<!VecTraits< T >::IsVec, T >::type & min(const T &a, const T &b)
Definition: Composite.h:106
Film(size_t width, size_t height, const RGBA &bg)
Definition: RayTracer.h:269
std::unique_ptr< Type[]> convertToBitBuffer(const bool alpha=true) const
Definition: RayTracer.h:301
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:121
virtual ~BaseCamera()
Definition: RayTracer.h:368
void operator()(const tbb::blocked_range< size_t > &range) const
Public method required by tbb::parallel_for.
Definition: RayTracer.h:893
BaseShader * copy() const override
Definition: RayTracer.h:556
T lengthSqr() const
Definition: Vec3.h:212
BaseShader()
Definition: RayTracer.h:524
T dot(const Vec3< T > &v) const
Dot product.
Definition: Vec3.h:192
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:842
math::Vec3< Real > Vec3R
Definition: Types.h:72
void render(bool threaded=true) const
Perform the actual (potentially multithreaded) volume rendering.
Definition: RayTracer.h:977
Definition: Interpolation.h:97
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:218
ValueT g
Definition: RayTracer.h:261