diff --git a/src/cmake/testing.cmake b/src/cmake/testing.cmake index 5b5b4327d7..05e01fa58b 100644 --- a/src/cmake/testing.cmake +++ b/src/cmake/testing.cmake @@ -362,6 +362,7 @@ macro (osl_add_all_tests) render-cornell render-displacement render-furnace-diffuse + render-mx-anisotropic-vdf render-mx-furnace-burley-diffuse render-mx-furnace-oren-nayar render-mx-furnace-sheen @@ -371,7 +372,9 @@ macro (osl_add_all_tests) render-mx-generalized-schlick render-mx-generalized-schlick-glass render-mx-layer render-mx-sheen - render-microfacet render-oren-nayar + render-mx-medium-vdf + render-mx-medium-vdf-glass + render-microfacet render-oren-nayar render-spi-thinlayer render-uv render-veachmis render-ward render-raytypes diff --git a/src/testrender/shading.cpp b/src/testrender/shading.cpp index 96c140f96a..6f25cb7097 100644 --- a/src/testrender/shading.cpp +++ b/src/testrender/shading.cpp @@ -1513,6 +1513,127 @@ struct ZeltnerBurleySheen final : public BSDF, MxSheenParams { } }; + +struct HenyeyGreenstein final : public BSDF { + const float g; + OSL_HOSTDEVICE HenyeyGreenstein(float g) : BSDF(this), g(g) {} + + static OSL_HOSTDEVICE float PhaseHG(float cos_theta, float g) + { + const float denom = 1 + g * g + 2 * g * cos_theta; + return (1 - g * g) / (4 * M_PI * denom * sqrtf(denom)); + } + + OSL_HOSTDEVICE Sample eval(const Vec3& wo, const Vec3& wi) const + { + const float pdf = PhaseHG(dot(wo, wi), g); + return { wi, Color3(pdf), pdf, 0.0f }; + } + + OSL_HOSTDEVICE Sample sample(const Vec3& wo, float rx, float ry, + float rz) const + { + TangentFrame frame = TangentFrame::from_normal(wo); + + float cos_theta; + if (abs(g) < 1e-3f) { + cos_theta = 1.0f - 2.0f * rx; + } else { + float sqr_term = (1 - g * g) / (1 - g + 2 * g * rx); + cos_theta = (1 + g * g - sqr_term * sqr_term) / (2 * g); + cos_theta = OIIO::clamp(cos_theta, -1.0f, 1.0f); + } + + float sin_theta = sqrtf( + OIIO::clamp(1.0f - cos_theta * cos_theta, 0.0f, 1.0f)); + float phi = 2 * M_PI * ry; + Vec3 local_wi = Vec3(sin_theta * cosf(phi), sin_theta * sinf(phi), + cos_theta); + + Vec3 wi = frame.toworld(local_wi); + float pdf_val = PhaseHG(cos_theta, g); + + return { wi, Color3(1.0f), pdf_val, 0.0f }; + } +}; + +struct HomogeneousMedium final : public Medium { + MediumParams params; + HenyeyGreenstein phase_func; + + OSL_HOSTDEVICE HomogeneousMedium(const MediumParams& params) + : Medium(this), params(params), phase_func(params.medium_g) + { + } + + OSL_HOSTDEVICE Medium::Sample sample(Ray& r, Sampler& sampler, + Intersection& hit) const + { + Vec3 rand_vol = sampler.get(); + + float t_volume = -logf(1.0f - rand_vol.x) / params.avg_sigma_t(); + + Color3 weight; + Color3 tr; + + if (t_volume < hit.t) { + r.origin = r.point(t_volume); + tr = transmittance(t_volume); + + Color3 albedo = params.sigma_s / params.sigma_t; + + weight = albedo / tr; + } else { + tr = transmittance(hit.t); + weight = Color3(1.0 / tr.x, 1.0 / tr.y, 1.0 / tr.z); + } + + return Medium::Sample { t_volume, tr, weight }; + } + + OSL_HOSTDEVICE BSDF::Sample sample_phase_func(const Vec3& wo, float rx, + float ry, + float rz) const + { + return phase_func.sample(wo, rx, ry, rz); + } + + OSL_HOSTDEVICE const MediumParams* get_params() const { return ¶ms; } + + OSL_HOSTDEVICE Color3 transmittance(float distance) const + { // Beer-Lambert law + return Color3(expf(-params.sigma_t.x * distance), + expf(-params.sigma_t.y * distance), + expf(-params.sigma_t.z * distance)); + } +}; + +struct EmptyMedium final : public Medium { + MediumParams params; + + OSL_HOSTDEVICE EmptyMedium(const MediumParams& params) + : Medium(this), params(params) + { + } + + OSL_HOSTDEVICE const MediumParams* get_params() const { return ¶ms; } + + OSL_HOSTDEVICE Medium::Sample sample(Ray& ray, Sampler& sampler, + Intersection& hit) const + { + return { 0.0f, Color3(1.0f), Color3(1.0f) }; + } + + OSL_HOSTDEVICE BSDF::Sample sample_phase_func(const Vec3& wo, float rx, + float ry, + float rz) const + { + return { Vec3(1.0f), Color3(1.0f), 0.0f, 0.0f }; + } + +}; + + OSL_HOSTDEVICE Color3 evaluate_layer_opacity(const ShaderGlobalsType& sg, float path_roughness, const ClosureColor* closure) @@ -1606,8 +1727,8 @@ evaluate_layer_opacity(const ShaderGlobalsType& sg, float path_roughness, OSL_HOSTDEVICE void process_medium_closure(const ShaderGlobalsType& sg, float path_roughness, - ShadingResult& result, const ClosureColor* closure, - const Color3& w) + ShadingResult& result, MediumStack& medium_stack, + const ClosureColor* closure, const Color3& w) { if (!closure) return; @@ -1649,37 +1770,72 @@ process_medium_closure(const ShaderGlobalsType& sg, float path_roughness, const ClosureComponent* comp = closure->as_comp(); Color3 cw = weight * comp->w; const auto& params = *comp->as(); - result.sigma_t = cw * params.extinction; - result.sigma_s = params.albedo * result.sigma_t; - result.medium_g = params.anisotropy; - closure = nullptr; + result.medium_data.sigma_t = cw * params.extinction; + result.medium_data.sigma_s = params.albedo + * result.medium_data.sigma_t; + result.medium_data.medium_g = params.anisotropy; + result.medium_data.priority = 0; + + if (!sg.backfacing) { // if entering + if (result.medium_data.is_vaccum()) { + medium_stack.add_medium(result.medium_data); + } else { + medium_stack.add_medium( + result.medium_data); + } + } + + closure = nullptr; break; } case MX_MEDIUM_VDF_ID: { const ClosureComponent* comp = closure->as_comp(); Color3 cw = weight * comp->w; const auto& params = *comp->as(); - result.sigma_t = { -OIIO::fast_log(params.transmission_color.x), - -OIIO::fast_log(params.transmission_color.y), - -OIIO::fast_log(params.transmission_color.z) }; - // NOTE: closure weight scales the extinction parameter - result.sigma_t *= cw / params.transmission_depth; - result.sigma_s = params.albedo * result.sigma_t; - result.medium_g = params.anisotropy; - // TODO: properly track a medium stack here ... - result.refraction_ior = sg.backfacing ? 1.0f / params.ior - : params.ior; - result.priority = params.priority; - closure = nullptr; + + result.medium_data.sigma_t + = Color3(-OIIO::fast_log(params.transmission_color.x), + -OIIO::fast_log(params.transmission_color.y), + -OIIO::fast_log(params.transmission_color.z)); + + result.medium_data.sigma_t *= cw / params.transmission_depth; + result.medium_data.sigma_s = params.albedo + * result.medium_data.sigma_t; + result.medium_data.medium_g = params.anisotropy; + + result.medium_data.refraction_ior = sg.backfacing + ? 1.0f / params.ior + : params.ior; + result.medium_data.priority = params.priority; + + if (!sg.backfacing) { // if entering + if (result.medium_data.is_vaccum()) { + medium_stack.add_medium(result.medium_data); + } else { + medium_stack.add_medium( + result.medium_data); + } + } + + closure = nullptr; break; } case MxDielectric::closureid(): { const ClosureComponent* comp = closure->as_comp(); const MxDielectric::Data& params = *comp->as(); if (!is_black(weight * comp->w * params.refr_tint)) { - // TODO: properly track a medium stack here ... - result.refraction_ior = sg.backfacing ? 1.0f / params.IOR - : params.IOR; + float new_ior = sg.backfacing ? 1.0f / params.IOR : params.IOR; + + result.medium_data.refraction_ior = new_ior; + + const MediumParams* current_params + = medium_stack.current_params(); + if (current_params + && result.medium_data.priority + <= current_params->priority) { + result.medium_data.refraction_ior + = current_params->refraction_ior; + } } closure = nullptr; break; @@ -1688,13 +1844,23 @@ process_medium_closure(const ShaderGlobalsType& sg, float path_roughness, const ClosureComponent* comp = closure->as_comp(); const auto& params = *comp->as(); if (!is_black(weight * comp->w * params.transmission_tint)) { - // TODO: properly track a medium stack here ... float avg_F0 = clamp((params.f0.x + params.f0.y + params.f0.z) / 3.0f, 0.0f, 0.99f); float sqrt_F0 = sqrtf(avg_F0); float ior = (1 + sqrt_F0) / (1 - sqrt_F0); - result.refraction_ior = sg.backfacing ? 1.0f / ior : ior; + float new_ior = sg.backfacing ? 1.0f / ior : ior; + + result.medium_data.refraction_ior = new_ior; + + const MediumParams* current_params + = medium_stack.current_params(); + if (current_params + && result.medium_data.priority + <= current_params->priority) { + result.medium_data.refraction_ior + = current_params->refraction_ior; + } } closure = nullptr; break; @@ -1711,8 +1877,9 @@ process_medium_closure(const ShaderGlobalsType& sg, float path_roughness, // recursively walk through the closure tree, creating bsdfs as we go OSL_HOSTDEVICE void process_bsdf_closure(const ShaderGlobalsType& sg, float path_roughness, - ShadingResult& result, const ClosureColor* closure, - const Color3& w, bool light_only) + ShadingResult& result, MediumStack& medium_stack, + const ClosureColor* closure, const Color3& w, + bool light_only) { static const ustringhash uh_ggx("ggx"); static const ustringhash uh_beckmann("beckmann"); @@ -1845,9 +2012,16 @@ process_bsdf_closure(const ShaderGlobalsType& sg, float path_roughness, case MxDielectric::closureid(): { const MxDielectric::Data& params = *comp->as(); - ok = result.bsdf.add_bsdf(cw, params, -sg.I, - sg.backfacing, - path_roughness); + + if (medium_stack.false_intersection_with( + result.medium_data)) { + ok = result.bsdf.add_bsdf(cw); + } else { + ok = result.bsdf.add_bsdf(cw, params, + -sg.I, + sg.backfacing, + path_roughness); + } break; } case MxConductor::closureid(): { @@ -1860,15 +2034,21 @@ process_bsdf_closure(const ShaderGlobalsType& sg, float path_roughness, case MX_GENERALIZED_SCHLICK_ID: { const MxGeneralizedSchlickParams& params = *comp->as(); - if (is_black(params.transmission_tint)) - ok = result.bsdf.add_bsdf>(cw, - params, - 1.0f); - else - ok = result.bsdf.add_bsdf>( - cw, params, result.refraction_ior); + + if (medium_stack.false_intersection_with( + result.medium_data)) { + ok = result.bsdf.add_bsdf(cw); + } else { + if (is_black(params.transmission_tint)) { + ok = result.bsdf.add_bsdf>( + cw, params, 1.0f); + } else { + ok = result.bsdf.add_bsdf>( + cw, params, result.medium_data.refraction_ior); + } + } break; }; case MX_TRANSLUCENT_ID: { @@ -1957,11 +2137,14 @@ process_bsdf_closure(const ShaderGlobalsType& sg, float path_roughness, OSL_HOSTDEVICE void process_closure(const ShaderGlobalsType& sg, float path_roughness, - ShadingResult& result, const ClosureColor* Ci, bool light_only) + ShadingResult& result, MediumStack& medium_stack, + const ClosureColor* Ci, bool light_only) { if (!light_only) - process_medium_closure(sg, path_roughness, result, Ci, Color3(1)); - process_bsdf_closure(sg, path_roughness, result, Ci, Color3(1), light_only); + process_medium_closure(sg, path_roughness, result, medium_stack, Ci, + Color3(1)); + process_bsdf_closure(sg, path_roughness, result, medium_stack, Ci, + Color3(1), light_only); } OSL_HOSTDEVICE Vec3 @@ -2022,5 +2205,23 @@ BSDF::sample_vrtl(const Vec3& wo, float rx, float ry, float rz) const return dispatch([&](auto bsdf) { return bsdf.sample(wo, rx, ry, rz); }); } +OSL_HOSTDEVICE Medium::Sample +Medium::sample_vrtl(Ray& ray, Sampler& sampler, Intersection& hit) const +{ + return dispatch( + [&](const auto& medium) { return medium.sample(ray, sampler, hit); }); +} + +OSL_HOSTDEVICE BSDF::Sample +Medium::sample_phase_func_vrtl(const Vec3& wo, float rx, float ry, float rz) const +{ + return dispatch([&](auto medium) { return medium.sample_phase_func(wo, rx, ry, rz); }); +} + +OSL_HOSTDEVICE const MediumParams* +Medium::get_params_vrtl() const +{ + return dispatch([&](const auto& medium) { return medium.get_params(); }); +} OSL_NAMESPACE_END diff --git a/src/testrender/shading.h b/src/testrender/shading.h index 45c37103f5..82308826f8 100644 --- a/src/testrender/shading.h +++ b/src/testrender/shading.h @@ -14,10 +14,11 @@ #include "bsdl_config.h" #include +#include "bvh.h" #include "optics.h" +#include "raytracer.h" #include "sampling.h" - OSL_NAMESPACE_BEGIN @@ -226,6 +227,35 @@ struct MxMediumVdfParams { ustringhash label; }; + +struct MediumParams { + Color3 sigma_t = Color3(0.0f); // extinction coefficient + Color3 sigma_s = Color3(0.0f); // scattering + float medium_g = 0.0f; // volumetric anisotropy + float refraction_ior = 1.0f; + int priority = 0; + + OSL_HOSTDEVICE bool is_vaccum() const + { + return sigma_s.x <= 0.0f && sigma_s.y <= 0.0f && sigma_s.z <= 0.0f; + } + + OSL_HOSTDEVICE bool is_special_priority() const { return priority == 0; } + + OSL_HOSTDEVICE float avg_sigma_t() const + { + return (sigma_t.x + sigma_t.y + sigma_t.z) / 3; + } + + OSL_HOSTDEVICE bool operator==(const MediumParams& rhs) const + { + return refraction_ior == rhs.refraction_ior && medium_g == rhs.medium_g + && sigma_t.x == rhs.sigma_t.x && sigma_t.y == rhs.sigma_t.y + && sigma_t.z == rhs.sigma_t.z && sigma_s.x == rhs.sigma_s.x + && sigma_s.y == rhs.sigma_s.y && sigma_s.z == rhs.sigma_s.z; + } +}; + struct GGXDist; struct BeckmannDist; @@ -261,6 +291,10 @@ struct EnergyCompensatedOrenNayar; struct ZeltnerBurleySheen; struct CharlieSheen; struct SpiThinLayer; +struct HenyeyGreenstein; + +struct HomogeneousMedium; +struct EmptyMedium; // StaticVirtual generates a switch/case dispatch method for us given // a list of possible subtypes. We just need to forward declare them. @@ -270,9 +304,12 @@ using AbstractBSDF = bsdl::StaticVirtual< MicrofacetBeckmannBoth, MicrofacetGGXRefl, MicrofacetGGXRefr, MicrofacetGGXBoth, MxConductor, MxDielectric, MxBurleyDiffuse, EnergyCompensatedOrenNayar, ZeltnerBurleySheen, CharlieSheen, - MxGeneralizedSchlickOpaque, MxGeneralizedSchlick, SpiThinLayer>; + MxGeneralizedSchlickOpaque, MxGeneralizedSchlick, SpiThinLayer, + HenyeyGreenstein>; + +using AbstractMedium = bsdl::StaticVirtual; -// Then we just need to inherit from AbstractBSDF +// Then we just need to inherit from AbstractBSDF or AbstractMedium /// Individual BSDF (diffuse, phong, refraction, etc ...) /// Actual implementations of this class are private @@ -331,6 +368,52 @@ struct BSDF : public AbstractBSDF { #endif }; +struct Medium : public AbstractMedium { + struct Sample { + OSL_HOSTDEVICE Sample() : t(0.0f), transmittance(0.0f), weight(0.0f) {} + OSL_HOSTDEVICE Sample(const Sample& o) + : t(o.t), transmittance(o.transmittance), weight(o.weight) + { + } + OSL_HOSTDEVICE Sample(float t, Color3 transmittance, Color3 weight) + : t(t), transmittance(transmittance), weight(weight) + { + } + float t; + Color3 transmittance; + Color3 weight; + }; + + template + OSL_HOSTDEVICE Medium(LOBE* lobe) + : AbstractMedium(lobe) + { + } + + OSL_HOSTDEVICE const MediumParams* get_params() const { return {}; } + + OSL_HOSTDEVICE const MediumParams* get_params_vrtl() const; + + OSL_HOSTDEVICE Sample sample(Ray& r, Sampler& sampler, + Intersection& hit) const + { + return {}; + } + + OSL_HOSTDEVICE Sample sample_vrtl(Ray& r, Sampler& sampler, + Intersection& hit) const; + + OSL_HOSTDEVICE BSDF::Sample sample_phase_func(const Vec3& wo, float rx, + float ry, + float rz) const { + return {}; + } + OSL_HOSTDEVICE BSDF::Sample sample_phase_func_vrtl(const Vec3& wo, float rx, + float ry, + float rz) const; + +}; + /// Represents a weighted sum of BSDFS /// NOTE: no need to inherit from BSDF here because we use a "flattened" representation and therefore never nest these /// @@ -381,7 +464,7 @@ struct CompositeBSDF { OSL_HOSTDEVICE BSDF::Sample eval(const Vec3& wo, const Vec3& wi) const { - BSDF::Sample s = {}; + BSDF::Sample s {}; for (int i = 0; i < num_bsdfs; i++) { BSDF::Sample b = bsdfs[i]->eval_vrtl(wo, wi); b.weight *= weights[i]; @@ -454,22 +537,164 @@ struct CompositeBSDF { int num_bsdfs, num_bytes; }; +struct MediumStack { + OSL_HOSTDEVICE MediumStack() : depth(0), num_bytes(0) {} + + OSL_HOSTDEVICE Medium* current() const + { + // return the highest-priority medium + return depth > 0 ? mediums[0] : nullptr; + } + + OSL_HOSTDEVICE const MediumParams* current_params() const + { + if (depth > 0 && mediums[0]) { + const MediumParams* params = mediums[0]->get_params_vrtl(); + if (params) { + return params; + } + } + return nullptr; + } + + OSL_HOSTDEVICE bool in_medium() const { return depth > 0; } + + OSL_HOSTDEVICE int size() const { return depth; } + + OSL_HOSTDEVICE bool integrate(Ray& r, Sampler& sampler, Intersection& hit, + Color3& path_weight, Color3& path_radiance, + float& bsdf_pdf) const + { + if (depth <= 0) { + return false; + } + + Medium::Sample combined_sample { 1.0f, Color3(1.0f), Color3(1.0f) }; + bool scatter = false; + + for (int i = 0; i < depth; ++i) { + Medium::Sample s = mediums[i]->sample_vrtl(r, sampler, hit); + + combined_sample.transmittance *= s.transmittance; + combined_sample.weight *= s.weight; + + scatter = s.t < hit.t || scatter; + combined_sample.t = s.t < combined_sample.t ? s.t + : combined_sample.t; + } + + if (!(combined_sample.transmittance.x > 0 + || combined_sample.transmittance.y > 0 + || combined_sample.transmittance.z > 0)) { + return false; + } + + path_weight *= combined_sample.transmittance; + + Vec3 rand_phase = sampler.get(); + if (scatter) { + + BSDF::Sample phase_sample = mediums[0]->sample_phase_func_vrtl( + -r.direction, rand_phase.x, rand_phase.y, rand_phase.z); + if (phase_sample.pdf <= 0.0f) { + return false; + } + + path_weight *= phase_sample.weight; + r.direction = phase_sample.wi; + bsdf_pdf = phase_sample.pdf; + return true; + } + + return false; + } + + template + OSL_HOSTDEVICE bool add_medium(Medium_Args&&... args) + { + if (depth >= MaxEntries) + return false; + + if (num_bytes + sizeof(Medium_Type) > MaxSize) + return false; + + Medium_Type* new_medium = new (pool + num_bytes) + Medium_Type(std::forward(args)...); + + if (!new_medium) { + return false; + } + + const MediumParams* new_params = new_medium->get_params_vrtl(); + int insert_pos = depth; + + for (int i = 0; i < depth; ++i) { + if (!mediums[i]) { + continue; + } + + const MediumParams* existing_params = mediums[i]->get_params_vrtl(); + if (existing_params + && new_params->priority > existing_params->priority) { + insert_pos = i; + break; + } + } + + for (int j = depth; j > insert_pos; --j) { + mediums[j] = mediums[j - 1]; + } + + mediums[insert_pos] = new_medium; + depth++; + num_bytes += sizeof(Medium_Type); + + return true; + } + + OSL_HOSTDEVICE void pop_medium() + { + if (depth > 0) { + depth--; + } + } + + OSL_HOSTDEVICE bool false_intersection_with(const MediumParams& params) + { + const MediumParams* current = current_params(); + return (current + && ((params.priority < current->priority) + || (params.is_special_priority() + && current->is_special_priority() && depth > 1))); + } + +private: + /// Never try to copy this struct because it would invalidate the medium pointers + OSL_HOSTDEVICE MediumStack(const MediumStack& c); + OSL_HOSTDEVICE MediumStack& operator=(const MediumStack& c); + + enum { MaxEntries = 8 }; + enum { MaxSize = 256 * sizeof(float) }; + + Medium* mediums[MaxEntries]; + float cdf[MaxEntries]; + char pool[MaxSize]; + int depth, num_bytes; +}; + struct ShadingResult { - Color3 Le = Color3(0.0f); - CompositeBSDF bsdf = {}; - // medium data - Color3 sigma_s = Color3(0.0f); - Color3 sigma_t = Color3(0.0f); - float medium_g = 0.0f; // volumetric anisotropy - float refraction_ior = 1.0f; - int priority = 0; + Color3 Le = Color3(0.0f); + CompositeBSDF bsdf = {}; + MediumParams medium_data = {}; }; + void register_closures(ShadingSystem* shadingsys); OSL_HOSTDEVICE void process_closure(const OSL::ShaderGlobals& sg, float path_roughness, - ShadingResult& result, const ClosureColor* Ci, bool light_only); + ShadingResult& result, MediumStack& medium_stack, + const ClosureColor* Ci, bool light_only); OSL_HOSTDEVICE Vec3 process_background_closure(const ClosureColor* Ci); diff --git a/src/testrender/simpleraytracer.cpp b/src/testrender/simpleraytracer.cpp index eb7ba27e1a..49fb778639 100644 --- a/src/testrender/simpleraytracer.cpp +++ b/src/testrender/simpleraytracer.cpp @@ -968,6 +968,8 @@ SimpleRaytracer::subpixel_radiance(float x, float y, Sampler& sampler, Color3 path_radiance(0, 0, 0); int prev_id = -1; float bsdf_pdf = inf; // camera ray has only one possible direction + MediumStack medium_stack; + for (int b = 0; b <= max_bounces; b++) { ShaderGlobalsType sg; @@ -992,6 +994,10 @@ SimpleRaytracer::subpixel_radiance(float x, float y, Sampler& sampler, } break; } + + if (medium_stack.integrate(r, sampler, hit, path_weight, path_radiance, bsdf_pdf)) { + continue; + } // construct a shader globals for the hit point globals_from_hit(sg, r, hit.t, hit.id, hit.u, hit.v); @@ -1031,8 +1037,8 @@ SimpleRaytracer::subpixel_radiance(float x, float y, Sampler& sampler, #endif ShadingResult result; bool last_bounce = b == max_bounces; - process_closure(sg, r.roughness, result, (const ClosureColor*)sg.Ci, - last_bounce); + process_closure(sg, r.roughness, result, medium_stack, + (const ClosureColor*)sg.Ci, last_bounce); #ifndef __CUDACC__ const size_t lightprims_size = m_lightprims.size(); @@ -1143,7 +1149,8 @@ SimpleRaytracer::subpixel_radiance(float x, float y, Sampler& sampler, #endif ShadingResult light_result; process_closure(light_sg, r.roughness, light_result, - (const ClosureColor*)light_sg.Ci, true); + medium_stack, (const ClosureColor*)light_sg.Ci, + true); // accumulate contribution path_radiance += contrib * light_result.Le; } @@ -1161,8 +1168,13 @@ SimpleRaytracer::subpixel_radiance(float x, float y, Sampler& sampler, // Just simply use roughness as spread slope r.spread = std::max(r.spread, p.roughness); r.roughness = p.roughness; + + if (sg.backfacing) { // if exiting + medium_stack.pop_medium(); + } + if (!(path_weight.x > 0) && !(path_weight.y > 0) - && !(path_weight.z > 0)) + && !(path_weight.z > 0) && b > 10) break; // filter out all 0's or NaNs prev_id = hit.id; r.origin = sg.P; @@ -1171,6 +1183,7 @@ SimpleRaytracer::subpixel_radiance(float x, float y, Sampler& sampler, } + OSL_HOSTDEVICE Color3 SimpleRaytracer::antialias_pixel(int x, int y, ShadingContext* ctx) { diff --git a/testsuite/render-mx-anisotropic-vdf/OPTIX b/testsuite/render-mx-anisotropic-vdf/OPTIX new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testsuite/render-mx-anisotropic-vdf/anisotropic.osl b/testsuite/render-mx-anisotropic-vdf/anisotropic.osl new file mode 100644 index 0000000000..9e741fdcdc --- /dev/null +++ b/testsuite/render-mx-anisotropic-vdf/anisotropic.osl @@ -0,0 +1,19 @@ +// Copyright Contributors to the Open Shading Language project. +// SPDX-License-Identifier: BSD-3-Clause +// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage + +volume +anisotropic + [[ string description = "Volume medium material" ]] +( + color albedo = 1.0 + [[ string description = "Scattering color" ]], + float extinction = 1.0 + [[ string description = "Volume extinction coefficient" ]], + float anisotropy = 0.0 + [[ string description = "Directionality of scattering (-1=back, 0=isotropic, 1=forward)", + float UImin = -1, float UImax = 1 ]], + ) +{ + Ci = transparent() + anisotropic_vdf(albedo, extinction, anisotropy); +} \ No newline at end of file diff --git a/testsuite/render-mx-anisotropic-vdf/emitter.osl b/testsuite/render-mx-anisotropic-vdf/emitter.osl new file mode 100644 index 0000000000..80c4507f70 --- /dev/null +++ b/testsuite/render-mx-anisotropic-vdf/emitter.osl @@ -0,0 +1,31 @@ +// Copyright Contributors to the Open Shading Language project. +// SPDX-License-Identifier: BSD-3-Clause +// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage + + +surface +emitter + [[ string description = "Spot emitter material" ]] +( + float power = 1 + [[ string description = "Total power of the light", + float UImin = 0 ]], + color Cs = 1 + [[ string description = "Base color", + float UImin = 0, float UImax = 1 ]], + float spread = 90 + [[ string description = "Spread angle in degrees", + float UImin = 1, float UImax = 180 ]] +) +{ + vector wo = normalize(I); + + float cosAngle = dot(N, -wo); + + float halfSpread = radians(spread * 0.5); + float cosThreshold = cos(halfSpread); + + float falloff = (cosAngle > cosThreshold) ? 1 : 0; + + Ci = (power / (M_PI * surfacearea())) * Cs * falloff * emission(); +} \ No newline at end of file diff --git a/testsuite/render-mx-anisotropic-vdf/glossy.osl b/testsuite/render-mx-anisotropic-vdf/glossy.osl new file mode 100644 index 0000000000..dec442f928 --- /dev/null +++ b/testsuite/render-mx-anisotropic-vdf/glossy.osl @@ -0,0 +1,41 @@ +// Copyright Contributors to the Open Shading Language project. +// SPDX-License-Identifier: BSD-3-Clause +// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage + + +surface +glossy + [[ string description = "Glossy glass material" ]] +( + color Cr = 1.0 + [[ string description = "Reflectance tint", + float UImin = 0, float UImax = 1 ]], + color Ct = 1.0 + [[ string description = "Transmission tint", + float UImin = 0, float UImax = 1 ]], + float ior = 1.5 + [[ string description = "Index of refraction", + float UImin = 1.0, float UImax = 3.0 ]], + float roughness = 0.5 + [[ string description = "Roughness of the surface", + float UImin = 0, float UImax = 1 ]], + float anisotropy = 0.0 + [[ string description = "Anisotropy of the surface", + float UImin = 0, float UImax = 1 ]], + float transmission_depth = 1.0 + [[ string description = "Mean free path (0.0 is black, infinity is transparent)", + float UImin = 0, float UImax = 100 ]], + float medium_anisotropy = 1.0 + [[ string description = "Anisotropy of the medium", + float UImin = 0, float UImax = 100 ]], + int priority = 0 + [[ string description = "Priority for overlapping mediums. Zero is a special 'off' priority", + float UImin = 0, float UImax = 8 ]], // Same as MaxEntries in MediumStack + ) +{ + float alpha = roughness * roughness; + float alpha_x = alpha * (1.0 - anisotropy); + float alpha_y = alpha; + vector U = normalize(cross(N, dPdv)); + Ci = dielectric_bsdf(N, U, Cr, Ct, alpha_x, alpha_y, ior, "ggx") + medium_vdf(color(0.5), transmission_depth, Cr, 0.0, ior, priority); +} diff --git a/testsuite/render-mx-anisotropic-vdf/matte.osl b/testsuite/render-mx-anisotropic-vdf/matte.osl new file mode 100644 index 0000000000..a8c6f187e4 --- /dev/null +++ b/testsuite/render-mx-anisotropic-vdf/matte.osl @@ -0,0 +1,19 @@ +// Copyright Contributors to the Open Shading Language project. +// SPDX-License-Identifier: BSD-3-Clause +// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage + + +surface +matte + [[ string description = "Lambertian diffuse material" ]] +( + float Kd = 1 + [[ string description = "Diffuse scaling", + float UImin = 0, float UIsoftmax = 1 ]], + color Cs = 1 + [[ string description = "Base color", + float UImin = 0, float UImax = 1 ]] + ) +{ + Ci = Kd * Cs * diffuse (N); +} diff --git a/testsuite/render-mx-anisotropic-vdf/metal.osl b/testsuite/render-mx-anisotropic-vdf/metal.osl new file mode 100644 index 0000000000..055a19f07d --- /dev/null +++ b/testsuite/render-mx-anisotropic-vdf/metal.osl @@ -0,0 +1,22 @@ +// Copyright Contributors to the Open Shading Language project. +// SPDX-License-Identifier: BSD-3-Clause +// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage + + +surface +metal + [[ string description = "Lambertian diffuse material" ]] +( + float Ks = 1 + [[ string description = "Specular scaling", + float UImin = 0, float UIsoftmax = 1 ]], + float eta = 10 + [[ string description = "Metal's index of refraction (controls fresnel effect)", + float UImin = 1, float UIsoftmax = 100 ]], + color Cs = 1 + [[ string description = "Base color", + float UImin = 0, float UImax = 1 ]] + ) +{ + Ci = Ks * Cs * reflection (N, eta); +} diff --git a/testsuite/render-mx-anisotropic-vdf/ref/out-optix-alt.exr b/testsuite/render-mx-anisotropic-vdf/ref/out-optix-alt.exr new file mode 100644 index 0000000000..3f478963c4 Binary files /dev/null and b/testsuite/render-mx-anisotropic-vdf/ref/out-optix-alt.exr differ diff --git a/testsuite/render-mx-anisotropic-vdf/ref/out.exr b/testsuite/render-mx-anisotropic-vdf/ref/out.exr new file mode 100644 index 0000000000..28b36c587d Binary files /dev/null and b/testsuite/render-mx-anisotropic-vdf/ref/out.exr differ diff --git a/testsuite/render-mx-anisotropic-vdf/run.py b/testsuite/render-mx-anisotropic-vdf/run.py new file mode 100755 index 0000000000..a611f88997 --- /dev/null +++ b/testsuite/render-mx-anisotropic-vdf/run.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python + +# Copyright Contributors to the Open Shading Language project. +# SPDX-License-Identifier: BSD-3-Clause +# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage + +failthresh = 0.01 +failpercent = 1 +outputs = [ "out.exr" ] +command = testrender("-r 196 196 -aa 48 scene.xml out.exr") diff --git a/testsuite/render-mx-anisotropic-vdf/scene.xml b/testsuite/render-mx-anisotropic-vdf/scene.xml new file mode 100644 index 0000000000..5e1ddd86ca --- /dev/null +++ b/testsuite/render-mx-anisotropic-vdf/scene.xml @@ -0,0 +1,36 @@ + + + + color Cs 0.75 0.25 0.25; shader matte layer1; + + + color Cs 0.25 0.25 0.75; shader matte layer1; + + + color Cs 0.25 0.25 0.25; shader matte layer1; + + + + + color Cs 0.35 0.35 0.35; shader matte layer1; + + + + float power 90000; shader emitter layer1 + + + + param color albedo 0.85 0.85 0.85; + param float extinction 0.01; + param float anisotropy 0.25; + + shader anisotropic layer1; + + + + + + + + + diff --git a/testsuite/render-mx-dielectric-glass/ref/out-optix-alt.exr b/testsuite/render-mx-dielectric-glass/ref/out-optix-alt.exr index c918a8be17..d89d0bdc08 100644 Binary files a/testsuite/render-mx-dielectric-glass/ref/out-optix-alt.exr and b/testsuite/render-mx-dielectric-glass/ref/out-optix-alt.exr differ diff --git a/testsuite/render-mx-dielectric-glass/ref/out.exr b/testsuite/render-mx-dielectric-glass/ref/out.exr index df2a39fff8..32e332cdbf 100644 Binary files a/testsuite/render-mx-dielectric-glass/ref/out.exr and b/testsuite/render-mx-dielectric-glass/ref/out.exr differ diff --git a/testsuite/render-mx-generalized-schlick-glass/ref/out-linux-alt.exr b/testsuite/render-mx-generalized-schlick-glass/ref/out-linux-alt.exr index 1cf2687f72..7b2ebe1498 100644 Binary files a/testsuite/render-mx-generalized-schlick-glass/ref/out-linux-alt.exr and b/testsuite/render-mx-generalized-schlick-glass/ref/out-linux-alt.exr differ diff --git a/testsuite/render-mx-generalized-schlick-glass/ref/out-optix-alt.exr b/testsuite/render-mx-generalized-schlick-glass/ref/out-optix-alt.exr index 0cdbd70651..9166e94871 100644 Binary files a/testsuite/render-mx-generalized-schlick-glass/ref/out-optix-alt.exr and b/testsuite/render-mx-generalized-schlick-glass/ref/out-optix-alt.exr differ diff --git a/testsuite/render-mx-generalized-schlick/ref/out-optix-alt.exr b/testsuite/render-mx-generalized-schlick/ref/out-optix-alt.exr index bca59dbd6a..7864ea106e 100644 Binary files a/testsuite/render-mx-generalized-schlick/ref/out-optix-alt.exr and b/testsuite/render-mx-generalized-schlick/ref/out-optix-alt.exr differ diff --git a/testsuite/render-mx-generalized-schlick/ref/out.exr b/testsuite/render-mx-generalized-schlick/ref/out.exr index 46f50adc98..80f759ec5f 100644 Binary files a/testsuite/render-mx-generalized-schlick/ref/out.exr and b/testsuite/render-mx-generalized-schlick/ref/out.exr differ diff --git a/testsuite/render-mx-medium-vdf-glass/emitter.osl b/testsuite/render-mx-medium-vdf-glass/emitter.osl new file mode 100644 index 0000000000..b026b63e0b --- /dev/null +++ b/testsuite/render-mx-medium-vdf-glass/emitter.osl @@ -0,0 +1,23 @@ +// Copyright Contributors to the Open Shading Language project. +// SPDX-License-Identifier: BSD-3-Clause +// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage + + +surface +emitter + [[ string description = "Lambertian emitter material" ]] +( + float power = 1 + [[ string description = "Total power of the light", + float UImin = 0 ]], + color Cs = 1 + [[ string description = "Base color", + float UImin = 0, float UImax = 1 ]] + ) +{ + // Because emission() expects a weight in radiance, we must convert by dividing + // the power (in Watts) by the surface area and the factor of PI implied by + // uniform emission over the hemisphere. N.B.: The total power is BEFORE Cs + // filters the color! + Ci = (power / (M_PI * surfacearea())) * Cs * emission(); +} diff --git a/testsuite/render-mx-medium-vdf-glass/glossy.osl b/testsuite/render-mx-medium-vdf-glass/glossy.osl new file mode 100644 index 0000000000..212ec95000 --- /dev/null +++ b/testsuite/render-mx-medium-vdf-glass/glossy.osl @@ -0,0 +1,41 @@ +// Copyright Contributors to the Open Shading Language project. +// SPDX-License-Identifier: BSD-3-Clause +// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage + + +surface +glossy + [[ string description = "Glossy glass material" ]] +( + color Cr = 1.0 + [[ string description = "Reflectance tint", + float UImin = 0, float UImax = 1 ]], + color Ct = 1.0 + [[ string description = "Transmission tint", + float UImin = 0, float UImax = 1 ]], + float ior = 1.5 + [[ string description = "Index of refraction", + float UImin = 1.0, float UImax = 3.0 ]], + float roughness = 0.5 + [[ string description = "Roughness of the surface", + float UImin = 0, float UImax = 1 ]], + float anisotropy = 0.0 + [[ string description = "Anisotropy of the surface", + float UImin = 0, float UImax = 1 ]], + float transmission_depth = 1.0 + [[ string description = "Mean free path (0.0 is black, infinity is transparent)", + float UImin = 0, float UImax = 100 ]], + float medium_anisotropy = 1.0 + [[ string description = "Anisotropy of the medium", + float UImin = 0, float UImax = 100 ]], + int priority = 0 + [[ string description = "Priority for overlapping mediums. Zero is a special 'off' priority", + float UImin = 0, float UImax = 8 ]], // Same as MaxEntries in MediumStack + ) +{ + float alpha = roughness * roughness; + float alpha_x = alpha * (1.0 - anisotropy); + float alpha_y = alpha; + vector U = normalize(cross(N, dPdv)); + Ci = dielectric_bsdf(N, U, Cr, Ct, alpha_x, alpha_y, ior, "ggx") + medium_vdf(color(0.5), transmission_depth, color(0.5), 0.0, ior, priority); +} diff --git a/testsuite/render-mx-medium-vdf-glass/matte.osl b/testsuite/render-mx-medium-vdf-glass/matte.osl new file mode 100644 index 0000000000..a8c6f187e4 --- /dev/null +++ b/testsuite/render-mx-medium-vdf-glass/matte.osl @@ -0,0 +1,19 @@ +// Copyright Contributors to the Open Shading Language project. +// SPDX-License-Identifier: BSD-3-Clause +// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage + + +surface +matte + [[ string description = "Lambertian diffuse material" ]] +( + float Kd = 1 + [[ string description = "Diffuse scaling", + float UImin = 0, float UIsoftmax = 1 ]], + color Cs = 1 + [[ string description = "Base color", + float UImin = 0, float UImax = 1 ]] + ) +{ + Ci = Kd * Cs * diffuse (N); +} diff --git a/testsuite/render-mx-medium-vdf-glass/ref/out.exr b/testsuite/render-mx-medium-vdf-glass/ref/out.exr new file mode 100644 index 0000000000..81ca5431ff Binary files /dev/null and b/testsuite/render-mx-medium-vdf-glass/ref/out.exr differ diff --git a/testsuite/render-mx-medium-vdf-glass/run.py b/testsuite/render-mx-medium-vdf-glass/run.py new file mode 100755 index 0000000000..dd73b98dc2 --- /dev/null +++ b/testsuite/render-mx-medium-vdf-glass/run.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python + +# Copyright Contributors to the Open Shading Language project. +# SPDX-License-Identifier: BSD-3-Clause +# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage + +failthresh = 0.01 +failpercent = 1 +outputs = [ "out.exr" ] +command = testrender("-r 240 240 -aa 24 scene.xml out.exr") diff --git a/testsuite/render-mx-medium-vdf-glass/scene.xml b/testsuite/render-mx-medium-vdf-glass/scene.xml new file mode 100644 index 0000000000..db024c4817 --- /dev/null +++ b/testsuite/render-mx-medium-vdf-glass/scene.xml @@ -0,0 +1,86 @@ + + + + color Cs 0.75 0.25 0.25; shader matte layer1; + + + color Cs 0.25 0.25 0.75; shader matte layer1; + + + color Cs 0.25 0.25 0.25; shader matte layer1; + + + + + float power 26000; shader emitter layer1 + + + + + + + color Cr 1.0 1.0 1.0; + float roughness 0.1; + float anisotropy 0.0; + float ior 1.1; + int priority 0; + float transmission_depth 100.0; + float medium_anisotropy -1.0; + int priority 0; + shader glossy layer1; + + + + + color Cr 1.0 1.0 1.0; + float roughness 0.1; + float anisotropy 0.0; + float ior 1.1; + int priority 0; + float transmission_depth 100.0; + float medium_anisotropy -1.0; + int priority 0; + shader glossy layer1; + + + + + + color Cr 0.0 0.0 1.0; + float roughness 0.1; + float anisotropy 0.0; + float ior 1.2; + int priority 0; + float transmission_depth 500.0; + float medium_anisotropy 0.0; + int priority 0; + shader glossy layer1; + + + + + color Cr 0.0 1.0 0.0; + float roughness 0.2; + float anisotropy 0.0; + float ior 1.1; + float transmission_depth 500.0; + float medium_anisotropy 0.0; + int priority 1; + shader glossy layer1; + + + + + color Cr 1.0 0.0 0.0; + float roughness 0.3; + float anisotropy 0.0; + float ior 1.1; + float transmission_depth 500.0; + float medium_anisotropy 0.0; + int priority 2; + shader glossy layer1; + + + + + diff --git a/testsuite/render-mx-medium-vdf/OPTIX b/testsuite/render-mx-medium-vdf/OPTIX new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testsuite/render-mx-medium-vdf/envmap.osl b/testsuite/render-mx-medium-vdf/envmap.osl new file mode 100644 index 0000000000..14f09243b2 --- /dev/null +++ b/testsuite/render-mx-medium-vdf/envmap.osl @@ -0,0 +1,19 @@ +// Copyright Contributors to the Open Shading Language project. +// SPDX-License-Identifier: BSD-3-Clause +// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage + +shader envmap( + color sky = color(0.7,0.8,0.9), + color horizon = color(0.3,0.6,0.9), + color sun = color(0.9,0.8,0.7), + vector sun_dir = vector(0,1,1), + float sun_angle = 5.0) +{ + vector dir = normalize(I); + vector sd = normalize(sun_dir); + color c = mix(horizon, sky, dir.y * dir.y); + float cos_ang = cos(radians(sun_angle / 2)); + if (dot(dir, normalize(sun_dir)) > cos_ang) + c += sun / (1 - cos_ang); // normalize + Ci = c * background(); +} diff --git a/testsuite/render-mx-medium-vdf/matte.osl b/testsuite/render-mx-medium-vdf/matte.osl new file mode 100644 index 0000000000..a8c6f187e4 --- /dev/null +++ b/testsuite/render-mx-medium-vdf/matte.osl @@ -0,0 +1,19 @@ +// Copyright Contributors to the Open Shading Language project. +// SPDX-License-Identifier: BSD-3-Clause +// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage + + +surface +matte + [[ string description = "Lambertian diffuse material" ]] +( + float Kd = 1 + [[ string description = "Diffuse scaling", + float UImin = 0, float UIsoftmax = 1 ]], + color Cs = 1 + [[ string description = "Base color", + float UImin = 0, float UImax = 1 ]] + ) +{ + Ci = Kd * Cs * diffuse (N); +} diff --git a/testsuite/render-mx-medium-vdf/medium.osl b/testsuite/render-mx-medium-vdf/medium.osl new file mode 100644 index 0000000000..81a623c218 --- /dev/null +++ b/testsuite/render-mx-medium-vdf/medium.osl @@ -0,0 +1,31 @@ +// Copyright Contributors to the Open Shading Language project. +// SPDX-License-Identifier: BSD-3-Clause +// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage + + +volume +medium + [[ string description = "Volume medium material" ]] +( + color albedo = 1.0 + [[ string description = "Scattering color", + float UImin = 0, float UImax = 1 ]], + float transmission_depth = 0.5 + [[ string description = "Mean free path (0.0 is black, infinity is transparent)", + float UImin = 0, float UImax = 1 ]], + color transmission_color = 1.0 + [[ string description = "Transmission color (volume absorption tint)", + float UImin = 0, float UImax = 1 ]], + float anisotropy = 0.0 + [[ string description = "Directionality of scattering (-1=back, 0=isotropic, 1=forward)", + float UImin = -1, float UImax = 1 ]], + float ior = 1.0 + [[ string description = "Index of refraction", + float UImin = 0, float UImax = 1 ]], + int priority = 0 + [[ string description = "Priority for overlapping mediums. Zero is a special 'off' priority", + float UImin = 0, float UImax = 8 ]], // Same as MaxEntries in MediumStack + ) +{ + Ci = transparent() + medium_vdf(albedo, transmission_depth, transmission_color, anisotropy, ior, priority); +} \ No newline at end of file diff --git a/testsuite/render-mx-medium-vdf/ref/out-optix-alt.exr b/testsuite/render-mx-medium-vdf/ref/out-optix-alt.exr new file mode 100644 index 0000000000..bcd8c4191b Binary files /dev/null and b/testsuite/render-mx-medium-vdf/ref/out-optix-alt.exr differ diff --git a/testsuite/render-mx-medium-vdf/ref/out.exr b/testsuite/render-mx-medium-vdf/ref/out.exr new file mode 100644 index 0000000000..7cdcd311bc Binary files /dev/null and b/testsuite/render-mx-medium-vdf/ref/out.exr differ diff --git a/testsuite/render-mx-medium-vdf/run.py b/testsuite/render-mx-medium-vdf/run.py new file mode 100755 index 0000000000..a2bbf4ee67 --- /dev/null +++ b/testsuite/render-mx-medium-vdf/run.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python + +# Copyright Contributors to the Open Shading Language project. +# SPDX-License-Identifier: BSD-3-Clause +# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage + +failthresh = 0.01 +failpercent = 1 +outputs = [ "out.exr" ] +command = testrender("-v -r 196 196 -aa 96 scene.xml out.exr") diff --git a/testsuite/render-mx-medium-vdf/scene.xml b/testsuite/render-mx-medium-vdf/scene.xml new file mode 100644 index 0000000000..abcd9cbb1b --- /dev/null +++ b/testsuite/render-mx-medium-vdf/scene.xml @@ -0,0 +1,88 @@ + + + + + vector sun_dir 0.0 0.75 1.0; + shader envmap layer1; + + + + + color Cs 0.25 0.25 0.25; + shader matte layer1; + + + + + + + + param color albedo 0.5 0.5 0.5; + param float transmission_depth 1.0; + param color transmission_color 1.0 0.2 0.2; + param float anisotropy 0.0; + param float ior 0.0; + param int priority 1; + shader medium layer1; + + + + + param color albedo 0.5 0.5 0.5; + param float transmission_depth 1.0; + param color transmission_color 0.2 0.4 1.0; + param float anisotropy 0.0; + param float ior 0.0; + param int priority 1; + shader medium layer1; + + + + + param color albedo 0.5 0.5 0.5; + param float transmission_depth 1.0; + param color transmission_color 0.2 1.0 0.2; + param float anisotropy 0.0; + param float ior 1.0; + param int priority 1; + shader medium layer1; + + + + + + param color albedo 0.5 0.5 0.5; + param float transmission_depth 10.0; + param color transmission_color 0.5 0.5 0.5; + param float anisotropy -0.5; + param float ior 1.0; + param int priority 1; + shader medium layer1; + + + + + param color albedo 0.5 0.5 0.5; + param float transmission_depth 10.0; + param color transmission_color 0.5 0.5 0.5; + param float anisotropy 0.0; + param float ior 1.0; + param int priority 1; + shader medium layer1; + + + + + param color albedo 0.5 0.5 0.5; + param float transmission_depth 10.0; + param color transmission_color 0.5 0.5 0.5; + param float anisotropy 0.5; + param float ior 1.0; + param int priority 1; + shader medium layer1; + + + + + + \ No newline at end of file