commit d2427ce9dec95a44e38cc9db5812a0f518b90221
parent 549eeb8ef88321a1a37938d2a94e4edc30b3a63c
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Thu, 23 Mar 2017 15:47:21 +0100
Update the BxDF sample API
On B<x|S>DF sampling return the type of the sampled component.
Diffstat:
16 files changed, 120 insertions(+), 44 deletions(-)
diff --git a/src/ssf.h b/src/ssf.h
@@ -49,6 +49,14 @@ struct ssf_bxdf; /* Bidirectional <Reflec|Transmit>tance Distribution Function *
struct ssf_fresnel; /* Equation of the Fresnel term */
struct ssf_microfacet_distribution;
+enum ssf_bxdf_flag {
+ SSF_REFLECTION = BIT(0),
+ SSF_TRANSMISSION = BIT(1),
+ SSF_SPECULAR = BIT(2),
+ SSF_DIFFUSE = BIT(3),
+ SSF_GLOSSY = BIT(4)
+};
+
/* Generic BxDF type descriptor. Note that by convention the outgoing direction
* `wo' and the incoming direction `wi' point outward the surface. Furthermore,
* `wo' and the normal N must point on the same side of the surface. As a
@@ -67,6 +75,7 @@ struct ssf_bxdf_type {
const double wo[3], /* Normalized outgoing direction */
const double N[3], /* Normalized surface normal */
double wi[3], /* Sampled normalized incoming direction */
+ int* type, /* Type of the sampled component. Combination of ssf_bxdf_flag */
double* pdf); /* PDF to sample wi wrt wo */
/* Evaluate the BxDF wrt to wo and wi */
@@ -292,6 +301,7 @@ ssf_bsdf_sample
const double wo[3], /* Normalized outgoing direction */
const double N[3], /* Normalized surface normal */
double wi[3], /* Sampled normalized incoming direction */
+ int* type, /* Type of the sampled component. Combination of ssf_bxdf_flag */
double* pdf); /* PDF to sample wi wrt wo */
SSF_API double
@@ -338,6 +348,7 @@ ssf_bxdf_sample
const double wo[3], /* Normalized outgoing direction */
const double N[3], /* Normalized surface normal */
double wi[3], /* Sampled normalized incoming direction. */
+ int* type, /* Sampled BxDF type. Combination of ssf_bxdf_flag */
double* pdf); /* PDF of the sampled direction */
SSF_API double
diff --git a/src/ssf_bsdf.c b/src/ssf_bsdf.c
@@ -148,6 +148,7 @@ ssf_bsdf_sample
const double wo[3],
const double N[3],
double wi[3],
+ int* type,
double* out_pdf)
{
double cumul[MAX_BxDFs];
@@ -155,15 +156,16 @@ ssf_bsdf_sample
double r;
double pdf;
size_t i;
- ASSERT(bsdf && rng && wi && N && wo && out_pdf);
+ ASSERT(bsdf && rng && wi && N && wo && type && out_pdf);
ASSERT(d3_is_normalized(wo) && d3_is_normalized(N));
if(!bsdf->nbxdfs) {
*out_pdf = 0;
+ *type = 0;
return 0;
}
if(bsdf->nbxdfs == 1) {
- return ssf_bxdf_sample(bsdf->bxdfs[0], rng, wo, N, wi, out_pdf);
+ return ssf_bxdf_sample(bsdf->bxdfs[0], rng, wo, N, wi, type, out_pdf);
}
bsdf_normalize_weights(bsdf);
@@ -181,7 +183,7 @@ ssf_bsdf_sample
}
/* Sample a direction from the selected component */
- R = ssf_bxdf_sample(bsdf->bxdfs[i], rng, wo, N, wi, &pdf);
+ R = ssf_bxdf_sample(bsdf->bxdfs[i], rng, wo, N, wi, type, &pdf);
*out_pdf = pdf*bsdf->weights[i];
return R;
}
diff --git a/src/ssf_bxdf.c b/src/ssf_bxdf.c
@@ -120,11 +120,12 @@ ssf_bxdf_sample
const double wo[3],
const double N[3],
double wi[3],
+ int* type,
double* pdf)
{
- ASSERT(bxdf && rng && wo && N && wi && pdf);
+ ASSERT(bxdf && rng && wo && N && wi && type && pdf);
ASSERT(d3_is_normalized(wo) && d3_is_normalized(N));
- return bxdf->type.sample(bxdf->data, rng, wo, N, wi, pdf);
+ return bxdf->type.sample(bxdf->data, rng, wo, N, wi, type, pdf);
}
double
diff --git a/src/ssf_lambertian_reflection.c b/src/ssf_lambertian_reflection.c
@@ -60,16 +60,18 @@ lambertian_reflection_sample
const double wo[3],
const double N[3],
double wi[3],
+ int* type,
double* pdf)
{
double sample[4];
- ASSERT(data && rng && wo && N && wi);
+ ASSERT(data && rng && wo && N && wi && type && pdf);
ASSERT(d3_is_normalized(wo) && d3_is_normalized(N) && d3_dot(wo, N) > 0);
(void)wo;
ssp_ran_hemisphere_cos(rng, N, sample);
d3_set(wi, sample);
*pdf = sample[3];
+ *type = SSF_REFLECTION | SSF_DIFFUSE;
return ((struct lambertian_reflection*)data)->reflectivity;
}
diff --git a/src/ssf_microfacet_reflection.c b/src/ssf_microfacet_reflection.c
@@ -86,6 +86,7 @@ microfacet_reflection_sample
const double wo[3],
const double N[3],
double wi[3],
+ int* type,
double* pdf)
{
struct microfacet_reflection* bxdf = data;
@@ -93,13 +94,14 @@ microfacet_reflection_sample
double wh[3];
double pdf_wh;
double R;
- ASSERT(data && wo && N && wi);
+ ASSERT(data && wo && N && wi && pdf && type);
ASSERT(d3_is_normalized(wo) && d3_is_normalized(N) && d3_dot(wo, N) > 0);
ASSERT(bxdf->distrib && bxdf->fresnel);
ssf_microfacet_distribution_sample(bxdf->distrib, rng, wo, N, wh, &pdf_wh);
reflect(dir, wo, wh);
*pdf = pdf_wh / (4.0*fabs(d3_dot(wo, wh)));
+ *type = SSF_REFLECTION | SSF_GLOSSY;
R = d3_dot(dir, N) > 0 ? ssf_fresnel_eval(bxdf->fresnel, d3_dot(dir, wh)) : 0;
d3_set(wi, dir);
return R;
@@ -131,6 +133,7 @@ microfacet2_reflection_sample
const double wo[3],
const double N[3],
double wi[3],
+ int* type,
double* pdf)
{
struct microfacet_reflection* bxdf = data;
@@ -138,7 +141,7 @@ microfacet2_reflection_sample
double wh[3];
double p;
double troughput = 1;
- ASSERT(data && wo && N && wi);
+ ASSERT(data && wo && N && wi && pdf && type);
ASSERT(d3_is_normalized(wo) && d3_is_normalized(N) && d3_dot(N, wo) > 0.0);
ASSERT(bxdf->distrib);
@@ -163,6 +166,7 @@ microfacet2_reflection_sample
}
*pdf = NaN;
+ *type = SSF_REFLECTION | SSF_GLOSSY;
d3_set(wi, dir);
return troughput;
}
diff --git a/src/ssf_specular_reflection.c b/src/ssf_specular_reflection.c
@@ -49,18 +49,20 @@ specular_reflection_sample
const double wo[3],
const double N[3],
double wi[3],
+ int* type,
double* pdf)
{
struct specular_reflection* brdf = data;
double cos_wo_N;
double cos_wi_N;
- ASSERT(rng && wi && N && wo && pdf);
+ ASSERT(rng && wi && N && wo && type && pdf);
ASSERT(d3_is_normalized(wo) && d3_is_normalized(N) && d3_dot(wo, N) > 0);
(void)rng;
/* Reflect the outgoing direction wo with respect to the surface normal N */
reflect(wi, wo, N);
*pdf = INF;
+ *type = SSF_REFLECTION | SSF_SPECULAR;
cos_wi_N = cos_wo_N = d3_dot(wo, N);
return ssf_fresnel_eval(brdf->fresnel, cos_wi_N);
diff --git a/src/ssf_specular_transmission.c b/src/ssf_specular_transmission.c
@@ -52,12 +52,13 @@ specular_transmission_sample
const double wo[3],
const double N[3],
double wi[3],
+ int* type,
double* pdf)
{
struct specular_transmission* btdf = bxdf;
double eta;
double cos_wi_N;
- ASSERT(rng && wo && N && wi && pdf);
+ ASSERT(rng && wo && N && wi && type && pdf);
ASSERT(d3_is_normalized(wo) && d3_is_normalized(N) && d3_dot(wo, N) > 0);
(void)rng;
@@ -66,11 +67,14 @@ specular_transmission_sample
eta = btdf->eta_i / btdf->eta_t;
if(!refract(wi, wo, N, eta)) { /* Total internal reflection */
- reflect(wi, wo, N); /* TODO ensure this */
+ reflect(wi, wo, N);
+ *pdf = INF;
+ *type = SSF_REFLECTION | SSF_SPECULAR;
return 0.0;
}
cos_wi_N = d3_dot(wi, N);
*pdf = INF;
+ *type = SSF_TRANSMISSION | SSF_SPECULAR;
return 1.0 - ssf_fresnel_eval(btdf->fresnel, fabs(cos_wi_N));
}
diff --git a/src/ssf_thin_specular_dielectric.c b/src/ssf_thin_specular_dielectric.c
@@ -55,6 +55,7 @@ thin_specular_dielectric_sample
const double wo[3],
const double N[3],
double wi[3],
+ int* type,
double* pdf)
{
struct thin_specular_dielectric* bsdf = bxdf;
@@ -66,7 +67,7 @@ thin_specular_dielectric_sample
double R, T;
double rho1, rho2, rho2_sqr;
double tau, tau_sqr;
- ASSERT(bxdf && rng && wi && N && wo);
+ ASSERT(bxdf && rng && wi && N && wo && type && pdf);
ASSERT(d3_is_normalized(wo) && d3_is_normalized(N));
ASSERT(d3_dot(wo, N) > -1.e-6);
(void)rng;
@@ -74,6 +75,8 @@ thin_specular_dielectric_sample
eta = bsdf->eta_i / bsdf->eta_t;
if(!refract(wt, wo, N, eta)) { /* Total internal reflection */
reflect(wi, wo, N);
+ *pdf = INF;
+ *type = SSF_SPECULAR | SSF_REFLECTION;
return 1;
}
fresnel = bsdf->fresnel;
@@ -106,9 +109,11 @@ thin_specular_dielectric_sample
/* Importance sample the BTDF wrt R */
if(ssp_rng_canonical(rng) < R) { /* Sample the reflective part */
reflect(wi, wo, N);
+ *type = SSF_SPECULAR | SSF_REFLECTION;
return 1;
} else { /* Sample the transmissive part */
d3_minus(wi, wo);
+ *type = SSF_SPECULAR | SSF_TRANSMISSION;
return T;
}
}
diff --git a/src/test_ssf_bsdf.c b/src/test_ssf_bsdf.c
@@ -34,6 +34,7 @@ main(int argc, char** argv)
double sum, sqr_sum;
double sample[4];
size_t i;
+ int type;
(void)argc, (void)argv;
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
@@ -67,14 +68,16 @@ main(int argc, char** argv)
d3_normalize(wo, d3(wo, 1, 1, 0));
d3(N, 0.0, 1.0, 0.0);
- R = ssf_bsdf_sample(bsdf, rng, wo, N, wi, &pdf);
+ R = ssf_bsdf_sample(bsdf, rng, wo, N, wi, &type, &pdf);
+ CHECK(type, SSF_SPECULAR | SSF_REFLECTION);
CHECK(eq_eps(R, ssf_fresnel_eval(fresnel, d3_dot(wi, N)), 1.e-6), 1);
CHECK(ssf_bsdf_eval(bsdf, wo, N, wi), 0);
CHECK(ssf_bsdf_pdf(bsdf, wo, N, wi), 0);
CHECK(ssf_specular_reflection_setup(bxdf, fresnel), RES_OK);
- R = ssf_bsdf_sample(bsdf, rng, wo, N, wi, &pdf);
+ R = ssf_bsdf_sample(bsdf, rng, wo, N, wi, &type, &pdf);
CHECK(eq_eps(R, ssf_fresnel_eval(fresnel, d3_dot(wi, N)), 1.e-6), 1);
+ CHECK(type, SSF_SPECULAR | SSF_REFLECTION);
CHECK(ssf_bsdf_add(bsdf, bxdf2, 1), RES_OK);
@@ -85,7 +88,8 @@ main(int argc, char** argv)
ssp_ran_hemisphere_uniform(rng, N, sample);
d3_set(wo, sample);
FOR_EACH(i, 0, NSTEPS) {
- double weight = ssf_bsdf_sample(bsdf, rng, wo, N, wi, &pdf);
+ double weight = ssf_bsdf_sample(bsdf, rng, wo, N, wi, &type, &pdf);
+ CHECK(type, SSF_SPECULAR | SSF_REFLECTION);
CHECK(ssf_bsdf_eval(bsdf, wo, N, wi), 0);
CHECK(ssf_bsdf_pdf(bsdf, wo, N, wi), 0);
sum += weight;
@@ -99,7 +103,8 @@ main(int argc, char** argv)
CHECK(ssf_bsdf_clear(NULL), RES_BAD_ARG);
CHECK(ssf_bsdf_clear(bsdf), RES_OK);
- CHECK(ssf_bsdf_sample(bsdf, rng, wo, N, wi, &pdf), 0.0);
+ CHECK(ssf_bsdf_sample(bsdf, rng, wo, N, wi, &type, &pdf), 0.0);
+ CHECK(type, 0);
CHECK(pdf, 0.0);
CHECK(ssf_bsdf_ref_put(bsdf), RES_OK);
diff --git a/src/test_ssf_bxdf.c b/src/test_ssf_bxdf.c
@@ -58,6 +58,7 @@ bxdf_sample
const double wo[3],
const double N[3],
double wi[3],
+ int* type,
double* pdf)
{
struct bxdf* BxDF = bxdf;
@@ -66,6 +67,7 @@ bxdf_sample
CHECK(d3_eq(BxDF->wo, wo), 1);
CHECK(d3_eq(BxDF->N, N), 1);
d3(wi, 1.0, 2.0, 3.0);
+ *type = 314;
*pdf = 4;
return BxDF->reflectivity;
}
@@ -116,6 +118,7 @@ main(int argc, char** argv)
double N[3];
double wi[4];
double pdf;
+ int i;
(void)argc, (void)argv;
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
@@ -186,11 +189,13 @@ main(int argc, char** argv)
data->rng = rng;
data->reflectivity = 0.1234;
- CHECK(ssf_bxdf_sample(bxdf, rng, wo, N, wi, &pdf), 0.1234);
- CHECK(ssf_bxdf_sample(bxdf, rng, wo, N, wi, &pdf), 0.1234);
+ CHECK(ssf_bxdf_sample(bxdf, rng, wo, N, wi, &i, &pdf), 0.1234);
+ CHECK(ssf_bxdf_sample(bxdf, rng, wo, N, wi, &i, &pdf), 0.1234);
+ CHECK(i, 314);
+ CHECK(pdf, 4);
data->reflectivity = 0.314;
- CHECK(ssf_bxdf_sample(bxdf, rng, wo, N, wi, &pdf), 0.314);
+ CHECK(ssf_bxdf_sample(bxdf, rng, wo, N, wi, &i, &pdf), 0.314);
d3_normalize(wi, wi);
d3_set(data->wi, wi);
diff --git a/src/test_ssf_lambertian_reflection.c b/src/test_ssf_lambertian_reflection.c
@@ -36,6 +36,7 @@ main(int argc, char** argv)
double pdf;
double R;
size_t i;
+ int type;
(void)argc, (void)argv;
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
@@ -54,14 +55,16 @@ main(int argc, char** argv)
d3(N, 0.0, 0.0, 1.0);
d3_normalize(wo, d3(wo, 1.0, 0.0, 1.0));
- R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &pdf);
+ R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &type, &pdf);
CHECK(eq_eps(wi[2]/PI, pdf, 1.e-6), 1);
CHECK(R, 0);
+ CHECK(type, SSF_DIFFUSE|SSF_REFLECTION);
CHECK(ssf_lambertian_reflection_setup(brdf, 0.7), RES_OK);
- R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &pdf);
+ R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &type, &pdf);
CHECK(eq_eps(R, 0.7, 1.e-6), 1);
CHECK(eq_eps(pdf, d3_dot(wi, N)/PI, 1.e-6), 1);
+ CHECK(type, SSF_DIFFUSE|SSF_REFLECTION);
d3_normalize(wo, d3(wo, 1.0, 0.0, 1.0));
N[0] = ssp_rng_uniform_double(rng, -1, 1);
@@ -74,10 +77,11 @@ main(int argc, char** argv)
sum = sum_sqr = 0;
FOR_EACH(i, 0, NSTEPS) {
double cos_wi_N;
- R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &pdf) / PI;
+ R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &type, &pdf) / PI;
cos_wi_N = d3_dot(wi, N);
CHECK(eq_eps(R, 0.7/PI, 1.e-6), 1);
CHECK(eq_eps(cos_wi_N/PI, pdf, 1.e-6), 1);
+ CHECK(type, SSF_DIFFUSE|SSF_REFLECTION);
sum += cos_wi_N;
sum_sqr += cos_wi_N * cos_wi_N;
}
@@ -91,10 +95,11 @@ main(int argc, char** argv)
double cos_wi_N;
double w;
- R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &pdf)/PI;
+ R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &type, &pdf)/PI;
cos_wi_N = d3_dot(wi, N);
CHECK(eq_eps(R, 0.7/PI, 1.e-6), 1);
CHECK(eq_eps(cos_wi_N/PI, pdf, 1.e-6), 1);
+ CHECK(type, SSF_DIFFUSE|SSF_REFLECTION);
w = cos_wi_N*cos_wi_N;
sum += w;
sum_sqr += w*w;
@@ -108,10 +113,11 @@ main(int argc, char** argv)
FOR_EACH(i, 0, NSTEPS) {
double val;
- R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &pdf);
+ R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &type, &pdf);
CHECK(eq_eps(R, 0.7, 1.e-6), 1);
val = ssf_bxdf_eval(brdf, wo, N, wi) * d3_dot(wi, N);
CHECK(eq_eps(val, R * pdf, 1.e-6), 1);
+ CHECK(type, SSF_DIFFUSE|SSF_REFLECTION);
}
CHECK(ssf_bxdf_ref_put(brdf), RES_OK);
diff --git a/src/test_ssf_microfacet_reflection.c b/src/test_ssf_microfacet_reflection.c
@@ -57,7 +57,9 @@ main(int argc, char** argv)
ssp_ran_hemisphere_cos(rng, N, wo);
FOR_EACH(i, 0, NSTEPS) {
double wi[3], pdf;
- CHECK(ssf_bxdf_sample(bxdf, rng, wo, N, wi, &pdf), 1);
+ int type;
+ CHECK(ssf_bxdf_sample(bxdf, rng, wo, N, wi, &type, &pdf), 1);
+ CHECK(type, SSF_GLOSSY | SSF_REFLECTION);
CHECK(d3_dot(wi, N) > 0, 1);
}
diff --git a/src/test_ssf_specular_reflection.c b/src/test_ssf_specular_reflection.c
@@ -32,6 +32,7 @@ main(int argc, char** argv)
double pdf;
double R; /* Directional reflectance */
size_t i;
+ int type;
(void)argc, (void)argv;
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
@@ -50,40 +51,47 @@ main(int argc, char** argv)
d3(N, 0.0, 1.0, 0.0);
d3_normalize(wo, d3(wo, 1.0, 1.0, 0.0));
- R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &pdf);
+ R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &type, &pdf);
CHECK(eq_eps(R, ssf_fresnel_eval(fresnel, d3_dot(N, wi)), 1.e-6), 1);
CHECK(IS_INF(pdf), 1);
+ CHECK(type, SSF_SPECULAR|SSF_REFLECTION);
d3_normalize(wo, d3(wo, 1.0, 1.0, 0.0));
CHECK(ssf_specular_reflection_setup(brdf, fresnel), RES_OK);
- R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &pdf);
+ R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &type, &pdf);
CHECK(eq_eps(R, ssf_fresnel_eval(fresnel, d3_dot(N, wi)), 1.e-6), 1);
CHECK(IS_INF(pdf), 1);
CHECK(d3_eq_eps(d3(wo, -wo[0], wo[1], 0.0), wi, 1.e-6), 1);
+ CHECK(type, SSF_SPECULAR|SSF_REFLECTION);
CHECK(ssf_bxdf_eval(brdf, wo, N, wi), 0.0);
CHECK(ssf_bxdf_pdf(brdf, wo, N, wi), 0.0);
d3(wo, 0.0, 1.0, 0.0);
- R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &pdf);
+ R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &type, &pdf);
CHECK(eq_eps(R, ssf_fresnel_eval(fresnel, d3_dot(N, wi)), 1.e-6), 1);
CHECK(IS_INF(pdf), 1);
CHECK(d3_eq_eps(d3(wo, 0.0, 1.0, 0.0), wi, 1.e-6), 1);
+ CHECK(type, SSF_SPECULAR|SSF_REFLECTION);
d3_normalize(wo, d3(wo, -1.0, 1.0, 0.0));
- R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &pdf);
+ R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &type, &pdf);
CHECK(eq_eps(R, ssf_fresnel_eval(fresnel, d3_dot(N, wi)), 1.e-6), 1);
CHECK(IS_INF(pdf), 1);
CHECK(d3_eq_eps(d3(wo, -wo[0], wo[1], 0.0), wi, 1.e-6), 1);
+ CHECK(type, SSF_SPECULAR|SSF_REFLECTION);
wo[0] = ssp_rng_uniform_double(rng, -1, 1);
wo[1] = ssp_rng_uniform_double(rng, 0, 1);
wo[2] = ssp_rng_uniform_double(rng, -1, 1);
d3_normalize(wo, wo);
- R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &pdf);
+ R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &type, &pdf);
+ CHECK(type, SSF_SPECULAR|SSF_REFLECTION);
FOR_EACH(i, 0, NSTEPS) {
- CHECK(eq_eps(ssf_bxdf_sample(brdf, rng, wo, N, wi, &pdf), R, 1.e-6), 1);
+ CHECK(eq_eps(ssf_bxdf_sample
+ (brdf, rng, wo, N, wi, &type, &pdf), R, 1.e-6), 1);
+ CHECK(type, SSF_SPECULAR|SSF_REFLECTION);
}
CHECK(ssf_bxdf_ref_put(brdf), RES_OK);
diff --git a/src/test_ssf_specular_transmission.c b/src/test_ssf_specular_transmission.c
@@ -31,6 +31,7 @@ main(int argc, char** argv)
double N[3];
double pdf;
double R;
+ int type;
(void)argc, (void)argv;
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
@@ -53,36 +54,42 @@ main(int argc, char** argv)
d3(N, 0.0, 1.0, 0.0);
d3_normalize(wo, d3(wo, 1.0, 1.0, 0.0));
- R = ssf_bxdf_sample(btdf, rng, wo, N, wi, &pdf);
+ R = ssf_bxdf_sample(btdf, rng, wo, N, wi, &type, &pdf);
CHECK(eq_eps(R, ssf_fresnel_eval(fresnel, fabs(d3_dot(N, wi))), 1.e-6), RES_OK);
CHECK(d3_eq_eps(wi, d3_minus(tmp, wo), 1.e-6), 0);
CHECK(wi[1] < 0, 1);
CHECK(IS_INF(pdf), 1);
+ CHECK(type, SSF_SPECULAR|SSF_TRANSMISSION);
CHECK(ssf_bxdf_eval(btdf, wo, N, wi), 0.0);
CHECK(ssf_bxdf_pdf(btdf, wo, N, wi), 0.0);
d3(wo, 0.0, 1.0, 0.0);
- R = ssf_bxdf_sample(btdf, rng, wo, N, wi, &pdf);
+ R = ssf_bxdf_sample(btdf, rng, wo, N, wi, &type, &pdf);
CHECK(eq_eps(R, ssf_fresnel_eval(fresnel, fabs(d3_dot(N, wi))), 1.e-6), RES_OK);
CHECK(IS_INF(pdf), 1);
CHECK(d3_eq_eps(wi, d3_minus(tmp, wo), 1.e-6), 1);
+ CHECK(type, SSF_SPECULAR|SSF_TRANSMISSION);
d3_normalize(wo, d3(wo, -1.0, 1.0, 0.0));
- R = ssf_bxdf_sample(btdf, rng, wo, N, wi, &pdf);
+ R = ssf_bxdf_sample(btdf, rng, wo, N, wi, &type, &pdf);
reflect(tmp, wi, N);
+ CHECK(type, SSF_SPECULAR|SSF_TRANSMISSION);
d3_normalize(wo, d3(wo, 1.0, 1.0, 0.0));
- R = ssf_bxdf_sample(btdf, rng, wo, N, wi, &pdf);
+ R = ssf_bxdf_sample(btdf, rng, wo, N, wi, &type, &pdf);
CHECK(d3_eq_eps(wi, tmp, 1.e-6), 1);
+ CHECK(type, SSF_SPECULAR|SSF_TRANSMISSION);
d3_normalize(wo, d3(wo, -1, 1.e-6, 0));
- R = ssf_bxdf_sample(btdf, rng, wo, N, wi, &pdf);
+ R = ssf_bxdf_sample(btdf, rng, wo, N, wi, &type, &pdf);
CHECK(eq_eps(R, 0, 1.e-3), 1);
+ CHECK(type, SSF_SPECULAR|SSF_TRANSMISSION);
/* Check total internal reflection */
CHECK(ssf_specular_transmission_setup(btdf, 1.5, 1.00027), RES_OK);
- R = ssf_bxdf_sample(btdf, rng, wo, N, wi, &pdf);
+ R = ssf_bxdf_sample(btdf, rng, wo, N, wi, &type, &pdf);
CHECK(eq_eps(R, 0, 1.e-3), 1);
+ CHECK(type, SSF_SPECULAR|SSF_REFLECTION);
CHECK(ssf_fresnel_ref_put(fresnel), RES_OK);
CHECK(ssf_bxdf_ref_put(btdf), RES_OK);
diff --git a/src/test_ssf_thin_specular_dielectric.c b/src/test_ssf_thin_specular_dielectric.c
@@ -34,6 +34,7 @@ main(int argc, char** argv)
double pdf;
double R; /* Directional reflectance */
size_t i;
+ int type;
(void)argc, (void)argv;
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
@@ -80,8 +81,9 @@ main(int argc, char** argv)
d3(N, 0.0, 1.0, 0.0);
d3_normalize(wo, d3(wo, 1.0, 1.0, 0.0));
- R = ssf_bxdf_sample(bsdf, rng, wo, N, wi, &pdf);
+ R = ssf_bxdf_sample(bsdf, rng, wo, N, wi, &type, &pdf);
NCHECK(R, 0);
+ NCHECK(type & SSF_SPECULAR, 0);
CHECK(IS_INF(pdf), 1);
CHECK(d3_eq_eps(wi, d3(tmp, -wo[0], wo[1], 0), 1.e-6)
|| d3_eq_eps(wi, d3(tmp, -wo[0], -wo[1], 0), 1.e-6), 1);
@@ -90,24 +92,27 @@ main(int argc, char** argv)
CHECK(ssf_bxdf_pdf(bsdf, wo, N, wi), 0.0);
d3(wo, 0.0, 1.0, 0.0);
- R = ssf_bxdf_sample(bsdf, rng, wo, N, wi, &pdf);
+ R = ssf_bxdf_sample(bsdf, rng, wo, N, wi, &type, &pdf);
NCHECK(R, 0);
CHECK(IS_INF(pdf), 1);
CHECK(d3_eq_eps(wi, d3(tmp, -wo[0], -wo[1], 0), 1.e-6), 1);
+ CHECK(type, SSF_SPECULAR | SSF_TRANSMISSION);
d3(wo, 1.0, 0.0, 0.0);
- R = ssf_bxdf_sample(bsdf, rng, wo, N, wi, &pdf);
+ R = ssf_bxdf_sample(bsdf, rng, wo, N, wi, &type, &pdf);
NCHECK(R, 0);
CHECK(IS_INF(pdf), 1);
CHECK(d3_eq_eps(wi, d3(tmp, -wo[0], wo[1], 0), 1.e-6), 1);
+ CHECK(type, SSF_SPECULAR | SSF_REFLECTION);
/* Check total internal reflection, i.e. no transmission */
d3_normalize(wo, d3(wo, 1, 0.0000001, 0));
CHECK(ssf_thin_specular_dielectric_setup(bsdf, 0, 1.4, 1.0, 1), RES_OK);
- R = ssf_bxdf_sample(bsdf, rng, wo, N, wi, &pdf);
+ R = ssf_bxdf_sample(bsdf, rng, wo, N, wi, &type, &pdf);
NCHECK(R, 0);
CHECK(IS_INF(pdf), 1);
CHECK(d3_eq_eps(wi, d3(tmp, -wo[0], wo[1], 0), 1.e-6), 1);
+ CHECK(type, SSF_SPECULAR | SSF_REFLECTION);
wo[0] = ssp_rng_uniform_double(rng, -1, 1);
wo[1] = ssp_rng_uniform_double(rng, -1, 1);
@@ -117,10 +122,16 @@ main(int argc, char** argv)
d3_minus(refract, wo);
FOR_EACH(i, 0, NSTEPS) {
- R = ssf_bxdf_sample(bsdf, rng, wo, N, wi, &pdf);
+ R = ssf_bxdf_sample(bsdf, rng, wo, N, wi, &type, &pdf);
NCHECK(R, 0);
CHECK(IS_INF(pdf), 1);
- CHECK(d3_eq_eps(wi, reflect, 1.e-6) || d3_eq_eps(wi, refract, 1e-6), 1);
+ if(d3_eq_eps(wi, reflect, 1.e-6)) {
+ CHECK(type, SSF_SPECULAR | SSF_REFLECTION);
+ } else if(d3_eq_eps(wi, refract, 1e-6), 1) {
+ CHECK(type, SSF_SPECULAR | SSF_TRANSMISSION);
+ } else {
+ FATAL("Unexpected value.\n");
+ }
}
CHECK(ssp_rng_ref_put(rng), RES_OK);
diff --git a/src/test_ssf_utils.h b/src/test_ssf_utils.h
@@ -51,9 +51,10 @@ bxdf_dummy_sample
const double w[3],
const double N[3],
double dir[3],
+ int* type,
double* pdf)
{
- (void)bxdf, (void)rng, (void)w, (void)N, (void)dir, (void)pdf;
+ (void)bxdf, (void)rng, (void)w, (void)N, (void)dir, (void)type, (void)pdf;
return 0.0;
}