Skip to content

Commit

Permalink
Fix reflect/refract decision for Layered materials by taking the albe…
Browse files Browse the repository at this point in the history
…do of the substrate into account
  • Loading branch information
sherholz-intel authored and johguenther committed Sep 18, 2024
1 parent 9f9332b commit 5e5b0b4
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 16 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Version History
*first* hit (as opposed to `OSP_FB_NORMAL`, which holds the normal
of the first *non-specular* hit for denoising)
- Channel `OSP_FB_POSITION` holds the world-space position of the first hit
- Improved sampling of layered materials

### Changes in v3.2.0:

Expand Down
27 changes: 17 additions & 10 deletions modules/cpu/render/bsdfs/DielectricLayer.ih
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ OSPRAY_END_ISPC_NAMESPACE
// Eval macros

#define DIELECTRICLAYER_EVAL( \
dl_name, scatteringType, substrate_bsdf, substrate_fn) \
dl_name, albedo, scatteringType, substrate_bsdf, substrate_fn) \
const varying DielectricLayer *uniform dl = \
(const varying DielectricLayer *uniform) & dl_name; \
\
Expand All @@ -97,7 +97,8 @@ OSPRAY_END_ISPC_NAMESPACE
\
/* Fresnel term */ \
float cosThetaO1; /* positive */ \
float Fo = fresnelDielectricEx(cosThetaO, cosThetaO1, dl->eta) * dl->weight; \
float F = fresnelDielectricEx(cosThetaO, cosThetaO1, dl->eta); \
float Fo = F * dl->weight; \
\
float cosThetaI = dot(wi, getN(&dl->super)); \
float cosThetaI1; /* positive */ \
Expand Down Expand Up @@ -125,14 +126,16 @@ OSPRAY_END_ISPC_NAMESPACE
* rcp(1.f - dl->Favg); /* for diffuse substrates [Kelemen and \
Szirmay-Kalos, 2001] */ \
substrate.value = substrate.value * T; \
substrate.pdf *= (1.f - Fo)
/* TODO: add considering the absorption of the coating if present */ \
const float coatPickProb = Fo / ((1.f - F) * reduce_max(albedo) + Fo); \
substrate.pdf *= (1.f - coatPickProb)

#define DIELECTRICLAYER_EVAL_GET() substrate

// Sample macros

