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