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