@@ -1513,7 +1513,7 @@ struct ZeltnerBurleySheen final : public BSDF, MxSheenParams {
15131513 }
15141514};
15151515
1516- // / @name Mediums
1516+
15171517struct HenyeyGreenstein final : public BSDF {
15181518 const float g;
15191519 OSL_HOSTDEVICE HenyeyGreenstein (float g)
@@ -1559,29 +1559,25 @@ struct HenyeyGreenstein final : public BSDF {
15591559
15601560};
15611561
1562- struct HomogeneousVolume final : public Medium, MediumParams {
1562+ struct HomogeneousVolume final : public Medium {
1563+ MediumParams params;
15631564
15641565 OSL_HOSTDEVICE HomogeneousVolume (const MediumParams& params)
1565- : Medium(this ), MediumParams (params)
1566+ : Medium(this ), params (params)
15661567 {
15671568 }
15681569
15691570 OSL_HOSTDEVICE static HomogeneousVolume* create (void * storage, const MediumParams& params) {
15701571 HomogeneousVolume* volume = new (storage) HomogeneousVolume (params);
1571- volume->phase_func = new HenyeyGreenstein (params.medium_g ); // assuming g is anisotropy parameter
1572+ volume->phase_func = new HenyeyGreenstein (params.medium_g );
15721573 return volume;
15731574 }
15741575
15751576 OSL_HOSTDEVICE Medium::Sample sample (const Ray &ray, Sampler &sampler, Intersection& hit) const
15761577 {
15771578 Vec3 rand_vol = sampler.get ();
1578- float max_sigma_t = std::max (std::max (sigma_t .x , sigma_t .y ), sigma_t .z );
1579- /*
1580- if (max_sigma_t <= 0.0f) {
1581- // vacuum: no attenuation, pdf irrelevant
1582- return Medium::Sample { hit.t, false, Color3(1.0f) };
1583- }
1584- */
1579+ float max_sigma_t = fmaxf (fmaxf (params.sigma_t .x , params.sigma_t .y ), params.sigma_t .z );
1580+
15851581 float t_volume = -logf (1 .0f - rand_vol.x ) / max_sigma_t ;
15861582 bool volume_scatter = (t_volume < hit.t );
15871583
@@ -1592,9 +1588,9 @@ struct HomogeneousVolume final : public Medium, MediumParams {
15921588 tr = transmittance (t_volume);
15931589
15941590 Color3 albedo = Color3 (
1595- sigma_s.x / sigma_t .x ,
1596- sigma_s.y / sigma_t .y ,
1597- sigma_s.z / sigma_t .z
1591+ params. sigma_s .x / params. sigma_t .x ,
1592+ params. sigma_s .y / params. sigma_t .y ,
1593+ params. sigma_s .z / params. sigma_t .z
15981594 );
15991595
16001596 weight = albedo / tr;
@@ -1606,30 +1602,46 @@ struct HomogeneousVolume final : public Medium, MediumParams {
16061602 1.0 / tr.z
16071603 );
16081604 }
1609- /*
1610- if (pdf <= 0.0f) {
1611- // ensure Tr is black in this degenerate case if we expected absorption
1612- return Medium::Sample { hit.t, false, tr };
1613- }
1614- */
1605+
16151606 return Medium::Sample { volume_scatter, t_volume, tr, weight };
16161607 }
16171608
1609+ OSL_HOSTDEVICE const MediumParams* get_params () const {
1610+ return ¶ms;
1611+ }
1612+
16181613 OSL_HOSTDEVICE Color3 transmittance (float distance) const
1619- { // Beer-Lambert law
1620- return Color3 (expf (-sigma_t .x * distance),
1621- expf (-sigma_t .y * distance),
1622- expf (-sigma_t .z * distance));
1614+ { // Beer-Lambert law
1615+ return Color3 (expf (-params. sigma_t .x * distance),
1616+ expf (-params. sigma_t .y * distance),
1617+ expf (-params. sigma_t .z * distance));
16231618 }
16241619};
16251620
16261621struct EmptyVolume final : public Medium {
1627- OSL_HOSTDEVICE EmptyVolume () :
1628- Medium(this )
1622+ MediumParams params;
1623+
1624+ OSL_HOSTDEVICE EmptyVolume (const MediumParams& params)
1625+ : Medium(this ), params(params)
1626+ {
1627+ }
1628+
1629+ OSL_HOSTDEVICE static EmptyVolume* create (void * storage, const MediumParams& params) {
1630+ EmptyVolume* volume = new (storage) EmptyVolume (params);
1631+ return volume;
1632+ }
1633+
1634+ OSL_HOSTDEVICE Medium::Sample sample (const Ray &ray, Sampler &sampler, Intersection& hit) const
16291635 {
1636+ return { false , 0 .0f , Color3 (1 .0f ), Color3 (1 .0f ) };
1637+ }
1638+
1639+ OSL_HOSTDEVICE const MediumParams* get_params () const {
1640+ return ¶ms;
16301641 }
16311642};
16321643
1644+
16331645OSL_HOSTDEVICE Color3
16341646evaluate_layer_opacity (const ShaderGlobalsType& sg, float path_roughness,
16351647 const ClosureColor* closure)
@@ -1769,9 +1781,14 @@ process_medium_closure(const ShaderGlobalsType& sg, float path_roughness,
17691781 result.medium_data .sigma_t = cw * params.extinction ;
17701782 result.medium_data .sigma_s = params.albedo * result.medium_data .sigma_t ;
17711783 result.medium_data .medium_g = params.anisotropy ;
1784+ result.medium_data .priority = 0 ;
17721785
17731786 if (!sg.backfacing ) { // if entering
1774- medium_stack.push_medium <HomogeneousVolume>(result.medium_data );
1787+ if (result.medium_data .is_vaccum ()) {
1788+ medium_stack.add_medium <EmptyVolume>(result.medium_data );
1789+ } else {
1790+ medium_stack.add_medium <HomogeneousVolume>(result.medium_data );
1791+ }
17751792 }
17761793
17771794 closure = nullptr ;
@@ -1781,7 +1798,7 @@ process_medium_closure(const ShaderGlobalsType& sg, float path_roughness,
17811798 const ClosureComponent* comp = closure->as_comp ();
17821799 Color3 cw = weight * comp->w ;
17831800 const auto & params = *comp->as <MxMediumVdfParams>();
1784-
1801+
17851802 result.medium_data .sigma_t = Color3 (
17861803 -OIIO::fast_log (params.transmission_color .x ),
17871804 -OIIO::fast_log (params.transmission_color .y ),
@@ -1792,44 +1809,56 @@ process_medium_closure(const ShaderGlobalsType& sg, float path_roughness,
17921809 result.medium_data .sigma_s = params.albedo * result.medium_data .sigma_t ;
17931810 result.medium_data .medium_g = params.anisotropy ;
17941811
1795- // Track IOR and priority here
1796- result.medium_data .refraction_ior = sg.backfacing ? 1 .0f / params.ior
1797- : params.ior ;
1798-
1812+ result.medium_data .refraction_ior = sg.backfacing ? 1 .0f / params.ior : params.ior ;
1813+ result.medium_data .priority = params.priority ;
1814+
17991815 if (!sg.backfacing ) { // if entering
1800- medium_stack.push_medium <HomogeneousVolume>(result.medium_data );
1816+ if (result.medium_data .is_vaccum ()) {
1817+ medium_stack.add_medium <EmptyVolume>(result.medium_data );
1818+ } else {
1819+ medium_stack.add_medium <HomogeneousVolume>(result.medium_data );
1820+ }
18011821 }
1802-
1803- // result.medium_data.priority = params.priority;
1822+
18041823 closure = nullptr ;
18051824 break ;
18061825 }
18071826 case MxDielectric::closureid (): {
18081827 const ClosureComponent* comp = closure->as_comp ();
18091828 const MxDielectric::Data& params = *comp->as <MxDielectric::Data>();
18101829 if (!is_black (weight * comp->w * params.refr_tint )) {
1811- // TODO: properly track a medium stack here ...
1812- result.medium_data .refraction_ior = sg.backfacing ? 1 .0f / params.IOR
1813- : params.IOR ;
1830+ float new_ior = sg.backfacing ? 1 .0f / params.IOR : params.IOR ;
1831+
1832+ result.medium_data .refraction_ior = new_ior;
1833+
1834+ const MediumParams* current_params = medium_stack.current_params ();
1835+ if (current_params && result.medium_data .priority <= current_params->priority ) {
1836+ result.medium_data .refraction_ior = current_params->refraction_ior ;
1837+ }
18141838 }
18151839 closure = nullptr ;
18161840 break ;
18171841 }
18181842 case MX_GENERALIZED_SCHLICK_ID: {
1819- const ClosureComponent* comp = closure->as_comp ();
1820- const auto & params = *comp->as <MxGeneralizedSchlickParams>();
1821- if (!is_black (weight * comp->w * params.transmission_tint )) {
1822- // TODO: properly track a medium stack here ...
1823- float avg_F0 = clamp ((params.f0 .x + params.f0 .y + params.f0 .z )
1824- / 3 .0f ,
1825- 0 .0f , 0 .99f );
1826- float sqrt_F0 = sqrtf (avg_F0);
1827- float ior = (1 + sqrt_F0) / (1 - sqrt_F0);
1828- result.medium_data .refraction_ior = sg.backfacing ? 1 .0f / ior : ior;
1843+ const ClosureComponent* comp = closure->as_comp ();
1844+ const auto & params = *comp->as <MxGeneralizedSchlickParams>();
1845+ if (!is_black (weight * comp->w * params.transmission_tint )) {
1846+ float avg_F0 = clamp ((params.f0 .x + params.f0 .y + params.f0 .z ) / 3 .0f ,
1847+ 0 .0f , 0 .99f );
1848+ float sqrt_F0 = sqrtf (avg_F0);
1849+ float ior = (1 + sqrt_F0) / (1 - sqrt_F0);
1850+ float new_ior = sg.backfacing ? 1 .0f / ior : ior;
1851+
1852+ result.medium_data .refraction_ior = new_ior;
1853+
1854+ const MediumParams* current_params = medium_stack.current_params ();
1855+ if (current_params && result.medium_data .priority <= current_params->priority ) {
1856+ result.medium_data .refraction_ior = current_params->refraction_ior ;
18291857 }
1830- closure = nullptr ;
1831- break ;
18321858 }
1859+ closure = nullptr ;
1860+ break ;
1861+ }
18331862 default : closure = nullptr ; break ;
18341863 }
18351864 if (closure == nullptr && stack_idx > 0 ) {
@@ -1842,8 +1871,9 @@ process_medium_closure(const ShaderGlobalsType& sg, float path_roughness,
18421871// recursively walk through the closure tree, creating bsdfs as we go
18431872OSL_HOSTDEVICE void
18441873process_bsdf_closure (const ShaderGlobalsType& sg, float path_roughness,
1845- ShadingResult& result, const ClosureColor* closure,
1846- const Color3& w, bool light_only)
1874+ ShadingResult& result, MediumStack& medium_stack,
1875+ const ClosureColor* closure, const Color3& w,
1876+ bool light_only)
18471877{
18481878 static const ustringhash uh_ggx (" ggx" );
18491879 static const ustringhash uh_beckmann (" beckmann" );
@@ -1976,9 +2006,13 @@ process_bsdf_closure(const ShaderGlobalsType& sg, float path_roughness,
19762006 case MxDielectric::closureid (): {
19772007 const MxDielectric::Data& params
19782008 = *comp->as <MxDielectric::Data>();
1979- ok = result.bsdf .add_bsdf <MxDielectric>(cw, params, -sg.I ,
1980- sg.backfacing ,
1981- path_roughness);
2009+
2010+ if (medium_stack.false_intersection_with (result.medium_data )) {
2011+ ok = result.bsdf .add_bsdf <Transparent>(cw);
2012+ } else {
2013+ ok = result.bsdf .add_bsdf <MxDielectric>(cw, params, -sg.I ,
2014+ sg.backfacing , path_roughness);
2015+ }
19822016 break ;
19832017 }
19842018 case MxConductor::closureid (): {
@@ -1991,17 +2025,23 @@ process_bsdf_closure(const ShaderGlobalsType& sg, float path_roughness,
19912025 case MX_GENERALIZED_SCHLICK_ID: {
19922026 const MxGeneralizedSchlickParams& params
19932027 = *comp->as <MxGeneralizedSchlickParams>();
1994- if (is_black (params.transmission_tint ))
1995- ok = result.bsdf .add_bsdf <MxMicrofacet<
1996- MxGeneralizedSchlickParams, GGXDist, false >>(cw,
1997- params,
1998- 1 .0f );
1999- else
2000- ok = result.bsdf .add_bsdf <MxMicrofacet<
2001- MxGeneralizedSchlickParams, GGXDist, true >>(
2002- cw, params, result.medium_data .refraction_ior );
2028+
2029+ if (medium_stack.false_intersection_with (result.medium_data )) {
2030+ ok = result.bsdf .add_bsdf <Transparent>(cw);
2031+ } else {
2032+ if (is_black (params.transmission_tint )) {
2033+ ok = result.bsdf .add_bsdf <MxMicrofacet<
2034+ MxGeneralizedSchlickParams, GGXDist, false >>(cw,
2035+ params,
2036+ 1 .0f );
2037+ } else {
2038+ ok = result.bsdf .add_bsdf <MxMicrofacet<
2039+ MxGeneralizedSchlickParams, GGXDist, true >>(
2040+ cw, params, result.medium_data .refraction_ior );
2041+ }
2042+ }
20032043 break ;
2004- };
2044+ }
20052045 case MX_TRANSLUCENT_ID: {
20062046 const MxTranslucentParams* srcparams
20072047 = comp->as <MxTranslucentParams>();
@@ -2093,7 +2133,7 @@ process_closure(const ShaderGlobalsType& sg, float path_roughness,
20932133{
20942134 if (!light_only)
20952135 process_medium_closure (sg, path_roughness, result, medium_stack, Ci, Color3 (1 ));
2096- process_bsdf_closure (sg, path_roughness, result, Ci, Color3 (1 ), light_only);
2136+ process_bsdf_closure (sg, path_roughness, result, medium_stack, Ci, Color3 (1 ), light_only);
20972137}
20982138
20992139OSL_HOSTDEVICE Vec3
@@ -2156,7 +2196,12 @@ BSDF::sample_vrtl(const Vec3& wo, float rx, float ry, float rz) const
21562196
21572197Medium::Sample Medium::sample_vrtl (const Ray &ray, Sampler &sampler, Intersection& hit) const
21582198{
2159- return dispatch ([&](auto volume) { return volume.sample (ray, sampler, hit); });
2199+ return dispatch ([&](const auto & medium) { return medium.sample (ray, sampler, hit); });
2200+ }
2201+
2202+ const MediumParams* Medium::get_params_vrtl () const
2203+ {
2204+ return dispatch ([&](const auto & medium) { return medium.get_params (); });
21602205}
21612206
21622207OSL_NAMESPACE_END
0 commit comments