@@ -230,7 +230,7 @@ struct MxMediumVdfParams {
230230
231231struct MediumParams {
232232 Color3 sigma_t = Color3(0 .0f ); // extinction coefficient
233- Color3 sigma_s = Color3(0 .0f ); // scattering
233+ Color3 sigma_s = Color3(0 .0f ); // scattering
234234 float medium_g = 0 .0f ; // volumetric anisotropy
235235 float refraction_ior = 1 .0f ;
236236 int priority = 0 ;
@@ -244,6 +244,10 @@ struct MediumParams {
244244 return priority == 0 ;
245245 }
246246
247+ OSL_HOSTDEVICE float avg_sigma_t () const {
248+ return (sigma_t .x + sigma_t .y + sigma_t .z ) / 3 ;
249+ }
250+
247251 OSL_HOSTDEVICE bool operator ==(const MediumParams &rhs) const {
248252 return refraction_ior == rhs.refraction_ior &&
249253 medium_g == rhs.medium_g &&
@@ -377,16 +381,16 @@ struct has_equal<T, std::void_t<decltype(std::declval<const T&>() == std::declva
377381
378382struct Medium : public AbstractMedium {
379383 struct Sample {
380- OSL_HOSTDEVICE Sample ()
381- : scatter(false ), t(0 .0f ), transmittance(0 .0f ), weight(0 .0f )
384+ OSL_HOSTDEVICE Sample () :
385+ scatter(false ), t(0 .0f ), transmittance(0 .0f ), weight(0 .0f )
382386 {
383387 }
384- OSL_HOSTDEVICE Sample (const Sample& o)
385- : scatter(o.scatter), t(o.t), transmittance(o.transmittance), weight(o.weight)
388+ OSL_HOSTDEVICE Sample (const Sample& o) :
389+ scatter(o.scatter), t(o.t), transmittance(o.transmittance), weight(o.weight)
386390 {
387391 }
388- OSL_HOSTDEVICE Sample (bool scatter, float t, Color3 transmittance, Color3 weight)
389- : scatter(scatter), t(t), transmittance(transmittance), weight(weight)
392+ OSL_HOSTDEVICE Sample (bool scatter, float t, Color3 transmittance, Color3 weight) :
393+ scatter(scatter), t(t), transmittance(transmittance), weight(weight)
390394 {
391395 }
392396 bool scatter;
@@ -396,7 +400,7 @@ struct Medium : public AbstractMedium {
396400 };
397401
398402 template <typename LOBE>
399- OSL_HOSTDEVICE Medium (LOBE* lobe) : AbstractMedium(lobe)
403+ OSL_HOSTDEVICE Medium (LOBE* lobe) : AbstractMedium(lobe), phase_func( nullptr )
400404 {
401405 }
402406
@@ -410,11 +414,11 @@ struct Medium : public AbstractMedium {
410414 return {};
411415 }
412416
413- OSL_HOSTDEVICE Sample sample (const Ray &ray , Sampler &sampler, Intersection& hit) const {
417+ OSL_HOSTDEVICE Sample sample (Ray &r , Sampler &sampler, Intersection& hit) const {
414418 return {};
415419 }
416420
417- OSL_HOSTDEVICE Sample sample_vrtl (const Ray &ray , Sampler &sampler, Intersection& hit) const ;
421+ OSL_HOSTDEVICE Sample sample_vrtl (Ray &r , Sampler &sampler, Intersection& hit) const ;
418422
419423 OSL_HOSTDEVICE const MediumParams* get_params_vrtl () const ;
420424
@@ -554,7 +558,7 @@ struct MediumStack {
554558 }
555559
556560 OSL_HOSTDEVICE const MediumParams* current_params () const {
557- if (depth > 0 ) {
561+ if (depth > 0 && mediums[ 0 ] ) {
558562 const MediumParams* params = mediums[0 ]->get_params_vrtl ();
559563 if (params) {
560564 return params;
@@ -567,21 +571,77 @@ struct MediumStack {
567571
568572 OSL_HOSTDEVICE int size () const { return depth; }
569573
574+ OSL_HOSTDEVICE bool integrate (Ray& r, Sampler& sampler, Intersection& hit, Color3& path_weight, Color3& path_radiance, float & bsdf_pdf) const
575+ {
576+ if (depth <= 0 ) {
577+ return false ;
578+ }
579+
580+ Medium::Sample combined_sample{ false , 1 .0f , Color3 (1 .0f ), Color3 (1 .0f ) };
581+
582+ for (int i = 0 ; i < depth; ++i) {
583+ Medium::Sample s = mediums[i]->sample_vrtl (r, sampler, hit);
584+
585+ combined_sample.transmittance *= s.transmittance ;
586+ combined_sample.weight *= s.weight ;
587+
588+ combined_sample.scatter = s.scatter || combined_sample.scatter ;
589+ combined_sample.t = s.t < combined_sample.t ? s.t : combined_sample.t ;
590+ }
591+
592+ if (!(combined_sample.transmittance .x > 0 || combined_sample.transmittance .y > 0 || combined_sample.transmittance .z > 0 )) {
593+ return false ;
594+ }
595+
596+ path_weight *= combined_sample.transmittance ;
597+
598+ Vec3 rand_phase = sampler.get ();
599+ if (combined_sample.scatter ) {
600+ if (!mediums[0 ]->phase_func ) {
601+ return false ;
602+ }
603+ BSDF::Sample phase_sample = mediums[0 ]->phase_func ->sample_vrtl (-r.direction ,
604+ rand_phase.x ,
605+ rand_phase.y ,
606+ rand_phase.z );
607+ if (phase_sample.pdf <= 0 .0f ) {
608+ return false ;
609+ }
610+
611+ path_weight *= phase_sample.weight ;
612+ r.direction = phase_sample.wi ;
613+ bsdf_pdf = phase_sample.pdf ;
614+ return true ;
615+ }
616+
617+ return false ;
618+ }
619+
570620 template <typename Medium_Type, typename ... Medium_Args>
571621 OSL_HOSTDEVICE bool add_medium (Medium_Args&&... args) {
572622
573- Medium_Type* new_medium = Medium_Type::create (pool + num_bytes, std::forward<Medium_Args>(args)...);
574-
575623 if (depth >= MaxEntries)
576624 return false ;
577625
578626 if (num_bytes + sizeof (Medium_Type) > MaxSize)
579627 return false ;
580628
629+ Medium_Type* new_medium = Medium_Type::create (pool + num_bytes, std::forward<Medium_Args>(args)...);
630+
631+ if (!new_medium) {
632+ return false ;
633+ }
634+
635+ const MediumParams* new_params = new_medium->get_params_vrtl ();
581636 int insert_pos = depth;
582637
583638 for (int i = 0 ; i < depth; ++i) {
584- if (new_medium->get_params_vrtl ()->priority > mediums[i]->get_params_vrtl ()->priority ) {
639+ if (!mediums[i]) {
640+ continue ;
641+ }
642+
643+ const MediumParams* existing_params = mediums[i]->get_params_vrtl ();
644+ if (existing_params && new_params->priority > existing_params->priority ) {
585645 insert_pos = i;
586646 break ;
587647 }
@@ -601,12 +661,6 @@ struct MediumStack {
601661 OSL_HOSTDEVICE void pop_medium ()
602662 {
603663 if (depth > 0 ) {
604- mediums[0 ]->~Medium ();
605-
606- for (int i = 1 ; i < depth; ++i) {
607- mediums[i - 1 ] = mediums[i];
608- }
609-
610664 depth--;
611665 }
612666 }
@@ -615,6 +669,7 @@ struct MediumStack {
615669 const MediumParams* current = current_params ();
616670 return (current && ((params.priority < current->priority ) || (params.is_special_priority () && current->is_special_priority () && depth > 1 )));
617671 }
672+
618673private:
619674 // / Never try to copy this struct because it would invalidate the medium pointers
620675 OSL_HOSTDEVICE MediumStack (const MediumStack& c);
@@ -624,6 +679,7 @@ struct MediumStack {
624679 enum { MaxSize = 256 * sizeof (float ) };
625680
626681 Medium* mediums[MaxEntries];
682+ float cdf[MaxEntries];
627683 char pool[MaxSize];
628684 int depth, num_bytes;
629685};
0 commit comments