commit c2b41c82fcd97a70809fd6cab03a29b618046c8e
parent 4b6658c8ca704f84aa45a57726b0c5de8cdf6dd2
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Tue, 4 Oct 2016 21:13:54 +0200
The pdf of the sampled specular reflection is infinity
Rewrite some comments and add some tests to the lambertian BxDF
Diffstat:
6 files changed, 28 insertions(+), 45 deletions(-)
diff --git a/src/ssf.h b/src/ssf.h
@@ -55,12 +55,8 @@ struct ssf_bxdf_type {
res_T (*init)(struct mem_allocator* allocator, void* bxdf);
void (*release)(void* bxdf);
- /* Sample an incoming direction `wi' with respect to the outgoing direction
- * `wo'. Return the direction reflectance along 'wi'. Note that the
- * directional reflectance is *not* the value of the BxDF wrt to 'wo'
- * and 'wi'. It is the ratio between the reflected and the incoming radiance
- * (i.e. Li / Lo), while the BxDF is the constant of proportionality between
- * the reflected radiance and the incoming irradiance (i.e. Lo / Eo) */
+ /* Sample a direction `wi' wrt `wo' whose pdf is BxDF(wo, wi) |wi.n|. Return
+ * the value of BxDF(wo, wi) */
double
(*sample)
(void* bxdf,
@@ -78,6 +74,7 @@ struct ssf_bxdf_type {
const double N[3], /* Normalized surface normal */
const double wi[3]);/* Normalized incoming direction */
+ /* Probability density function */
double
(*pdf)
(void* bxdf,
@@ -200,10 +197,9 @@ SSF_API res_T
ssf_bsdf_clear
(struct ssf_bsdf* bsdf);
-/* Return the directional reflectance, i.e. the ratio between the reflected
- * and the incoming radiance (Li/Lo). Note that this is different to the
- * BSDF value that is the ratio between the reflected radiance and the incoming
- * irradiance, i.e. Li/Eo */
+/* Sample a direction `wi' wrt `wo' whose pdf is BSDF(wo, wi) |wi.n|. Return
+ * the directionnal reflectance, i.e. pdf to be reflected in *any* direction
+ * wrt to the incident direction `wi' */
SSF_API double
ssf_bsdf_sample
(struct ssf_bsdf* bsdf,
@@ -220,7 +216,7 @@ ssf_bsdf_eval
const double N[3], /* Normalized surface normal */
const double wi[3]); /* Normalized incoming direction */
-SSF_API double
+SSF_API double /* Probability density function*/
ssf_bsdf_pdf
(struct ssf_bsdf* bsdf,
const double wo[3], /* Normalized incoming direction */
@@ -247,10 +243,9 @@ SSF_API res_T
ssf_bxdf_ref_put
(struct ssf_bxdf* bxdf);
-/* Return the directionnal reflectance, i.e. the ratio between the reflected
- * and the incoming radiance (Li/Lo). Note that this is different to the
- * BxDF value that is the ratio between the reflected radiance and the incoming
- * irradiance, i.e. Li/Eo */
+/* Sample a direction `wi' wrt `wo' whose pdf is BxDF(wo, wi) |wi.n|. Return
+ * the directionnal reflectance, i.e. pdf to be reflected in *any* direction
+ * wrt to the incident direction `wi' */
SSF_API double
ssf_bxdf_sample
(struct ssf_bxdf* bxdf,
@@ -267,7 +262,7 @@ ssf_bxdf_eval
const double N[3], /* Normalized surface normal */
const double wi[3]);/* Normalized incoming direction */
-SSF_API double /* Probability */
+SSF_API double /* Probability density function */
ssf_bxdf_pdf
(struct ssf_bxdf* bxdf,
const double wo[3], /* Normalized outgoing direction */
diff --git a/src/ssf_bsdf.c b/src/ssf_bsdf.c
@@ -151,7 +151,7 @@ ssf_bsdf_sample
double* out_pdf)
{
double cumul[MAX_BxDFs];
- double R_wi;
+ double R;
double r;
double pdf;
size_t i;
@@ -181,9 +181,9 @@ ssf_bsdf_sample
}
/* Sample a direction from the selected component */
- R_wi = ssf_bxdf_sample(bsdf->bxdfs[i], rng, wo, N, wi, &pdf);
+ R = ssf_bxdf_sample(bsdf->bxdfs[i], rng, wo, N, wi, &pdf);
*out_pdf = pdf*bsdf->weights[i];
- return R_wi;
+ return R;
}
double
@@ -210,13 +210,13 @@ ssf_bsdf_eval
const double N[3],
const double wi[3])
{
- double R = 0;
+ double fr = 0;
size_t i;
ASSERT(bsdf);
bsdf_normalize_weights(bsdf);
FOR_EACH(i, 0, bsdf->nbxdfs) {
- R += bsdf->weights[i] * ssf_bxdf_eval(bsdf->bxdfs[i], wo, N, wi);
+ fr += bsdf->weights[i] * ssf_bxdf_eval(bsdf->bxdfs[i], wo, N, wi);
}
- return R;
+ return fr;
}
diff --git a/src/ssf_microfacet_reflection.c b/src/ssf_microfacet_reflection.c
@@ -120,14 +120,6 @@ microfacet_reflection_pdf
return pdf_wh / (4.0*fabs(d3_dot(wo, wh)));
}
-static FINLINE double
-microfacet_reflection_rho(void* data, const double wo[3], const double N[3])
-{
- ASSERT(data && wo && N);
- (void)data, (void)wo, (void)N;
- return 0; /* TODO */
-}
-
/*******************************************************************************
* Microfacet 2 functions
******************************************************************************/
diff --git a/src/ssf_specular_reflection.c b/src/ssf_specular_reflection.c
@@ -60,10 +60,9 @@ specular_reflection_sample
/* Reflect the outgoing direction wo with respect to the surface normal N */
reflect(wi, wo, N);
- *pdf = 1.0; /* pdf */
+ *pdf = INF;
cos_wi_N = cos_wo_N = d3_dot(wo, N);
- /* TODO check this */
return cos_wo_N > 0 ? ssf_fresnel_eval(brdf->fresnel, cos_wi_N) : 0;
}
diff --git a/src/test_ssf_lambertian_reflection.c b/src/test_ssf_lambertian_reflection.c
@@ -115,16 +115,13 @@ main(int argc, char** argv)
CHECK(eq_eps(E, 2.0/4.0, 2.0*SE), 1);
CHECK(eq_eps(SE, 1.0/sqrt((double)NSTEPS) * sqrt(1.0/3.0 - 1.0/4.0), 1.e-6), 1);
- sum = sum_sqr = 0;
FOR_EACH(i, 0, NSTEPS) {
+ double val;
R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &pdf);
- sum += R;
- sum_sqr += R*R;
+ 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);
}
- E = sum/(double)NSTEPS;
- V = MMAX(sum_sqr/(double)NSTEPS - E*E, 0);
- SE = sqrt(V/(double)NSTEPS);
- CHECK(eq_eps(E, 0.7, SE), 1);
CHECK(ssf_bxdf_ref_put(brdf), RES_OK);
CHECK(ssf_bxdf_ref_put(dummy), RES_OK);
diff --git a/src/test_ssf_specular_reflection.c b/src/test_ssf_specular_reflection.c
@@ -30,7 +30,7 @@ main(int argc, char** argv)
double wo[3], wi[3];
double N[3];
double pdf;
- double R;
+ double R; /* Directional reflectance */
size_t i;
(void)argc, (void)argv;
@@ -52,13 +52,13 @@ main(int argc, char** argv)
d3_normalize(wo, d3(wo, 1.0, 1.0, 0.0));
R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &pdf);
CHECK(eq_eps(R, ssf_fresnel_eval(fresnel, d3_dot(N, wi)), 1.e-6), 1);
- CHECK(pdf, 1);
+ CHECK(IS_INF(pdf), 1);
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);
CHECK(eq_eps(R, ssf_fresnel_eval(fresnel, d3_dot(N, wi)), 1.e-6), 1);
- CHECK(pdf, 1);
+ CHECK(IS_INF(pdf), 1);
CHECK(d3_eq_eps(d3(wo, -wo[0], wo[1], 0.0), wi, 1.e-6), 1);
CHECK(ssf_bxdf_eval(brdf, wo, N, wi), 0.0);
@@ -67,19 +67,19 @@ main(int argc, char** argv)
d3(wo, 0.0, 1.0, 0.0);
R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &pdf);
CHECK(eq_eps(R, ssf_fresnel_eval(fresnel, d3_dot(N, wi)), 1.e-6), 1);
- CHECK(pdf, 1);
+ CHECK(IS_INF(pdf), 1);
CHECK(d3_eq_eps(d3(wo, 0.0, 1.0, 0.0), wi, 1.e-6), 1);
d3_normalize(wo, d3(wo, -1.0, 1.0, 0.0));
R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &pdf);
CHECK(eq_eps(R, ssf_fresnel_eval(fresnel, d3_dot(N, wi)), 1.e-6), 1);
- CHECK(pdf, 1);
+ CHECK(IS_INF(pdf), 1);
CHECK(d3_eq_eps(d3(wo, -wo[0], wo[1], 0.0), wi, 1.e-6), 1);
d3(wo, 0.0, -1.0, 0.0);
R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &pdf);
CHECK(eq_eps(R, 0, 1.e-6), 1);
- CHECK(pdf, 1);
+ CHECK(IS_INF(pdf), 1);
CHECK(d3_eq_eps(d3(wo, 0.0, -1.0, 0.0), wi, 1.e-6), 1);
d3(wo, 1.0, 0.0, 0.0);