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