commit 863ed1ee241b1aae6870a7d30cc721f7341e6ef4
parent e5495a3b45c2da69df4101938b7b1b390fc84a6c
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Thu, 22 Sep 2016 12:08:55 +0200
Add and test the "rho" B<x|S>DF function
rho(wo) is the integral over 2PI of B<x|S>DF(wo, wi) |wi.N|
Diffstat:
11 files changed, 117 insertions(+), 15 deletions(-)
diff --git a/src/ssf.h b/src/ssf.h
@@ -78,9 +78,18 @@ struct ssf_bxdf_type {
const double N[3], /* Normalized surface normal */
const double wi[3]);/* Normalized incoming direction */
+ /* rho(wo) = \int_{2\pi} BxDF(wo,wi) |wi.N| dwi
+ * rho(wo) P(wi,wo) = BxDF(wo,wi) |wi.N|; with \int_{2\pi} P(wo,wi) dwi = 1 */
+ double
+ (*rho)
+ (void* bxdf,
+ const double wo[3]);
+
size_t sizeof_bxdf; /* In Bytes */
size_t alignof_bxdf; /* In Bytes */
};
+#define SSF_BXDF_TYPE_NULL__ {NULL, NULL, NULL, NULL, NULL, NULL, 0, 1}
+static const struct ssf_bxdf_type SSF_BXDF_TYPE_NULL = SSF_BXDF_TYPE_NULL__;
/* Generic Fresnel term descriptor */
struct ssf_fresnel_type {
@@ -95,6 +104,9 @@ struct ssf_fresnel_type {
size_t sizeof_fresnel; /* In Bytes */
size_t alignof_fresnel; /* In Bytes */
};
+#define SSF_FRESNEL_TYPE_NULL__ {NULL, NULL, NULL, 0, 1}
+static const struct ssf_fresnel_type SSF_FRESNEL_TYPE_NULL =
+ SSF_FRESNEL_TYPE_NULL__;
/* Generic descriptor of a microfacet distribution */
struct ssf_microfacet_distribution_type {
@@ -128,6 +140,10 @@ struct ssf_microfacet_distribution_type {
size_t sizeof_distribution; /* In Bytes */
size_t alignof_distribution; /* In Bytes */
};
+#define SSF_MICROFACET_DISTRIBUTION_TYPE_NULL__ \
+ {NULL, NULL, NULL, NULL, NULL, 0, 1}
+static const struct ssf_microfacet_distribution_type
+SSF_MICROFACET_DISTRIBUTION_TYPE_NULL = SSF_MICROFACET_DISTRIBUTION_TYPE_NULL__;
BEGIN_DECLS
@@ -216,6 +232,11 @@ ssf_bsdf_view_pdf
const double N[3], /* Normalized surface normal */
const double wi[3]); /* Normalized outgoing direction */
+SSF_API double /* \int_{2\pi} BSDF(wi, wo) |wi.N| dwi */
+ssf_bsdf_view_rho
+ (struct ssf_bsdf_view* view,
+ const double wo[3]);
+
/*******************************************************************************
* BxDF API - Bidirectional <Reflectance|Transmittance> distribution function.
* Describes how the light is reflected|transmitted by a surface. Note that by
@@ -260,6 +281,11 @@ ssf_bxdf_pdf
const double N[3], /* Normalized surface normal */
const double wi[3]);/* Normalized incoming dir. Point outward the surface */
+SSF_API double /* \int_{2\pi} BxDF(wi, wo) |wi.N| dwi */
+ssf_bxdf_rho
+ (struct ssf_bxdf* bxdf,
+ const double wo[3]);
+
/* Retrieve the internal data of the BxDF. Usefull for user defined BxDFs on
* which the caller has to retrieve their data to setup their parameters */
SSF_API res_T
diff --git a/src/ssf_bsdf_view.c b/src/ssf_bsdf_view.c
@@ -177,9 +177,9 @@ ssf_bsdf_view_sample
double
ssf_bsdf_view_eval
(struct ssf_bsdf_view* view,
- const double wi[3],
+ const double wo[3],
const double N[3],
- const double wo[3])
+ const double wi[3])
{
double R = 0;
size_t i;
@@ -187,7 +187,7 @@ ssf_bsdf_view_eval
ASSERT(d3_is_normalized(wi) && d3_is_normalized(wo));
FOR_EACH(i, 0, view->ncomponents) {
- R += ssf_bxdf_eval(view->components[i], wi, N, wo) * view->probas[i];
+ R += ssf_bxdf_eval(view->components[i], wo, N, wi) * view->probas[i];
}
return R;
}
@@ -195,9 +195,9 @@ ssf_bsdf_view_eval
double
ssf_bsdf_view_pdf
(struct ssf_bsdf_view* view,
- const double wi[3],
+ const double wo[3],
const double N[3],
- const double wo[3])
+ const double wi[3])
{
double pdf = 0;
size_t i;
@@ -205,11 +205,25 @@ ssf_bsdf_view_pdf
ASSERT(d3_is_normalized(wi) && d3_is_normalized(wo));
FOR_EACH(i, 0, view->ncomponents) {
- pdf += ssf_bxdf_pdf(view->components[i], wi, N, wo) * view->probas[i];
+ pdf += ssf_bxdf_pdf(view->components[i], wo, N, wi) * view->probas[i];
}
return pdf;
}
+double
+ssf_bsdf_view_rho
+ (struct ssf_bsdf_view* view,
+ const double wo[3])
+{
+ double rho = 0;
+ size_t i;
+ ASSERT(view && wo);
+ FOR_EACH(i, 0, view->ncomponents) {
+ rho += ssf_bxdf_rho(view->components[i], wo) * view->probas[i];
+ }
+ return rho;
+}
+
/*******************************************************************************
* Local functions
******************************************************************************/
diff --git a/src/ssf_bxdf.c b/src/ssf_bxdf.c
@@ -34,6 +34,7 @@ check_bxdf_type(const struct ssf_bxdf_type* type)
&& type->sample
&& type->eval
&& type->pdf
+ && type->rho
&& IS_POW2(type->alignof_bxdf);
}
@@ -152,6 +153,13 @@ ssf_bxdf_pdf
return bxdf->type.pdf(bxdf->data, wo, N, wi);
}
+double
+ssf_bxdf_rho(struct ssf_bxdf* bxdf, const double wo[3])
+{
+ ASSERT(bxdf && wo && d3_is_normalized(wo));
+ return bxdf->type.rho(bxdf->data, wo);
+}
+
res_T
ssf_bxdf_get_data(struct ssf_bxdf* bxdf, void** data)
{
diff --git a/src/ssf_bxdf_c.h b/src/ssf_bxdf_c.h
@@ -36,6 +36,7 @@ struct ssf_bxdf {
&& (A)->sample == (B)->sample \
&& (A)->eval == (B)->eval \
&& (A)->pdf == (B)->pdf \
+ && (A)->rho == (B)->rho \
&& (A)->sizeof_bxdf == (B)->sizeof_bxdf \
&& (A)->alignof_bxdf == (B)->alignof_bxdf)
diff --git a/src/ssf_lambertian_reflection.c b/src/ssf_lambertian_reflection.c
@@ -93,6 +93,14 @@ lambertian_reflection_pdf
return cos_wi_N <= 0.0 ? 0.0 : cos_wi_N / PI;
}
+static double
+lambertian_reflection_rho(void* data, const double wo[3])
+{
+ ASSERT(data && wo);
+ (void)wo;
+ return ((struct lambertian_reflection*)data)->reflectivity;
+}
+
/*******************************************************************************
* Exorted symbols
******************************************************************************/
@@ -102,6 +110,7 @@ const struct ssf_bxdf_type ssf_lambertian_reflection = {
lambertian_reflection_sample,
lambertian_reflection_eval,
lambertian_reflection_pdf,
+ lambertian_reflection_rho,
sizeof(struct lambertian_reflection),
ALIGNOF(struct lambertian_reflection)
};
diff --git a/src/ssf_microfacet_reflection.c b/src/ssf_microfacet_reflection.c
@@ -124,6 +124,14 @@ microfacet_reflection_pdf
return pdf_wh / (4.0*fabs(d3_dot(wo, wh))); /* TODO check this */
}
+static FINLINE double
+microfacet_reflection_rho(void* data, const double wo[3])
+{
+ ASSERT(data && wo);
+ (void)data, (void)wo;
+ return 0; /* TODO */
+}
+
/*******************************************************************************
* Exported symbols
******************************************************************************/
@@ -133,6 +141,7 @@ const struct ssf_bxdf_type ssf_microfacet_reflection = {
microfacet_reflection_sample,
microfacet_reflection_eval,
microfacet_reflection_pdf,
+ microfacet_reflection_rho,
sizeof(struct microfacet_reflection),
ALIGNOF(struct microfacet_reflection)
};
diff --git a/src/ssf_specular_reflection.c b/src/ssf_specular_reflection.c
@@ -80,6 +80,14 @@ specular_reflection_pdf
return 0.0;
}
+static double
+specular_reflection_rho(void* data, const double wo[3])
+{
+ ASSERT(data && wo);
+ (void)wo;
+ return ((struct specular_reflection*)data)->reflectivity;
+}
+
/*******************************************************************************
* Exported symbols
******************************************************************************/
@@ -89,6 +97,7 @@ const struct ssf_bxdf_type ssf_specular_reflection = {
specular_reflection_sample,
specular_reflection_eval,
specular_reflection_pdf,
+ specular_reflection_rho,
sizeof(struct specular_reflection),
ALIGNOF(struct specular_reflection)
};
diff --git a/src/test_ssf_bsdf_view.c b/src/test_ssf_bsdf_view.c
@@ -30,6 +30,7 @@ main(int argc, char** argv)
double N[3], wi[3], wo[3];
double pdf;
double R;
+ double rho;
double E, V, SE;
double sum, sqr_sum;
size_t i;
@@ -89,6 +90,9 @@ main(int argc, char** argv)
SE = sqrt(V / (double)NSTEPS);
CHECK(eq_eps((0.1234+0.6789) * 0.5, E, SE), 1);
+ rho = ssf_bsdf_view_rho(view, wo);
+ CHECK(eq_eps(rho, (0.1234+0.6789)*0.5, 1.e-6), 1);
+
CHECK(ssf_bsdf_view_ref_get(NULL), RES_BAD_ARG);
CHECK(ssf_bsdf_view_ref_get(view), RES_OK);
CHECK(ssf_bsdf_view_ref_put(NULL), RES_BAD_ARG);
diff --git a/src/test_ssf_bxdf.c b/src/test_ssf_bxdf.c
@@ -30,6 +30,7 @@ struct ALIGN(64) bxdf {
double reflectivity;
double value;
double pdf;
+ double rho;
};
static res_T
@@ -106,13 +107,22 @@ bxdf_pdf
return BxDF->pdf;
}
+static double
+bxdf_rho(void* bxdf, const double wo[3])
+{
+ struct bxdf* BxDF = bxdf;
+ NCHECK(BxDF, NULL);
+ CHECK(d3_eq(BxDF->wo, wo), 1);
+ return BxDF->rho;
+}
+
int
main(int argc, char** argv)
{
struct mem_allocator allocator;
struct bxdf* data;
struct ssf_bxdf* bxdf;
- struct ssf_bxdf_type type;
+ struct ssf_bxdf_type type = SSF_BXDF_TYPE_NULL;
double wo[3];
double N[3];
double wi[4];
@@ -125,6 +135,7 @@ main(int argc, char** argv)
type.release = bxdf_release;
type.sample = bxdf_sample;
type.eval = bxdf_eval;
+ type.rho = bxdf_rho;
type.pdf = bxdf_pdf;
type.sizeof_bxdf = sizeof(struct bxdf);
type.alignof_bxdf = ALIGNOF(struct bxdf);
@@ -185,23 +196,26 @@ main(int argc, char** argv)
d3_set(data->N, N);
data->u = 0.0;
data->v = 0.0;
- data->reflectivity = 1.234;
+ data->reflectivity = 0.1234;
- CHECK(ssf_bxdf_sample(bxdf, 0, 0, wo, N, wi, &pdf), 1.234);
+ CHECK(ssf_bxdf_sample(bxdf, 0, 0, wo, N, wi, &pdf), 0.1234);
data->u = 0.5;
data->v = 0.5;
- CHECK(ssf_bxdf_sample(bxdf, 0.5, 0.5, wo, N, wi, &pdf), 1.234);
+ CHECK(ssf_bxdf_sample(bxdf, 0.5, 0.5, wo, N, wi, &pdf), 0.1234);
- data->reflectivity = 3.14;
- CHECK(ssf_bxdf_sample(bxdf, 0.5, 0.5, wo, N, wi, &pdf), 3.14);
+ data->reflectivity = 0.314;
+ CHECK(ssf_bxdf_sample(bxdf, 0.5, 0.5, wo, N, wi, &pdf), 0.314);
d3_normalize(wi, wi);
d3_set(data->wi, wi);
- data->value = 4.567;
+ data->value = 0.4567;
CHECK(ssf_bxdf_eval(bxdf, wo, N, wi), data->value);
- data->pdf = 8.90;
+ data->pdf = 0.890;
CHECK(ssf_bxdf_pdf(bxdf, wo, N, wi), data->pdf);
+ data->rho = 0.314;
+ CHECK(ssf_bxdf_rho(bxdf, wo), data->rho);
+
CHECK(bxdf_is_init, 1);
CHECK(ssf_bxdf_ref_put(bxdf), RES_OK);
CHECK(bxdf_is_init, 0);
diff --git a/src/test_ssf_fresnel.c b/src/test_ssf_fresnel.c
@@ -59,7 +59,7 @@ main(int argc, char** argv)
struct mem_allocator allocator;
struct fresnel* data;
struct ssf_fresnel* fresnel;
- struct ssf_fresnel_type type;
+ struct ssf_fresnel_type type = SSF_FRESNEL_TYPE_NULL;
(void)argc, (void)argv;
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
diff --git a/src/test_ssf_utils.h b/src/test_ssf_utils.h
@@ -71,12 +71,20 @@ bxdf_dummy_pdf
return 0.0;
}
+static double
+bxdf_dummy_rho(void* bxdf, const double wo[3])
+{
+ (void)bxdf, (void)wo;
+ return 0.0;
+}
+
static const struct ssf_bxdf_type bxdf_dummy = {
bxdf_dummy_init,
bxdf_dummy_release,
bxdf_dummy_sample,
bxdf_dummy_eval,
bxdf_dummy_pdf,
+ bxdf_dummy_rho,
0, 1
};