18#ifndef OPENVDB_TOOLS_RAYTRACER_HAS_BEEN_INCLUDED
19#define OPENVDB_TOOLS_RAYTRACER_HAS_BEEN_INCLUDED
48template<
typename Gr
idT>
52 size_t pixelSamples = 1,
53 unsigned int seed = 0,
54 bool threaded =
true);
57template<
typename Gr
idT,
typename IntersectorT>
62 size_t pixelSamples = 1,
63 unsigned int seed = 0,
64 bool threaded =
true);
71template<
typename Gr
idT,
typename IntersectorT = tools::LevelSetRayIntersector<Gr
idT> >
76 using Vec3Type =
typename IntersectorT::Vec3Type;
77 using RayType =
typename IntersectorT::RayType;
83 size_t pixelSamples = 1,
84 unsigned int seed = 0);
91 size_t pixelSamples = 1,
92 unsigned int seed = 0);
101 void setGrid(
const GridT& grid);
130 void operator()(
const tbb::blocked_range<size_t>& range)
const;
133 const bool mIsMaster;
136 std::unique_ptr<const BaseShader> mShader;
148template <
typename IntersectorT,
typename SamplerT = tools::BoxSampler>
154 using RayType =
typename IntersectorT::RayType;
158 static_assert(std::is_floating_point<ValueType>::value,
159 "VolumeRender requires a floating-point-valued grid");
175 void setIntersector(
const IntersectorT& inter);
207 void print(std::ostream& os = std::cout,
int verboseLevel = 1);
211 void operator()(
const tbb::blocked_range<size_t>& range)
const;
215 AccessorType mAccessor;
217 std::unique_ptr<IntersectorT> mPrimary, mShadow;
218 Real mPrimaryStep, mShadowStep, mCutOff, mLightGain;
219 Vec3R mLightDir, mLightColor, mAbsorption, mScattering;
236 explicit RGBA(
ValueT intensity) :
r(intensity),
g(intensity),
b(intensity),
a(1) {}
238 r(_r),
g(_g),
b(_b),
a(_a)
240 RGBA(
double _r,
double _g,
double _b,
double _a = 1.0)
254 const float s = rhs.
a*(1.0f-
a);
279 return mPixels[w + h*mWidth];
286 return mPixels[w + h*mWidth];
289 void fill(
const RGBA& rgb=
RGBA(0)) {
for (
size_t i=0; i<mSize; ++i) mPixels[i] = rgb; }
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;
300 template <
typename Type =
unsigned char>
303 const size_t totalSize = mSize * (alpha ? 4 : 3);
304 std::unique_ptr<Type[]> buffer(
new Type[totalSize]);
305 Type *q = buffer.get();
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);
313 *q++ =
static_cast<Type>(255.0f*(*p).a);
321 std::string name(fileName);
322 if (name.find_last_of(
".") == std::string::npos) name.append(
".ppm");
324 std::ofstream os(name.c_str(), std::ios_base::binary);
326 std::cerr <<
"Error opening PPM file \"" << name <<
"\"" << std::endl;
331 unsigned char* tmp = buf.get();
333 os <<
"P6\n" << mWidth <<
" " << mHeight <<
"\n255\n";
334 os.write(
reinterpret_cast<const char*
>(&(*tmp)), 3 * mSize *
sizeof(
unsigned char));
337 size_t width()
const {
return mWidth; }
338 size_t height()
const {
return mHeight; }
343 size_t mWidth, mHeight, mSize;
344 std::unique_ptr<RGBA[]> mPixels;
355 double frameWidth,
double nearPlane,
double farPlane)
365 this->
initRay(nearPlane, farPlane);
382 const Vec3R dir = orig - xyz;
401 size_t i,
size_t j,
double iOffset = 0.5,
double jOffset = 0.5)
const = 0;
406 mRay.setTimes(t0, t1);
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)
453 size_t i,
size_t j,
double iOffset = 0.5,
double jOffset = 0.5)
const override
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)
506 size_t i,
size_t j,
double iOffset = 0.5,
double jOffset = 0.5)
const override
547 MatteShader(
const GridT& grid) : mAcc(grid.getAccessor()), mXform(&grid.transform()) {}
553 SamplerType::sample(mAcc, mXform->worldToIndex(xyz), v);
559 typename GridT::ConstAccessor mAcc;
564template<
typename SamplerType>
589template<
typename GridT = Film::RGBA,
594 NormalShader(
const GridT& grid) : mAcc(grid.getAccessor()), mXform(&grid.transform()) {}
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));
606 typename GridT::ConstAccessor mAcc;
611template<
typename SamplerType>
620 return mRGBA *
Film::RGBA(normal[0] + 1.0, normal[1] + 1.0, normal[2] + 1.0);
636template<
typename GridT = Film::RGBA,
643 , mInvDim(1.0/bbox.extents())
644 , mAcc(grid.getAccessor())
645 , mXform(&grid.transform())
653 SamplerType::sample(mAcc, mXform->worldToIndex(xyz), v);
654 const Vec3R rgb = (xyz - mMin) * mInvDim;
660 const Vec3R mMin, mInvDim;
661 typename GridT::ConstAccessor mAcc;
666template<
typename SamplerType>
671 : mMin(bbox.min()), mInvDim(1.0/bbox.extents()), mRGBA(c) {}
676 const Vec3R rgb = (xyz - mMin)*mInvDim;
677 return mRGBA*
Film::RGBA(rgb[0], rgb[1], rgb[2]);
682 const Vec3R mMin, mInvDim;
696template<
typename GridT = Film::RGBA,
701 DiffuseShader(
const GridT& grid): mAcc(grid.getAccessor()), mXform(&grid.transform()) {}
707 SamplerType::sample(mAcc, mXform->worldToIndex(xyz), v);
716 typename GridT::ConstAccessor mAcc;
721template <
typename SamplerType>
750template<
typename Gr
idT>
759 tracer(grid, shader, camera, pixelSamples, seed);
764template<
typename Gr
idT,
typename IntersectorT>
766 const IntersectorT& inter,
781template<
typename Gr
idT,
typename IntersectorT>
791 mShader(shader.copy()),
797template<
typename Gr
idT,
typename IntersectorT>
807 mShader(shader.copy()),
813template<
typename Gr
idT,
typename IntersectorT>
818 mInter(other.mInter),
819 mShader(other.mShader->copy()),
820 mCamera(other.mCamera),
821 mSubPixels(other.mSubPixels)
825template<
typename Gr
idT,
typename IntersectorT>
829 if (mIsMaster)
delete [] mRand;
832template<
typename Gr
idT,
typename IntersectorT>
837 mInter = IntersectorT(grid);
840template<
typename Gr
idT,
typename IntersectorT>
848template<
typename Gr
idT,
typename IntersectorT>
853 mShader.reset(shader.
copy());
856template<
typename Gr
idT,
typename IntersectorT>
864template<
typename Gr
idT,
typename IntersectorT>
869 if (pixelSamples == 0) {
872 mSubPixels = pixelSamples - 1;
874 if (mSubPixels > 0) {
875 mRand =
new double[16];
877 for (
size_t i=0; i<16; ++i) mRand[i] = rand();
883template<
typename Gr
idT,
typename IntersectorT>
887 tbb::blocked_range<size_t> range(0, mCamera->height());
888 threaded ? tbb::parallel_for(range, *
this) : (*this)(range);
891template<
typename Gr
idT,
typename IntersectorT>
893operator()(
const tbb::blocked_range<size_t>& range)
const
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) {
901 RayType ray = mCamera->getRay(i, j);
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;
914template<
typename IntersectorT,
typename SampleT>
917 : mAccessor(inter.grid().getConstAccessor())
919 , mPrimary(new IntersectorT(inter))
920 , mShadow(new IntersectorT(inter))
925 , mLightDir(
Vec3R(0.3, 0.3, 0).unit())
926 , mLightColor(0.7, 0.7, 0.7)
932template<
typename IntersectorT,
typename SampleT>
935 : mAccessor(other.mAccessor)
936 , mCamera(other.mCamera)
937 , mPrimary(new IntersectorT(*(other.mPrimary)))
938 , mShadow(new IntersectorT(*(other.mShadow)))
939 , mPrimaryStep(other.mPrimaryStep)
940 , mShadowStep(other.mShadowStep)
941 , mCutOff(other.mCutOff)
942 , mLightGain(other.mLightGain)
943 , mLightDir(other.mLightDir)
944 , mLightColor(other.mLightColor)
945 , mAbsorption(other.mAbsorption)
946 , mScattering(other.mScattering)
950template<
typename IntersectorT,
typename SampleT>
952print(std::ostream& os,
int verboseLevel)
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;
964 mPrimary->print(os, verboseLevel);
967template<
typename IntersectorT,
typename SampleT>
971 mPrimary.reset(
new IntersectorT(inter));
972 mShadow.reset(
new IntersectorT(inter));
975template<
typename IntersectorT,
typename SampleT>
979 tbb::blocked_range<size_t> range(0, mCamera->height());
980 threaded ? tbb::parallel_for(range, *
this) : (*this)(range);
983template<
typename IntersectorT,
typename SampleT>
985operator()(
const tbb::blocked_range<size_t>& range)
const
987 SamplerType sampler(mAccessor, mShadow->grid().transform());
990 const Vec3R extinction = -mScattering-mAbsorption, One(1.0);
991 const Vec3R albedo = mLightColor*mScattering/(mScattering+mAbsorption);
992 const Real sGain = mLightGain;
993 const Real pStep = mPrimaryStep;
994 const Real sStep = mShadowStep;
995 const Real cutoff = mCutOff;
1004 std::vector<typename RayType::TimeSpan> pTS, sTS;
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) {
1012 bg.
a = bg.
r = bg.
g = bg.
b = 0;
1013 RayType pRay = mCamera->getRay(i, j);
1014 if( !mPrimary->setWorldRay(pRay))
continue;
1015 Vec3R pTrans(1.0), pLumi(0.0);
1018 while (mPrimary->march(pT0, pT1)) {
1019 for (
Real pT = pStep*ceil(pT0/pStep); pT <= pT1; pT += pStep) {
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) {
1026 Vec3R pPos = mPrimary->getWorldPos(pT);
1028 if (density < cutoff)
continue;
1032 if( !mShadow->setWorldRay(sRay))
continue;
1035 while (mShadow->march(sT0, sT1)) {
1036 for (
Real sT = sStep*ceil(sT0/sStep); sT <= sT1; sT+= sStep) {
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) {
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;
1050 pLumi += albedo * sTrans * pTrans * (One-dT);
1052 if (pTrans.lengthSqr()<cutoff)
goto Pixel;
1070#ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION
1072#ifdef OPENVDB_INSTANTIATE_RAYTRACER
1076#define _FUNCTION(TreeT) \
1077 void rayTrace(const Grid<TreeT>&, const BaseShader&, BaseCamera&, size_t, unsigned int, bool)
1081#define _FUNCTION(TreeT) \
1082 void rayTrace(const Grid<TreeT>&, const tools::LevelSetRayIntersector<Grid<TreeT>>&, const BaseShader&, BaseCamera&, size_t, unsigned int, bool)
#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
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
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
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
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
#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