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