#define DIELECTRICLAYER_SAMPLE( \
dl_name, scatteringType, substrate_bsdf, substrate_fn) \
dl_name, albedo, scatteringType, substrate_bsdf, substrate_fn) \
const varying DielectricLayer *uniform dl = \
(const varying DielectricLayer *uniform) & dl_name; \
BSDF_SampleRes res; \
Expand All @@ -143,18 +146,22 @@ OSPRAY_END_ISPC_NAMESPACE
\
/* Fresnel term */ \
float cosThetaO1; /* positive */ \
float Fo = fresnelDielectricEx(cosThetaO, cosThetaO1, dl->eta) * dl->weight; \
float F = fresnelDielectricEx(cosThetaO, cosThetaO1, dl->eta); \
float Fo = F * dl->weight; \
\
if (ss < Fo) { \
/* TODO: add considering the absorption of the coating if present */ \
const float coatPickProb = Fo / ((1.f - F) * reduce_max(albedo) + Fo); \
if (ss < coatPickProb) { \
/* Sample the coating */ \
res.type = BSDF_SPECULAR_REFLECTION; \
res.wi = reflect(wo, getN(&dl->super), cosThetaO); \
res.pdf = inf; \
res.weight = make_vec3f(1.f); \
res.weight = make_vec3f(Fo / coatPickProb); \
} else { \
/* Sample the substrate */ \
/* Ignore refraction */ \
float ss1 = (ss - Fo) * rcp(1.f - Fo); /* reallocate sample */ \
float ss1 = \
(ss - coatPickProb) * rcp(1.f - coatPickProb); /* reallocate sample */ \
res = substrate_fn(substrate_bsdf, wo, s, ss1); \
if (reduce_max(res.weight) <= 0.f) \
return res; \
Expand Down Expand Up @@ -184,8 +191,8 @@ OSPRAY_END_ISPC_NAMESPACE
T = (1.f - Fo) * (1.f - Fi) \
* rcp(1.f - dl->Favg); /* for diffuse substrates [Kelemen and \
Szirmay-Kalos, 2001] */ \
res.weight = res.weight * (T * rcp(1.f - Fo)); \
res.pdf *= (1.f - Fo); \
res.weight = res.weight * (T * rcp(1.f - coatPickProb)); \
res.pdf *= (1.f - coatPickProb); \
}

#define DIELECTRICLAYER_SAMPLE_GET() res
11 changes: 8 additions & 3 deletions modules/cpu/render/bsdfs/MicrofacetDielectricLayer.ih
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ OSPRAY_END_ISPC_NAMESPACE
// Eval macros

#define MICROFACETDIELECTRICLAYER_EVAL( \
mdl_name, scatteringType, substrate_bsdf, substrate_fn) \
mdl_name, albedo, scatteringType, substrate_bsdf, substrate_fn) \
const varying MicrofacetDielectricLayer *uniform mdl = \
(const varying MicrofacetDielectricLayer *uniform) & mdl_name; \
\
Expand Down Expand Up @@ -200,7 +200,9 @@ OSPRAY_END_ISPC_NAMESPACE
Szirmay-Kalos, 2001] */ \
substrate.value = substrate.value * T; \
\
float coatPickProb = Ro; \
/* TODO: add considering the absorption of the coating if present */ \
float coatPickProb = \
mdl->weight * Ro / ((1.f - Ro) * reduce_max(albedo) + mdl->weight * Ro); \
float substratePickProb = 1.f - coatPickProb; \
\
if (cosThetaI > 0.f) { \
Expand Down Expand Up @@ -246,6 +248,7 @@ OSPRAY_END_ISPC_NAMESPACE
// Sample macros

#define MICROFACETDIELECTRICLAYER_SAMPLE(mdl_name, \
albedo, \
scatteringType, \
substrate_bsdf, \
substrate_eval, \
Expand Down Expand Up @@ -274,7 +277,9 @@ OSPRAY_END_ISPC_NAMESPACE
vec3f wh; \
BSDF_EvalRes substrate; \
\
float coatPickProb = Ro; \
/* TODO: add considering the absorption of the coating if present */ \
float coatPickProb = \
mdl->weight * Ro / ((1.f - Ro) * reduce_max(albedo) + mdl->weight * Ro); \
float substratePickProb = 1.f - coatPickProb; \
\
if (ss < coatPickProb) { \
Expand Down
19 changes: 16 additions & 3 deletions modules/cpu/render/materials/CarPaint.ispc
Original file line number Diff line number Diff line change
Expand Up @@ -268,12 +268,15 @@ __noinline BSDF_SampleRes BaseBSDF_sample(
inline BSDF_EvalRes DielectricLayerBSDF_eval(
const varying CarPaint_BSDF *uniform self, const vec3f &wo, const vec3f &wi)
{
vec3f albedo = (self->flakeMask) ? self->conductor.super.albedo
: self->baseDiffuse.super.albedo;

BSDFScatteringType scatteringType = (self->flakeMask)
? self->conductor.super.scatteringType
: self->baseDiffuse.super.scatteringType;

DIELECTRICLAYER_EVAL(
self->dielectricLayer, scatteringType, self, BaseBSDF_eval);
self->dielectricLayer, albedo, scatteringType, self, BaseBSDF_eval);
return DIELECTRICLAYER_EVAL_GET();
}

Expand All @@ -283,12 +286,15 @@ inline BSDF_SampleRes DielectricLayerBSDF_sample(
const vec2f &s,
float ss)
{
vec3f albedo = (self->flakeMask) ? self->conductor.super.albedo
: self->baseDiffuse.super.albedo;

BSDFScatteringType scatteringType = (self->flakeMask)
? self->conductor.super.scatteringType
: self->baseDiffuse.super.scatteringType;

DIELECTRICLAYER_SAMPLE(
self->dielectricLayer, scatteringType, self, BaseBSDF_sample);
self->dielectricLayer, albedo, scatteringType, self, BaseBSDF_sample);
return DIELECTRICLAYER_SAMPLE_GET();
}

Expand All @@ -297,12 +303,15 @@ inline BSDF_SampleRes DielectricLayerBSDF_sample(
inline BSDF_EvalRes MicrofacetDielectricLayerBSDF_eval(
const varying CarPaint_BSDF *uniform self, const vec3f &wo, const vec3f &wi)
{
vec3f albedo = (self->flakeMask) ? self->conductor.super.albedo
: self->baseDiffuse.super.albedo;

BSDFScatteringType scatteringType = (self->flakeMask)
? self->conductor.super.scatteringType
: self->baseDiffuse.super.scatteringType;

MICROFACETDIELECTRICLAYER_EVAL(
self->dielectricLayer, scatteringType, self, BaseBSDF_eval);
self->dielectricLayer, albedo, scatteringType, self, BaseBSDF_eval);
return MICROFACETDIELECTRICLAYER_EVAL_GET();
}

Expand All @@ -312,11 +321,15 @@ inline BSDF_SampleRes MicrofacetDielectricLayerBSDF_sample(
const vec2f &s,
float ss)
{
vec3f albedo = (self->flakeMask) ? self->conductor.super.albedo
: self->baseDiffuse.super.albedo;

BSDFScatteringType scatteringType = (self->flakeMask)
? self->conductor.super.scatteringType
: self->baseDiffuse.super.scatteringType;

MICROFACETDIELECTRICLAYER_SAMPLE(self->dielectricLayer,
albedo,
scatteringType,
self,
BaseBSDF_eval,
Expand Down
2 changes: 2 additions & 0 deletions modules/cpu/render/materials/MetallicPaint.ispc
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ SYCL_EXTERNAL BSDF_EvalRes MetallicPaint_BSDF_eval(
(const varying MetallicPaint_BSDF *uniform)super;

DIELECTRICLAYER_EVAL(self->dielectricLayer,
self->multi.super.albedo,
self->multi.super.scatteringType,
&self->multi.super,
MultiBSDF_eval);
Expand All @@ -140,6 +141,7 @@ SYCL_EXTERNAL BSDF_SampleRes MetallicPaint_BSDF_sample(
(const varying MetallicPaint_BSDF *uniform)super;

DIELECTRICLAYER_SAMPLE(self->dielectricLayer,
self->multi.super.albedo,
self->multi.super.scatteringType,
&self->multi.super,
MultiBSDF_sample);
Expand Down
4 changes: 4 additions & 0 deletions modules/cpu/render/materials/Plastic.ispc
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ inline BSDF_EvalRes DielectricLayerBSDF_eval(
const varying Plastic_BSDF *uniform self, const vec3f &wo, const vec3f &wi)
{
DIELECTRICLAYER_EVAL(self->dielectricLayer,
self->lambert.albedo,
self->lambert.scatteringType,
&self->lambert,
Lambert_eval);
Expand All @@ -87,6 +88,7 @@ inline BSDF_SampleRes DielectricLayerBSDF_sample(
float ss)
{
DIELECTRICLAYER_SAMPLE(self->dielectricLayer,
self->lambert.albedo,
self->lambert.scatteringType,
&self->lambert,
Lambert_sample);
Expand All @@ -99,6 +101,7 @@ inline BSDF_EvalRes MicrofacetDielectricLayerBSDF_eval(
const varying Plastic_BSDF *uniform self, const vec3f &wo, const vec3f &wi)
{
MICROFACETDIELECTRICLAYER_EVAL(self->dielectricLayer,
self->lambert.albedo,
self->lambert.scatteringType,
&self->lambert,
Lambert_eval);
Expand All @@ -112,6 +115,7 @@ inline BSDF_SampleRes MicrofacetDielectricLayerBSDF_sample(
float ss)
{
MICROFACETDIELECTRICLAYER_SAMPLE(self->dielectricLayer,
self->lambert.albedo,
self->lambert.scatteringType,
&self->lambert,
Lambert_eval,
Expand Down
8 changes: 8 additions & 0 deletions modules/cpu/render/materials/Principled.ispc
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,7 @@ inline BSDF_EvalRes Plastic_DielectricLayerBSDF_eval(
const vec3f &wi)
{
DIELECTRICLAYER_EVAL(self->dielectricLayer,
self->diffuse.super.albedo,
self->diffuse.super.scatteringType,
&self->diffuse,
DiffuseBSDF_eval);
Expand All @@ -680,6 +681,7 @@ inline BSDF_SampleRes Plastic_DielectricLayerBSDF_sample(
float ss)
{
DIELECTRICLAYER_SAMPLE(self->dielectricLayer,
self->diffuse.super.albedo,
self->diffuse.super.scatteringType,
&self->diffuse,
DiffuseBSDF_sample);
Expand All @@ -694,6 +696,7 @@ inline BSDF_EvalRes Plastic_MicrofacetDielectricLayerBSDF_eval(
const vec3f &wi)
{
MICROFACETDIELECTRICLAYER_EVAL(self->dielectricLayer,
self->diffuse.super.albedo,
self->diffuse.super.scatteringType,
&self->diffuse,
DiffuseBSDF_eval);
Expand All @@ -707,6 +710,7 @@ inline BSDF_SampleRes Plastic_MicrofacetDielectricLayerBSDF_sample(
float ss)
{
MICROFACETDIELECTRICLAYER_SAMPLE(self->dielectricLayer,
self->diffuse.super.albedo,
self->diffuse.super.scatteringType,
&self->diffuse,
DiffuseBSDF_eval,
Expand Down Expand Up @@ -894,6 +898,7 @@ inline BSDF_EvalRes ClearCoat_DielectricLayerBSDF_eval(
const vec3f &wi)
{
DIELECTRICLAYER_EVAL(self->dielectricLayer,
self->base.super.albedo,
self->base.super.scatteringType,
&self->base,
BaseBSDF_eval);
Expand All @@ -907,6 +912,7 @@ inline BSDF_SampleRes ClearCoat_DielectricLayerBSDF_sample(
float ss)
{
DIELECTRICLAYER_SAMPLE(self->dielectricLayer,
self->base.super.albedo,
self->base.super.scatteringType,
&self->base,
BaseBSDF_sample);
Expand All @@ -921,6 +927,7 @@ inline BSDF_EvalRes ClearCoat_MicrofacetDielectricLayerBSDF_eval(
const vec3f &wi)
{
MICROFACETDIELECTRICLAYER_EVAL(self->dielectricLayer,
self->base.super.albedo,
self->base.super.scatteringType,
&self->base,
BaseBSDF_eval);
Expand All @@ -934,6 +941,7 @@ inline BSDF_SampleRes ClearCoat_MicrofacetDielectricLayerBSDF_sample(
float ss)
{
MICROFACETDIELECTRICLAYER_SAMPLE(self->dielectricLayer,
self->base.super.albedo,
self->base.super.scatteringType,
&self->base,
BaseBSDF_eval,
Expand Down

0 comments on commit 5e5b0b4

Please sign in to comment.