18 #ifndef OPENVDB_TOOLS_RAYTRACER_HAS_BEEN_INCLUDED
19 #define OPENVDB_TOOLS_RAYTRACER_HAS_BEEN_INCLUDED
34 #include <type_traits>
47 template<
typename Gr
idT>
51 size_t pixelSamples = 1,
52 unsigned int seed = 0,
53 bool threaded =
true);
56 template<
typename Gr
idT,
typename IntersectorT>
61 size_t pixelSamples = 1,
62 unsigned int seed = 0,
63 bool threaded =
true);
70 template<
typename Gr
idT,
typename IntersectorT = tools::LevelSetRayIntersector<Gr
idT> >
75 using Vec3Type =
typename IntersectorT::Vec3Type;
76 using RayType =
typename IntersectorT::RayType;
82 size_t pixelSamples = 1,
83 unsigned int seed = 0);
90 size_t pixelSamples = 1,
91 unsigned int seed = 0);
100 void setGrid(
const GridT& grid);
125 void render(
bool threaded =
true)
const;
132 const bool mIsMaster;
135 std::unique_ptr<const BaseShader> mShader;
147 template <
typename IntersectorT,
typename SamplerT = tools::BoxSampler>
153 using RayType =
typename IntersectorT::RayType;
158 "VolumeRender requires a floating-point-valued grid");
167 void render(
bool threaded=
true)
const;
206 void print(std::ostream& os = std::cout,
int verboseLevel = 1);
216 std::unique_ptr<IntersectorT> mPrimary, mShadow;
217 Real mPrimaryStep, mShadowStep, mCutOff, mLightGain;
218 Vec3R mLightDir, mLightColor, mAbsorption, mScattering;
235 explicit RGBA(
ValueT intensity) :
r(intensity),
g(intensity),
b(intensity),
a(1) {}
237 r(_r),
g(_g),
b(_b),
a(_a)
239 RGBA(
double _r,
double _g,
double _b,
double _a = 1.0)
253 const float s = rhs.
a*(1.0f-
a);
265 : mWidth(width), mHeight(height), mSize(width*height), mPixels(new
RGBA[mSize])
269 : mWidth(width), mHeight(height), mSize(width*height), mPixels(new
RGBA[mSize])
278 return mPixels[w + h*mWidth];
285 return mPixels[w + h*mWidth];
288 void fill(
const RGBA& rgb=
RGBA(0)) {
for (
size_t i=0; i<mSize; ++i) mPixels[i] = rgb; }
291 RGBA *p = mPixels.get();
292 for (
size_t j = 0;
j < mHeight; ++
j) {
293 for (
size_t i = 0; i < mWidth; ++i, ++p) {
294 *p = ((i &
size) ^ (
j &
size)) ? c1 : c2;
299 template <
typename Type =
unsigned char>
302 const size_t totalSize = mSize * (
alpha ? 4 : 3);
303 std::unique_ptr<Type[]>
buffer(
new Type[totalSize]);
304 Type *
q = buffer.get();
308 *q++ =
static_cast<Type>(255.0f*(*p).r);
309 *q++ =
static_cast<Type>(255.0f*(*p).g);
310 *q++ =
static_cast<Type>(255.0f*(*p).b);
312 *q++ =
static_cast<Type>(255.0f*(*p).a);
321 if (name.find_last_of(
".") == std::string::npos) name.append(
".ppm");
325 std::cerr <<
"Error opening PPM file \"" << name <<
"\"" << std::endl;
329 auto buf = this->convertToBitBuffer<unsigned char>(
false);
330 unsigned char* tmp =
buf.get();
332 os <<
"P6\n" << mWidth <<
" " << mHeight <<
"\n255\n";
333 os.write(reinterpret_cast<const char*>(&(*tmp)), 3 * mSize *
sizeof(
unsigned char));
336 size_t width()
const {
return mWidth; }
337 size_t height()
const {
return mHeight; }
342 size_t mWidth, mHeight, mSize;
343 std::unique_ptr<RGBA[]> mPixels;
354 double frameWidth,
double nearPlane,
double farPlane)
359 assert(nearPlane > 0 && farPlane > nearPlane);
364 this->
initRay(nearPlane, farPlane);
381 const Vec3R dir = orig - xyz;
383 Mat4d xform = math::aim<Mat4d>(dir, up);
400 size_t i,
size_t j,
double iOffset = 0.5,
double jOffset = 0.5)
const = 0;
438 double focalLength = 50.0,
439 double aperture = 41.2136,
440 double nearPlane = 1e-3,
442 :
BaseCamera(film,
rotation, translation, 0.5*aperture/focalLength, nearPlane, farPlane)
452 size_t i,
size_t j,
double iOffset = 0.5,
double jOffset = 0.5)
const override
467 return 360.0 / math::pi<double>() *
atan(aperture/(2.0*length));
473 return aperture/(2.0*(
tan(fov * math::pi<double>() / 360.0)));
496 double frameWidth = 1.0,
497 double nearPlane = 1e-3,
505 size_t i,
size_t j,
double iOffset = 0.5,
double jOffset = 0.5)
const override
541 template<
typename GridT = Film::RGBA,
558 typename GridT::ConstAccessor mAcc;
563 template<
typename SamplerType>
588 template<
typename GridT = Film::RGBA,
600 return Film::RGBA(v[0]*(normal[0]+1.0), v[1]*(normal[1]+1.0), v[2]*(normal[2]+1.0));
605 typename GridT::ConstAccessor mAcc;
610 template<
typename SamplerType>
619 return mRGBA *
Film::RGBA(normal[0] + 1.0, normal[1] + 1.0, normal[2] + 1.0);
635 template<
typename GridT = Film::RGBA,
642 , mInvDim(1.0/bbox.extents())
643 , mAcc(grid.getAccessor())
653 const Vec3R rgb = (xyz - mMin) * mInvDim;
659 const Vec3R mMin, mInvDim;
660 typename GridT::ConstAccessor mAcc;
665 template<
typename SamplerType>
670 : mMin(bbox.
min()), mInvDim(1.0/bbox.extents()), mRGBA(
c) {}
675 const Vec3R rgb = (xyz - mMin)*mInvDim;
676 return mRGBA*
Film::RGBA(rgb[0], rgb[1], rgb[2]);
681 const Vec3R mMin, mInvDim;
695 template<
typename GridT = Film::RGBA,
715 typename GridT::ConstAccessor mAcc;
720 template <
typename SamplerType>
749 template<
typename Gr
idT>
758 tracer(grid, shader, camera, pixelSamples, seed);
763 template<
typename Gr
idT,
typename IntersectorT>
765 const IntersectorT& inter,
780 template<
typename Gr
idT,
typename IntersectorT>
790 mShader(shader.
copy()),
796 template<
typename Gr
idT,
typename IntersectorT>
806 mShader(shader.
copy()),
812 template<
typename Gr
idT,
typename IntersectorT>
817 mInter(other.mInter),
818 mShader(other.mShader->
copy()),
819 mCamera(other.mCamera),
820 mSubPixels(other.mSubPixels)
824 template<
typename Gr
idT,
typename IntersectorT>
828 if (mIsMaster)
delete [] mRand;
831 template<
typename Gr
idT,
typename IntersectorT>
836 mInter = IntersectorT(grid);
839 template<
typename Gr
idT,
typename IntersectorT>
847 template<
typename Gr
idT,
typename IntersectorT>
852 mShader.reset(shader.
copy());
855 template<
typename Gr
idT,
typename IntersectorT>
863 template<
typename Gr
idT,
typename IntersectorT>
868 if (pixelSamples == 0) {
869 OPENVDB_THROW(ValueError,
"pixelSamples must be larger than zero!");
871 mSubPixels = pixelSamples - 1;
873 if (mSubPixels > 0) {
874 mRand =
new double[16];
876 for (
size_t i=0; i<16; ++i) mRand[i] = rand();
882 template<
typename Gr
idT,
typename IntersectorT>
886 tbb::blocked_range<size_t>
range(0, mCamera->height());
890 template<
typename Gr
idT,
typename IntersectorT>
896 const float frac = 1.0f / (1.0f +
float(mSubPixels));
897 for (
size_t j=range.begin(),
n=0, je = range.end();
j<je; ++
j) {
898 for (
size_t i=0, ie = mCamera->width(); i<ie; ++i) {
900 RayType ray = mCamera->getRay(i,
j);
901 Film::RGBA c = mInter.intersectsWS(ray, xyz, nml) ?
shader(xyz, nml, ray.dir()) : bg;
902 for (
size_t k=0; k<mSubPixels; ++k,
n +=2 ) {
903 ray = mCamera->getRay(i,
j, mRand[n & 15], mRand[(n+1) & 15]);
904 c += mInter.intersectsWS(ray, xyz, nml) ?
shader(xyz, nml, ray.dir()) : bg;
913 template<
typename IntersectorT,
typename SampleT>
916 : mAccessor(inter.grid().getConstAccessor())
918 , mPrimary(new IntersectorT(inter))
919 , mShadow(new IntersectorT(inter))
925 , mLightColor(0.7, 0.7, 0.7)
931 template<
typename IntersectorT,
typename SampleT>
934 : mAccessor(other.mAccessor)
935 , mCamera(other.mCamera)
936 , mPrimary(new IntersectorT(*(other.mPrimary)))
937 , mShadow(new IntersectorT(*(other.mShadow)))
938 , mPrimaryStep(other.mPrimaryStep)
939 , mShadowStep(other.mShadowStep)
940 , mCutOff(other.mCutOff)
941 , mLightGain(other.mLightGain)
942 , mLightDir(other.mLightDir)
943 , mLightColor(other.mLightColor)
944 , mAbsorption(other.mAbsorption)
945 , mScattering(other.mScattering)
949 template<
typename IntersectorT,
typename SampleT>
951 print(std::ostream& os,
int verboseLevel)
953 if (verboseLevel>0) {
954 os <<
"\nPrimary step: " << mPrimaryStep
955 <<
"\nShadow step: " << mShadowStep
956 <<
"\nCutoff: " << mCutOff
957 <<
"\nLightGain: " << mLightGain
958 <<
"\nLightDir: " << mLightDir
959 <<
"\nLightColor: " << mLightColor
960 <<
"\nAbsorption: " << mAbsorption
961 <<
"\nScattering: " << mScattering << std::endl;
963 mPrimary->print(os, verboseLevel);
966 template<
typename IntersectorT,
typename SampleT>
970 mPrimary.reset(
new IntersectorT(inter));
971 mShadow.reset(
new IntersectorT(inter));
974 template<
typename IntersectorT,
typename SampleT>
978 tbb::blocked_range<size_t>
range(0, mCamera->height());
982 template<
typename IntersectorT,
typename SampleT>
989 const Vec3R extinction = -mScattering-mAbsorption, One(1.0);
990 const Vec3R albedo = mLightColor*mScattering/(mScattering+mAbsorption);
991 const Real sGain = mLightGain;
992 const Real pStep = mPrimaryStep;
993 const Real sStep = mShadowStep;
994 const Real cutoff = mCutOff;
1003 std::vector<typename RayType::TimeSpan> pTS, sTS;
1008 for (
size_t j=range.begin(), je = range.end();
j<je; ++
j) {
1009 for (
size_t i=0, ie = mCamera->width(); i<ie; ++i) {
1011 bg.
a = bg.
r = bg.
g = bg.
b = 0;
1012 RayType pRay = mCamera->getRay(i,
j);
1013 if( !mPrimary->setWorldRay(pRay))
continue;
1014 Vec3R pTrans(1.0), pLumi(0.0);
1017 while (mPrimary->march(pT0, pT1)) {
1018 for (
Real pT = pStep*
ceil(pT0/pStep); pT <= pT1; pT += pStep) {
1020 mPrimary->hits(pTS);
1021 for (
size_t k=0; k<pTS.size(); ++k) {
1022 Real pT = pStep*
ceil(pTS[k].t0/pStep), pT1=pTS[k].t1;
1023 for (; pT <= pT1; pT += pStep) {
1025 Vec3R pPos = mPrimary->getWorldPos(pT);
1027 if (density < cutoff)
continue;
1031 if( !mShadow->setWorldRay(sRay))
continue;
1034 while (mShadow->march(sT0, sT1)) {
1035 for (
Real sT = sStep*
ceil(sT0/sStep); sT <= sT1; sT+= sStep) {
1038 for (
size_t l=0; l<sTS.size(); ++l) {
1039 Real sT = sStep*
ceil(sTS[l].t0/sStep), sT1=sTS[l].t1;
1040 for (; sT <= sT1; sT+= sStep) {
1042 const Real d =
sampler.wsSample(mShadow->getWorldPos(sT));
1043 if (d < cutoff)
continue;
1044 sTrans *=
math::Exp(extinction * d * sStep/(1.0+sT*sGain));
1045 if (sTrans.
lengthSqr()<cutoff)
goto Luminance;
1049 pLumi += albedo * sTrans * pTrans * (One-dT);
1051 if (pTrans.lengthSqr()<cutoff)
goto Pixel;
1069 #ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION
1071 #ifdef OPENVDB_INSTANTIATE_RAYTRACER
1075 #define _FUNCTION(TreeT) \
1076 void rayTrace(const Grid<TreeT>&, const BaseShader&, BaseCamera&, size_t, unsigned int, bool)
1080 #define _FUNCTION(TreeT) \
1081 void rayTrace(const Grid<TreeT>&, const tools::LevelSetRayIntersector<Grid<TreeT>>&, const BaseShader&, BaseCamera&, size_t, unsigned int, bool)
1088 #endif // OPENVDB_USE_EXPLICIT_INSTANTIATION
1095 #endif // OPENVDB_TOOLS_RAYTRACER_HAS_BEEN_INCLUDED
void parallel_for(int64_t start, int64_t end, std::function< void(int64_t index)> &&task, parallel_options opt=parallel_options(0, Split_Y, 1))
GLenum GLuint GLenum GLsizei const GLchar * buf
void setTimes(RealT t0=math::Delta< RealT >::value(), RealT t1=std::numeric_limits< RealT >::max())
Simple generator of random numbers over the range [0, 1)
bool normalize(T eps=T(1.0e-7))
this = normalized this
GridType
List of types that are currently supported by NanoVDB.
OIIO_UTIL_API bool copy(string_view from, string_view to, std::string &err)
void setEye(const Vec3Type &eye)
GLsizei const GLchar *const * string
GLsizei const GLfloat * value
const GLuint GLenum const void * binary
GLdouble GLdouble GLdouble z
#define OPENVDB_REAL_TREE_INSTANTIATE(Function)
void setDir(const Vec3Type &dir)
GLboolean GLboolean GLboolean GLboolean a
GLuint GLsizei GLsizei * length
#define OPENVDB_USE_VERSION_NAMESPACE
ImageBuf OIIO_API min(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
GLdouble GLdouble GLdouble q
T dot(const Vec3< T > &v) const
Dot product.
Vec3d applyJacobian(const Vec3d &in, const Vec3d &) const override
Return the Jacobian of the map applied to in.
Accelerated intersection of a ray with a narrow-band level set or a generic (e.g. density) volume...
GA_API const UT_StringHolder scale
GLint GLsizei GLsizei height
void accumPostRotation(Axis axis, double radians)
Modify the existing affine map by post-applying the given operation.
IMATH_NAMESPACE::V2f float
#define OPENVDB_INSTANTIATE_CLASS
Coord Abs(const Coord &xyz)
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.
void postTranslate(const Vec3< T0 > &tr)
Right multiplies by the specified translation matrix, i.e. (*this) * Trans.
png_const_structrp png_const_inforp int * unit
GLfloat GLfloat GLfloat alpha
SIM_API const UT_StringHolder rotation
GLuint const GLchar * name
Vec3< T > unit(T eps=0) const
return normalized this, throws if null vector
GLboolean GLboolean GLboolean b
GA_API const UT_StringHolder transform
Vec3d applyMap(const Vec3d &in) const override
Return the image of in under the map.
SYS_API double tan(double x)
GLfloat GLfloat GLfloat GLfloat h
IMATH_HOSTDEVICE constexpr int ceil(T x) IMATH_NOEXCEPT
Axis-aligned bounding box.
const Vec3T & dir() const
SYS_API double atan(double x)
ImageBuf OIIO_API max(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
void accumPostTranslation(const Vec3d &v)
Modify the existing affine map by post-applying the given operation.
GLubyte GLubyte GLubyte GLubyte w
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
void scaleTimes(RealT scale)
#define OPENVDB_THROW(exception, message)
Type Exp(const Type &x)
Return ex.