Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/cmake/testing.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
6 changes: 6 additions & 0 deletions src/libbsdl/include/BSDL/tools.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@

BSDL_ENTER_NAMESPACE

BSDL_INLINE float
MAX(float a, float b)
{
return std::max(a, b);
}

BSDL_INLINE float
MAX_ABS_XYZ(const Imath::V3f& v)
{
Expand Down
2 changes: 1 addition & 1 deletion src/testrender/optixraytracer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1175,7 +1175,7 @@ OptixRaytracer::processPrintfBuffer(void* buffer_data, size_t buffer_size)
if (format[j] == '%') {
fmt_string = "%";
bool format_end_found = false;
for (size_t i = 0; !format_end_found; i++) {
for (; !format_end_found; ) {
j++;
fmt_string += format[j];
switch (format[j]) {
Expand Down
190 changes: 149 additions & 41 deletions src/testrender/shading.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@


#include "shading.h"
#include "OSL/oslconfig.h"
#include <OSL/genclosure.h>
#include "optics.h"
#include "sampling.h"
Expand All @@ -12,6 +13,7 @@
#include <BSDL/MTX/bsdf_dielectric_impl.h>
#include <BSDL/SPI/bsdf_thinlayer_impl.h>
#include <BSDL/spectrum_impl.h>
#include <BSDL/SPI/bsdf_volume_impl.h>

using namespace OSL;

Expand Down Expand Up @@ -1513,6 +1515,51 @@ struct ZeltnerBurleySheen final : public BSDF, MxSheenParams {
}
};

struct HenyeyGreenstein : public bsdl::spi::VolumeLobe<BSDLLobe> {
using Base = bsdl::spi::VolumeLobe<BSDLLobe>;

OSL_HOSTDEVICE HenyeyGreenstein(const Data& data, const Vec3& wo,
float path_roughness)
: Base(this,
bsdl::BsdfGlobals(wo,
Vec3(0), // Nf
Vec3(0), // Ngf
false,
path_roughness,
1.0f, // outer_ior
0), // hero wavelength off
data)
{
}

OSL_HOSTDEVICE BSDF::Sample eval(const Vec3& wo, const Vec3& wi) const
{
bsdl::Sample s = Base::eval_impl(Base::frame.local(wo),
Base::frame.local(wi));
return { wi, s.weight.toRGB(0), s.pdf, s.roughness };
}
OSL_HOSTDEVICE BSDF::Sample sample(const Vec3& wo, float rx, float ry,
float rz) const
{
bsdl::Sample s = Base::sample_impl(Base::frame.local(wo),
{ rx, ry, rz });
return { Base::frame.world(s.wi), s.weight.toRGB(0), s.pdf,
s.roughness };
}
};


OSL_HOSTDEVICE BSDF::Sample MediumParams::sample_phase_func(const Vec3& wo, float rx,
float ry, float rz) const {
if (is_empty) {
return { Vec3(1.0f), Color3(1.0f), 0.0f, 0.0f };
}

HenyeyGreenstein::Data data { medium_g, medium_g, 0.0f };
HenyeyGreenstein phase_func(data, wo, 0.0f);
return phase_func.sample(wo, rx, ry, rz);
}

OSL_HOSTDEVICE Color3
evaluate_layer_opacity(const ShaderGlobalsType& sg, float path_roughness,
const ClosureColor* closure)
Expand Down Expand Up @@ -1606,8 +1653,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;
Expand Down Expand Up @@ -1649,37 +1696,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<MxAnisotropicVdfParams>();
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; // always intersect

result.medium_data.is_empty = result.medium_data.is_vaccum();

closure = nullptr;
break;
}
case MX_MEDIUM_VDF_ID: {
const ClosureComponent* comp = closure->as_comp();
Color3 cw = weight * comp->w;
const auto& params = *comp->as<MxMediumVdfParams>();
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;

// when both albedo and transmission_color are black, this is
// a vacuum medium used only to carry the IOR for dielectric
// surfaces.
bool is_vacuum = is_black(params.albedo)
&& is_black(params.transmission_color);

if (is_vacuum) {
result.medium_data.sigma_t = Color3(0.0f);
result.medium_data.sigma_s = Color3(0.0f);
result.medium_data.is_empty = true;
} else {
const float epsilon = 1e-10f;
result.medium_data.sigma_t = Color3(
-OIIO::fast_log(fmaxf(params.transmission_color.x, epsilon)),
-OIIO::fast_log(fmaxf(params.transmission_color.y, epsilon)),
-OIIO::fast_log(fmaxf(params.transmission_color.z, epsilon))
);

result.medium_data.sigma_t *= cw / params.transmission_depth;
result.medium_data.sigma_s = params.albedo
* result.medium_data.sigma_t;
result.medium_data.is_empty = result.medium_data.is_vaccum();
}

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;

closure = nullptr;
break;
}
case MxDielectric::closureid(): {
const ClosureComponent* comp = closure->as_comp();
const MxDielectric::Data& params = *comp->as<MxDielectric::Data>();
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.get_current_params();
if (current_params
&& result.medium_data.priority
<= current_params->priority) {
result.medium_data.refraction_ior
= current_params->refraction_ior;
}
}
closure = nullptr;
break;
Expand All @@ -1688,13 +1770,23 @@ process_medium_closure(const ShaderGlobalsType& sg, float path_roughness,
const ClosureComponent* comp = closure->as_comp();
const auto& params = *comp->as<MxGeneralizedSchlickParams>();
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.get_current_params();
if (current_params
&& result.medium_data.priority
<= current_params->priority) {
result.medium_data.refraction_ior
= current_params->refraction_ior;
}
}
closure = nullptr;
break;
Expand All @@ -1711,8 +1803,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");
Expand Down Expand Up @@ -1845,9 +1938,16 @@ process_bsdf_closure(const ShaderGlobalsType& sg, float path_roughness,
case MxDielectric::closureid(): {
const MxDielectric::Data& params
= *comp->as<MxDielectric::Data>();
ok = result.bsdf.add_bsdf<MxDielectric>(cw, params, -sg.I,
sg.backfacing,
path_roughness);

if (medium_stack.false_intersection_with(
result.medium_data)) {
ok = result.bsdf.add_bsdf<Transparent>(cw);
} else {
ok = result.bsdf.add_bsdf<MxDielectric>(cw, params,
-sg.I,
sg.backfacing,
path_roughness);
}
break;
}
case MxConductor::closureid(): {
Expand All @@ -1860,15 +1960,21 @@ process_bsdf_closure(const ShaderGlobalsType& sg, float path_roughness,
case MX_GENERALIZED_SCHLICK_ID: {
const MxGeneralizedSchlickParams& params
= *comp->as<MxGeneralizedSchlickParams>();
if (is_black(params.transmission_tint))
ok = result.bsdf.add_bsdf<MxMicrofacet<
MxGeneralizedSchlickParams, GGXDist, false>>(cw,
params,
1.0f);
else
ok = result.bsdf.add_bsdf<MxMicrofacet<
MxGeneralizedSchlickParams, GGXDist, true>>(
cw, params, result.refraction_ior);

if (medium_stack.false_intersection_with(
result.medium_data)) {
ok = result.bsdf.add_bsdf<Transparent>(cw);
} else {
if (is_black(params.transmission_tint)) {
ok = result.bsdf.add_bsdf<MxMicrofacet<
MxGeneralizedSchlickParams, GGXDist, false>>(
cw, params, 1.0f);
} else {
ok = result.bsdf.add_bsdf<MxMicrofacet<
MxGeneralizedSchlickParams, GGXDist, true>>(
cw, params, result.medium_data.refraction_ior);
}
}
break;
};
case MX_TRANSLUCENT_ID: {
Expand Down Expand Up @@ -1957,11 +2063,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
Expand Down Expand Up @@ -2022,5 +2131,4 @@ 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_NAMESPACE_END
Loading