commit 2b0cd94bbbd91e913c797102ce40d52f395008f4
parent 4b0ba2ff258f5fcb7777963f5dcbd06072b7ccd0
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Mon, 3 Oct 2016 15:13:32 +0200
Update the SSF API
Explicitly relies on the Star-SamPling library to generate random
numbers
Diffstat:
19 files changed, 194 insertions(+), 207 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -27,13 +27,14 @@ set(SSF_SOURCE_DIR ${PROJECT_SOURCE_DIR}/../src)
################################################################################
find_package(RCMake REQUIRED)
find_package(RSys 0.4 REQUIRED)
-include_directories(${RSys_INCLUDE_DIR})
+find_package(StarSP 0.3 REQUIRED)
+include_directories(${RSys_INCLUDE_DIR} ${StarSP_INCLUDE_DIR})
set(CMAKE_MODULE_PATH ${RCMAKE_SOURCE_DIR})
include(rcmake)
include(rcmake_runtime)
-rcmake_append_runtime_dirs(_runtime_dirs RSys)
+rcmake_append_runtime_dirs(_runtime_dirs RSys StarSP)
################################################################################
# Define targets
@@ -73,7 +74,7 @@ if(BUILD_STATIC)
set_target_properties(ssf PROPERTIES DEFINE_SYMBOL SSF_STATIC)
else()
add_library(ssf SHARED ${SSF_FILES_INC} ${SSF_FILES_SRC})
- target_link_libraries(ssf RSys)
+ target_link_libraries(ssf RSys StarSP)
set_target_properties(ssf PROPERTIES
DEFINE_SYMBOL SSF_SHARED_BUILD
VERSION ${VERSION}
@@ -93,7 +94,7 @@ if(NOT NO_TEST)
function(new_test _name)
add_executable(${_name} ${SSF_SOURCE_DIR}/${_name}.c)
- target_link_libraries(${_name} ssf RSys ${MATH_LIB})
+ target_link_libraries(${_name} ssf RSys StarSP ${MATH_LIB})
add_test(${_name} ${_name})
endfunction()
diff --git a/src/ssf.h b/src/ssf.h
@@ -40,6 +40,7 @@
/* Forward declaration */
struct mem_allocator;
+struct ssp_rng;
/* Opaque data types */
struct ssf_bsdf; /* Bidirectional Scattering Distribution Function */
@@ -63,8 +64,7 @@ struct ssf_bxdf_type {
double
(*sample)
(void* bxdf,
- const double u, /* Canonical random number */
- const double v, /* Canonical random number */
+ struct ssp_rng* rng, /* Random number generator */
const double wo[3], /* Normalized outgoing direction */
const double N[3], /* Normalized surface normal */
double wi[3], /* Sampled normalized incoming direction */
@@ -116,8 +116,7 @@ struct ssf_microfacet_distribution_type {
void
(*sample)
(void* distrib,
- const double u, /* Canonical random number */
- const double v, /* Canonical random number */
+ struct ssp_rng* rng, /* Random number generator */
const double wo[3], /* Normalized outgoing direction */
const double N[3], /* Normalized Z-direction of the distribution */
double wh[3], /* Sampled normalized half vector */
@@ -208,8 +207,7 @@ ssf_bsdf_clear
SSF_API double
ssf_bsdf_sample
(struct ssf_bsdf* bsdf,
- const double u, /* Canonical number */
- const double v, /* Canonical number */
+ struct ssp_rng* rng, /* Random number generator */
const double wo[3], /* Normalized outgoing direction */
const double N[3], /* Normalized surface normal */
double wi[3], /* Sampeled normalized incoming direction */
@@ -256,8 +254,7 @@ ssf_bxdf_ref_put
SSF_API double
ssf_bxdf_sample
(struct ssf_bxdf* bxdf,
- const double u, /* Canonical random number */
- const double v, /* Canonical random number */
+ struct ssp_rng* rng, /* Random number generator */
const double wo[3], /* Normalized outgoing direction */
const double N[3], /* Normalized surface normal */
double wi[3], /* Sampled normalized incoming direction. */
@@ -373,8 +370,7 @@ ssf_microfacet_distribution_eval
SSF_API void
ssf_microfacet_distribution_sample
(struct ssf_microfacet_distribution* distrib,
- const double u, /* Canonical random number */
- const double v, /* Canonical random number */
+ struct ssp_rng* rng, /* Random number generator */
const double wo[3], /* Normalized outgoing direction */
const double N[3], /* Normalized Z-direction of the distribution */
double wh[3], /* Normalized half vector */
diff --git a/src/ssf_beckmann_distribution.c b/src/ssf_beckmann_distribution.c
@@ -19,6 +19,8 @@
#include <rsys/double3.h>
#include <rsys/double33.h>
+#include <star/ssp.h>
+
struct beckmann_distribution {
double roughness;
};
@@ -61,8 +63,7 @@ beckmann_distribution_eval
static void
beckmann_distribution_sample
(void* distrib,
- const double u,
- const double v,
+ struct ssp_rng* rng,
const double wo[3],
const double N[3],
double wh[3],
@@ -77,10 +78,13 @@ beckmann_distribution_sample
double cos_theta_T, sin_theta_T;
double cos_theta, sin_theta;
double cos2_theta, sin2_theta;
- ASSERT(u >= 0 && u < 1 && v >= 0 && v < 1 && wh && N && wo);
+ double u, v;
+ ASSERT(rng && wh && N && wo);
ASSERT(d3_is_normalized(wo) && d3_is_normalized(N));
(void)wo;
+ u = ssp_rng_canonical(rng);
+ v = ssp_rng_canonical(rng);
phi = 2.0*PI*u;
m2 = beckmann->roughness * beckmann->roughness;
diff --git a/src/ssf_blinn_distribution.c b/src/ssf_blinn_distribution.c
@@ -19,6 +19,8 @@
#include <rsys/double3.h>
#include <rsys/double33.h>
+#include <star/ssp.h>
+
struct blinn_distribution {
double exponent;
};
@@ -57,8 +59,7 @@ blinn_distribution_eval
static void
blinn_distribution_sample
(void* distrib,
- const double u,
- const double v,
+ struct ssp_rng* rng,
const double wo[3],
const double N[3],
double wh[3],
@@ -70,9 +71,13 @@ blinn_distribution_sample
double cos_theta, sin_theta;
double cos_wh_wo;
double phi;
- ASSERT(distrib && u>=0 && u<1 && v>=0 && v<1 && wo && N && wh && pdf);
+ double u, v;
+ ASSERT(distrib && rng && wo && N && wh && pdf);
ASSERT(d3_is_normalized(wo) && d3_is_normalized(N));
+ u = ssp_rng_canonical(rng);
+ v = ssp_rng_canonical(rng);
+
phi = v*2*PI;
cos_theta = pow(u, 1/(blinn->exponent+1));
sin_theta = sqrt(MMAX(0, 1-cos_theta*cos_theta));
diff --git a/src/ssf_bsdf.c b/src/ssf_bsdf.c
@@ -23,6 +23,8 @@
#include <rsys/mem_allocator.h>
#include <rsys/ref_count.h>
+#include <star/ssp.h>
+
#define MAX_BxDFs 8
struct ssf_bsdf {
@@ -142,8 +144,7 @@ ssf_bsdf_clear(struct ssf_bsdf* bsdf)
double
ssf_bsdf_sample
(struct ssf_bsdf* bsdf,
- const double u,
- const double v,
+ struct ssp_rng* rng,
const double wo[3],
const double N[3],
double wi[3],
@@ -153,9 +154,8 @@ ssf_bsdf_sample
double R_wi;
double r;
double pdf;
- double lower;
size_t i;
- ASSERT(bsdf && u>=0 && u<1 && v>=0 && v<1 && wi && N && wo && out_pdf);
+ ASSERT(bsdf && rng && wi && N && wo && out_pdf);
ASSERT(d3_is_normalized(wo) && d3_is_normalized(N));
if(!bsdf->nbxdfs) {
@@ -163,7 +163,7 @@ ssf_bsdf_sample
return 0;
}
if(bsdf->nbxdfs == 1) {
- return ssf_bxdf_sample(bsdf->bxdfs[0], u, v, wo, N, wi, out_pdf);
+ return ssf_bxdf_sample(bsdf->bxdfs[0], rng, wo, N, wi, out_pdf);
}
bsdf_normalize_weights(bsdf);
@@ -175,17 +175,13 @@ ssf_bsdf_sample
}
/* Sample a component */
- lower = 0;
+ r = ssp_rng_canonical(rng);
FOR_EACH(i, 0, bsdf->nbxdfs-1) {
- if(u <= cumul[i]) break;
- lower = cumul[i];
+ if(r <= cumul[i]) break;
}
- /* Rescale the random number u in [0, 1) */
- r = (u - lower) / nextafter(cumul[i] - lower, DBL_MAX);
-
/* Sample a direction from the selected component */
- R_wi = ssf_bxdf_sample(bsdf->bxdfs[i], r, v, wo, N, wi, &pdf);
+ R_wi = ssf_bxdf_sample(bsdf->bxdfs[i], rng, wo, N, wi, &pdf);
*out_pdf = pdf*bsdf->weights[i];
return R_wi;
}
diff --git a/src/ssf_bxdf.c b/src/ssf_bxdf.c
@@ -116,16 +116,15 @@ ssf_bxdf_ref_put(struct ssf_bxdf* bxdf)
double
ssf_bxdf_sample
(struct ssf_bxdf* bxdf,
- const double u,
- const double v,
+ struct ssp_rng* rng,
const double wo[3],
const double N[3],
double wi[3],
double* pdf)
{
- ASSERT(bxdf && u>=0 && u<1 && v>=0 && v<1 && wo && N && wi && pdf);
+ ASSERT(bxdf && rng && wo && N && wi && pdf);
ASSERT(d3_is_normalized(wo) && d3_is_normalized(N));
- return bxdf->type.sample(bxdf->data, u, v, wo, N, wi, pdf);
+ return bxdf->type.sample(bxdf->data, rng, wo, N, wi, pdf);
}
double
diff --git a/src/ssf_lambertian_reflection.c b/src/ssf_lambertian_reflection.c
@@ -19,6 +19,8 @@
#include <rsys/double3.h>
#include <rsys/double33.h>
+#include <star/ssp.h>
+
struct lambertian_reflection {
double reflectivity;
};
@@ -55,29 +57,22 @@ lambertian_reflection_eval
static double
lambertian_reflection_sample
(void* data,
- const double u,
- const double v,
+ struct ssp_rng* rng,
const double wo[3],
const double N[3],
double wi[3],
double* pdf)
{
- double basis[9];
- double dir[3];
- double cos_theta, sin_theta;
- double phi;
- ASSERT(data && u>=0 && u<1 && v>=0 && v<1 && wo && N && wi);
+ float normal[3];
+ float sample[4];
+ ASSERT(data && rng && wo && N && wi);
ASSERT(d3_is_normalized(wo) && d3_is_normalized(N));
+ (void)wo;
- phi = 2.0 * PI * u;
- cos_theta = sqrt(v);
- sin_theta = sqrt(1.0 - v);
- dir[0] = cos(phi) * sin_theta;
- dir[1] = sin(phi) * sin_theta;
- dir[2] = cos_theta;
- if(d3_dot(wo, N) < 0) dir[2] = -dir[2];
- d33_muld3(wi, d33_basis(basis, N), dir);
- *pdf = cos_theta / PI;
+ f3_set_d3(normal, N);
+ ssp_ran_hemisphere_cos(rng, normal, sample);
+ d3_set_f3(wi, sample);
+ *pdf = sample[3];
return ((struct lambertian_reflection*)data)->reflectivity;
}
diff --git a/src/ssf_microfacet_distribution.c b/src/ssf_microfacet_distribution.c
@@ -121,16 +121,15 @@ ssf_microfacet_distribution_ref_put(struct ssf_microfacet_distribution* distrib)
void
ssf_microfacet_distribution_sample
(struct ssf_microfacet_distribution* distrib,
- const double u,
- const double v,
+ struct ssp_rng* rng,
const double wo[3],
const double N[3],
double wh[3],
double* pdf)
{
- ASSERT(distrib && u>=0 && u<1 && v>=0 && v<1 && wo && N && wh && pdf);
+ ASSERT(distrib && rng && wo && N && wh && pdf);
ASSERT(d3_is_normalized(wo) && d3_is_normalized(N));
- distrib->type.sample(distrib->data, u, v, wo, N, wh, pdf);
+ distrib->type.sample(distrib->data, rng, wo, N, wh, pdf);
}
double
diff --git a/src/ssf_microfacet_reflection.c b/src/ssf_microfacet_reflection.c
@@ -80,8 +80,7 @@ microfacet_reflection_eval
static FINLINE double
microfacet_reflection_sample
(void* data,
- const double u,
- const double v,
+ struct ssp_rng* rng,
const double wo[3],
const double N[3],
double wi[3],
@@ -92,13 +91,13 @@ microfacet_reflection_sample
double wh[3];
double pdf_wh;
double R;
- ASSERT(data && u>=0 && u<1 && v>=0 && v<1 && wo && N && wi);
+ ASSERT(data && wo && N && wi);
ASSERT(d3_is_normalized(wo) && d3_is_normalized(N));
ASSERT(bxdf->distrib && bxdf->fresnel);
if(d3_dot(wo, N) <= 0.0) return 0.0;
- ssf_microfacet_distribution_sample(bxdf->distrib, u, v, wo, N, wh, &pdf_wh);
+ 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)));
R = d3_dot(dir, N) > 0 ? ssf_fresnel_eval(bxdf->fresnel, d3_dot(dir, wh)) : 0;
@@ -135,8 +134,7 @@ microfacet_reflection_rho(void* data, const double wo[3], const double N[3])
static FINLINE double
microfacet2_reflection_sample
(void* data,
- const double u,
- const double v,
+ struct ssp_rng* rng,
const double wo[3],
const double N[3],
double wi[3],
@@ -147,14 +145,14 @@ microfacet2_reflection_sample
double wh[3];
double p;
double troughput = 1;
- ASSERT(data && u>=0 && u<1 && v>=0 && v<1 && wo && N && wi);
+ ASSERT(data && wo && N && wi);
ASSERT(d3_is_normalized(wo) && d3_is_normalized(N));
ASSERT(bxdf->distrib);
if(d3_dot(wo, N) <= 0.0) return 0.0;
do { /* Sample a micro facet that front faces 'wo' */
- ssf_microfacet_distribution_sample(bxdf->distrib, u, v, wo, N, wh, &p);
+ ssf_microfacet_distribution_sample(bxdf->distrib, rng, wo, N, wh, &p);
} while(d3_dot(wo, wh) <= 0);
reflect(dir, wo, wh);
@@ -168,7 +166,7 @@ microfacet2_reflection_sample
/* Handle directions that point toward the macro surface has
* inter-reflections */
do { /* Sample a microfacet that front faces 'wi' */
- ssf_microfacet_distribution_sample(bxdf->distrib, u, v, dir, N, wh, &p);
+ ssf_microfacet_distribution_sample(bxdf->distrib, rng, dir, N, wh, &p);
} while(d3_dot(dir, wh) <= 0);
reflect(dir, dir, wh);
}
@@ -226,7 +224,8 @@ ssf_microfacet_reflection_setup
struct microfacet_reflection* microfacet;
if(!bxdf || !fresnel || !distrib)
return RES_BAD_ARG;
- if(!BXDF_TYPE_EQ(&bxdf->type, &ssf_microfacet_reflection))
+ if(!BXDF_TYPE_EQ(&bxdf->type, &ssf_microfacet_reflection)
+ && !BXDF_TYPE_EQ(&bxdf->type, &ssf_microfacet2_reflection))
return RES_BAD_ARG;
microfacet = bxdf->data;
diff --git a/src/ssf_specular_reflection.c b/src/ssf_specular_reflection.c
@@ -45,8 +45,7 @@ specular_reflection_release(void* bxdf)
static double
specular_reflection_sample
(void* data,
- const double u,
- const double v,
+ struct ssp_rng* rng,
const double wo[3],
const double N[3],
double wi[3],
@@ -55,9 +54,9 @@ specular_reflection_sample
struct specular_reflection* brdf = data;
double cos_wo_N;
double cos_wi_N;
- ASSERT(u >= 0 && u < 1 && v >= 0 && v < 1 && wi && N && wo);
+ ASSERT(rng && wi && N && wo);
ASSERT(d3_is_normalized(wo) && d3_is_normalized(N));
- (void)u, (void)v;
+ (void)rng;
/* Reflect the outgoing direction wo with respect to the surface normal N */
reflect(wi, wo, N);
diff --git a/src/test_ssf_beckmann_distribution.c b/src/test_ssf_beckmann_distribution.c
@@ -26,12 +26,15 @@ main(int argc, char** argv)
struct mem_allocator allocator;
struct ssf_microfacet_distribution* distrib;
struct ssf_microfacet_distribution* dummy;
+ struct ssp_rng* rng;
const size_t NTESTS = 10;
size_t itest;
(void)argc, (void)argv;
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
+ CHECK(ssp_rng_create(&allocator, &ssp_rng_threefry, &rng), RES_OK);
+
CHECK(ssf_microfacet_distribution_create
(&allocator, &ssf_beckmann_distribution, &distrib), RES_OK);
CHECK(ssf_microfacet_distribution_create
@@ -49,13 +52,14 @@ main(int argc, char** argv)
CHECK(ssf_beckmann_distribution_setup(distrib, 0), RES_BAD_ARG);
FOR_EACH(itest, 0, NTESTS) {
- const double roughness = nextafter(rand_canonic(), 2); /* in ]0, 1] */
+ const double roughness = nextafter(ssp_rng_canonical(rng), 2); /*in ]0, 1]*/
CHECK(ssf_beckmann_distribution_setup(distrib, roughness), RES_OK);
- check_microfacet_distribution(distrib);
+ check_microfacet_distribution(distrib, rng);
}
CHECK(ssf_microfacet_distribution_ref_put(distrib), RES_OK);
CHECK(ssf_microfacet_distribution_ref_put(dummy), RES_OK);
+ CHECK(ssp_rng_ref_put(rng), RES_OK);
check_memory_allocator(&allocator);
mem_shutdown_proxy_allocator(&allocator);
diff --git a/src/test_ssf_blinn_distribution.c b/src/test_ssf_blinn_distribution.c
@@ -22,6 +22,7 @@ int
main(int argc, char** argv)
{
struct mem_allocator allocator;
+ struct ssp_rng* rng;
struct ssf_microfacet_distribution* distrib;
struct ssf_microfacet_distribution* dummy;
const size_t NTESTS = 5;
@@ -29,6 +30,7 @@ main(int argc, char** argv)
(void)argc, (void)argv;
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
+ CHECK(ssp_rng_create(&allocator, &ssp_rng_threefry, &rng), RES_OK);
CHECK(ssf_microfacet_distribution_create
(&allocator, &ssf_blinn_distribution, &distrib), RES_OK);
@@ -51,13 +53,15 @@ main(int argc, char** argv)
CHECK(ssf_blinn_distribution_setup(distrib, 32.32), RES_OK);
FOR_EACH(itest, 0, NTESTS) {
- const double exponent = rand_canonic()*SSF_BLINN_DISTRIBUTION_MAX_EXPONENT;
+ const double exponent = ssp_rng_uniform_double
+ (rng, 0, SSF_BLINN_DISTRIBUTION_MAX_EXPONENT);
CHECK(ssf_blinn_distribution_setup(distrib, exponent), RES_OK);
- check_microfacet_distribution(distrib);
+ check_microfacet_distribution(distrib, rng);
}
CHECK(ssf_microfacet_distribution_ref_put(distrib), RES_OK);
CHECK(ssf_microfacet_distribution_ref_put(dummy), RES_OK);
+ CHECK(ssp_rng_ref_put(rng), RES_OK);
check_memory_allocator(&allocator);
mem_shutdown_proxy_allocator(&allocator);
diff --git a/src/test_ssf_bsdf.c b/src/test_ssf_bsdf.c
@@ -23,6 +23,7 @@ main(int argc, char** argv)
{
const size_t NSTEPS = 100000;
struct mem_allocator allocator;
+ struct ssp_rng* rng;
struct ssf_bsdf* bsdf;
struct ssf_bxdf* bxdf;
struct ssf_bxdf* bxdf2;
@@ -31,10 +32,13 @@ main(int argc, char** argv)
double N[3];
double E, V, SE, R;
double sum, sqr_sum;
+ float normal[3];
+ float sample[3];
size_t i;
(void)argc, (void)argv;
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
+ CHECK(ssp_rng_create(&allocator, &ssp_rng_threefry, &rng), RES_OK);
CHECK(ssf_bsdf_create(NULL, NULL), RES_BAD_ARG);
CHECK(ssf_bsdf_create(&allocator, NULL), RES_BAD_ARG);
@@ -64,13 +68,13 @@ 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, 0.5, 0.5, wo, N, wi, &pdf);
+ R = ssf_bsdf_sample(bsdf, rng, wo, N, wi, &pdf);
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, 0.5, 0.5, wo, N, wi, &pdf);
+ R = ssf_bsdf_sample(bsdf, rng, wo, N, wi, &pdf);
CHECK(eq_eps(R, ssf_fresnel_eval(fresnel, d3_dot(wi, N)), 1.e-6), 1);
CHECK(ssf_bsdf_add(bsdf, bxdf2, 1), RES_OK);
@@ -79,11 +83,11 @@ main(int argc, char** argv)
* totally wrong */
sum = 0;
sqr_sum = 0;
- ran_hemisphere(N, wo, NULL);
+ f3_set_d3(normal, N);
+ ssp_ran_hemisphere_uniform(rng, normal, sample);
+ d3_set_f3(wo, sample);
FOR_EACH(i, 0, NSTEPS) {
- const double u = rand_canonic();
- const double v = rand_canonic();
- double weight = ssf_bsdf_sample(bsdf, u, v, wo, N, wi, &pdf);
+ double weight = ssf_bsdf_sample(bsdf, rng, wo, N, wi, &pdf);
CHECK(ssf_bsdf_eval(bsdf, wo, N, wi), 0);
CHECK(ssf_bsdf_pdf(bsdf, wo, N, wi), 0);
sum += weight;
@@ -97,13 +101,14 @@ 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, 0, 0, wo, N, wi, &pdf), 0.0);
+ CHECK(ssf_bsdf_sample(bsdf, rng, wo, N, wi, &pdf), 0.0);
CHECK(pdf, 0.0);
CHECK(ssf_bsdf_ref_put(bsdf), RES_OK);
CHECK(ssf_bxdf_ref_put(bxdf), RES_OK);
CHECK(ssf_bxdf_ref_put(bxdf2), RES_OK);
CHECK(ssf_fresnel_ref_put(fresnel), RES_OK);
+ CHECK(ssp_rng_ref_put(rng), RES_OK);
check_memory_allocator(&allocator);
mem_shutdown_proxy_allocator(&allocator);
diff --git a/src/test_ssf_bxdf.c b/src/test_ssf_bxdf.c
@@ -22,8 +22,7 @@ static int bxdf_is_init = 0;
struct ALIGN(64) bxdf {
uint32_t id;
- double u;
- double v;
+ struct ssp_rng* rng;
double wi[3];
double wo[3];
double N[3];
@@ -55,8 +54,7 @@ bxdf_release(void* bxdf)
static double
bxdf_sample
(void* bxdf,
- const double u,
- const double v,
+ struct ssp_rng* rng,
const double wo[3],
const double N[3],
double wi[3],
@@ -64,8 +62,7 @@ bxdf_sample
{
struct bxdf* BxDF = bxdf;
NCHECK(BxDF, NULL);
- CHECK(BxDF->u, u);
- CHECK(BxDF->v, v);
+ CHECK(BxDF->rng, rng);
CHECK(d3_eq(BxDF->wo, wo), 1);
CHECK(d3_eq(BxDF->N, N), 1);
d3(wi, 1.0, 2.0, 3.0);
@@ -111,6 +108,7 @@ int
main(int argc, char** argv)
{
struct mem_allocator allocator;
+ struct ssp_rng* rng;
struct bxdf* data;
struct ssf_bxdf* bxdf;
struct ssf_bxdf_type type = SSF_BXDF_TYPE_NULL;
@@ -121,6 +119,7 @@ main(int argc, char** argv)
(void)argc, (void)argv;
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
+ CHECK(ssp_rng_create(&allocator, &ssp_rng_threefry, &rng), RES_OK);
type.init = bxdf_init;
type.release = bxdf_release;
@@ -184,17 +183,14 @@ main(int argc, char** argv)
d3(N, 0.0, 1.0, 0.0);
d3_set(data->wo, wo);
d3_set(data->N, N);
- data->u = 0.0;
- data->v = 0.0;
+ data->rng = rng;
data->reflectivity = 0.1234;
- 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), 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);
data->reflectivity = 0.314;
- CHECK(ssf_bxdf_sample(bxdf, 0.5, 0.5, wo, N, wi, &pdf), 0.314);
+ CHECK(ssf_bxdf_sample(bxdf, rng, wo, N, wi, &pdf), 0.314);
d3_normalize(wi, wi);
d3_set(data->wi, wi);
@@ -207,6 +203,8 @@ main(int argc, char** argv)
CHECK(ssf_bxdf_ref_put(bxdf), RES_OK);
CHECK(bxdf_is_init, 0);
+ CHECK(ssp_rng_ref_put(rng), RES_OK);
+
check_memory_allocator(&allocator);
mem_shutdown_proxy_allocator(&allocator);
CHECK(mem_allocated_size(), 0);
diff --git a/src/test_ssf_lambertian_reflection.c b/src/test_ssf_lambertian_reflection.c
@@ -24,6 +24,7 @@ main(int argc, char** argv)
{
const size_t NSTEPS = 100000;
struct mem_allocator allocator;
+ struct ssp_rng* rng;
struct ssf_bxdf* brdf;
struct ssf_bxdf* dummy;
double E, SE, V;
@@ -38,6 +39,7 @@ main(int argc, char** argv)
(void)argc, (void)argv;
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
+ CHECK(ssp_rng_create(&allocator, &ssp_rng_threefry, &rng), RES_OK);
CHECK(ssf_bxdf_create(&allocator, &ssf_lambertian_reflection, &brdf), RES_OK);
CHECK(ssf_bxdf_create(&allocator, &bxdf_dummy, &dummy), RES_OK);
@@ -52,36 +54,36 @@ 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, 0, 0, wo, N, wi, &pdf);
+ R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &pdf);
CHECK(eq_eps(wi[2]/PI, pdf, 1.e-6), 1);
CHECK(R, 0);
CHECK(ssf_lambertian_reflection_setup(brdf, 0.7), RES_OK);
- R = ssf_bxdf_sample(brdf, rand_canonic(), rand_canonic(), wo, N, wi, &pdf);
+ R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &pdf);
CHECK(eq_eps(R, 0.7, 1.e-6), 1);
CHECK(eq_eps(pdf, d3_dot(wi, N)/PI, 1.e-6), 1);
d3_normalize(wo, d3(wo, 1.0, 0.0, -1.0));
- R = ssf_bxdf_sample(brdf, rand_canonic(), rand_canonic(), wo, N, wi, &pdf);
+ R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &pdf);
CHECK(R, 0.7);
d3_normalize(wo, d3(wo, 1.0, 1.0, 0.0));
- R = ssf_bxdf_sample(brdf, rand_canonic(), rand_canonic(), wo, N, wi, &pdf);
+ R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &pdf);
CHECK(eq_eps(R, 0.7, 1.e-6), 1);
CHECK(eq_eps(R, ssf_bxdf_eval(brdf, wo, N, wi)*PI, 1.e-6), 1);
d3_normalize(wo, d3(wo, 1.0, 0.0, 1.0));
- d3(N, rand_canonic(), rand_canonic(), rand_canonic());
+ N[0] = ssp_rng_uniform_double(rng, -1, 1);
+ N[1] = ssp_rng_uniform_double(rng, -1, 1);
+ N[2] = ssp_rng_uniform_double(rng, -1, 1);
d3_normalize(N, N);
d33_basis(basis, N);
d33_muld3(wo, basis, wo);
sum = sum_sqr = 0;
FOR_EACH(i, 0, NSTEPS) {
- const double u = rand_canonic();
- const double v = rand_canonic();
double cos_wi_N;
- R = ssf_bxdf_sample(brdf, u, v, wo, N, wi, &pdf) / PI;
+ R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &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);
@@ -95,12 +97,10 @@ main(int argc, char** argv)
sum = sum_sqr = 0;
FOR_EACH(i, 0, NSTEPS) {
- const double u = rand_canonic();
- const double v = rand_canonic();
double cos_wi_N;
double w;
- R = ssf_bxdf_sample(brdf, u, v, wo, N, wi, &pdf)/PI;
+ R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &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);
@@ -115,8 +115,20 @@ 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) {
+ R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &pdf);
+ sum += R;
+ sum_sqr += R*R;
+ }
+ 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);
+ CHECK(ssp_rng_ref_put(rng), RES_OK);
check_memory_allocator(&allocator);
mem_shutdown_proxy_allocator(&allocator);
diff --git a/src/test_ssf_microfacet_distribution.c b/src/test_ssf_microfacet_distribution.c
@@ -22,8 +22,7 @@ static int ufacet_is_init = 0;
struct ALIGN(64) ufacet {
uint32_t id;
- double u;
- double v;
+ struct ssp_rng* rng;
double wh[3];
double wo[3];
double N[3];
@@ -53,8 +52,7 @@ ufacet_release(void* distrib)
static void
ufacet_sample
(void* distrib,
- const double u,
- const double v,
+ struct ssp_rng* rng,
const double wo[3],
const double N[3],
double wh[3],
@@ -62,14 +60,11 @@ ufacet_sample
{
struct ufacet* ufacet = distrib;
NCHECK(ufacet, NULL);
- CHECK(u >= 0 && u < 1, 1);
- CHECK(v >= 0 && v < 1, 1);
NCHECK(wo, NULL);
NCHECK(N, NULL);
NCHECK(wh, NULL);
NCHECK(pdf, NULL);
- CHECK(ufacet->u, u);
- CHECK(ufacet->v, v);
+ CHECK(ufacet->rng, rng);
CHECK(d3_eq(ufacet->wo, wo), 1);
CHECK(d3_eq(ufacet->N, N), 1);
d3_normalize(wh, d3(wh, 1.0, 2.0, 3.0));
@@ -119,10 +114,12 @@ main(int argc, char** argv)
struct ssf_microfacet_distribution_type type =
SSF_MICROFACET_DISTRIBUTION_TYPE_NULL;
struct ssf_microfacet_distribution* distrib;
+ struct ssp_rng* rng;
double wo[3], N[3], wh[3], pdf;
(void)argc, (void)argv;
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
+ CHECK(ssp_rng_create(&allocator, &ssp_rng_threefry, &rng), RES_OK);
type.init = ufacet_init;
type.release = ufacet_release;
@@ -190,15 +187,14 @@ main(int argc, char** argv)
d3_set(data->wo, wo);
d3_set(data->N, N);
d3_normalize(data->wh, d3(data->wh, 1, 2, 3));
- data->u = data->v = 0.0;
+ data->rng = rng;
data->pdf = 0.1234;
data->value = 0.43;
- ssf_microfacet_distribution_sample(distrib, 0, 0, wo, N, wh, &pdf);
+ ssf_microfacet_distribution_sample(distrib, rng, wo, N, wh, &pdf);
CHECK(d3_eq(wh, data->wh), 1);
CHECK(pdf, data->pdf);
- data->u = data->v = 0.5;
- ssf_microfacet_distribution_sample(distrib, 0.5, 0.5, wo, N, wh, &pdf);
+ ssf_microfacet_distribution_sample(distrib, rng, wo, N, wh, &pdf);
CHECK(d3_eq(wh, data->wh), 1);
CHECK(pdf, data->pdf);
@@ -208,6 +204,8 @@ main(int argc, char** argv)
CHECK(ssf_microfacet_distribution_ref_put(distrib), RES_OK);
CHECK(ufacet_is_init, 0);
+ CHECK(ssp_rng_ref_put(rng), RES_OK);
+
check_memory_allocator(&allocator);
mem_shutdown_proxy_allocator(&allocator);
CHECK(mem_allocated_size(), 0);
diff --git a/src/test_ssf_microfacet_reflection.c b/src/test_ssf_microfacet_reflection.c
@@ -17,6 +17,7 @@
#include "test_ssf_utils.h"
#include <rsys/double3.h>
+#include <star/ssp.h>
int
main(int argc, char** argv)
@@ -26,10 +27,12 @@ main(int argc, char** argv)
struct ssf_bxdf* dummy;
struct ssf_fresnel* F;
struct ssf_microfacet_distribution* D;
+ struct ssp_rng* rng;
(void)argc, (void)argv;
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
- CHECK(ssf_bxdf_create(&allocator, &ssf_microfacet_reflection, &bxdf), RES_OK);
+ CHECK(ssp_rng_create(&allocator, &ssp_rng_threefry, &rng), RES_OK);
+ CHECK(ssf_bxdf_create(&allocator, &ssf_microfacet2_reflection, &bxdf), RES_OK);
CHECK(ssf_bxdf_create(&allocator, &bxdf_dummy, &dummy), RES_OK);
CHECK(ssf_fresnel_create(&allocator, &ssf_fresnel_no_op, &F), RES_OK);
CHECK(ssf_microfacet_distribution_create
@@ -47,32 +50,38 @@ main(int argc, char** argv)
CHECK(ssf_microfacet_reflection_setup(bxdf, F, D), RES_OK);
/* Numerically evaluate rho */
- /* TODO */
#if 0
- d3(N, 0, 1, 0);
- sum = sum_sqr = 0;
- ran_hemisphere_cos(N, wo, NULL);
- FOR_EACH(i, 0, NSTEPS) {
- double R;
- double weight;
- ran_hemisphere_cos(N, wi, &pdf);
- R = ssf_bxdf_eval(bxdf, wo, N, wi);
- weight = R * d3_dot(wi, N) / pdf;
- sum += weight;
- sum_sqr += weight*weight;
- }
+ {
+ double N[3];
+ double wo[3];
+ double wi[3];
+ double pdf;
+ double sum, sum_sqr;
+ double E, SE, V;
+ size_t i, NSTEPS=1000;
+
+ d3(N, 0, 1, 0);
+ sum = sum_sqr = 0;
+ ran_hemisphere_cos(N, wo, NULL);
+ FOR_EACH(i, 0, NSTEPS) {
+ double R;
+ R = ssf_bxdf_sample(bxdf, rng, wo, N, wi, &pdf);
+ sum += R;
+ sum_sqr += R*R;
+ }
- E = sum / (double)NSTEPS;
- V = sum_sqr / (double)NSTEPS - E*E;
- SE = sqrt(V/(double)NSTEPS);
- printf("%g +/- %g\n", E, SE);
- CHECK(eq_eps(E, ssf_bxdf_rho(bxdf, wo, N), SE), 1);
+ E = sum / (double)NSTEPS;
+ V = sum_sqr / (double)NSTEPS - E*E;
+ SE = sqrt(V/(double)NSTEPS);
+ printf("%g +/- %g\n", E, SE);
+ }
#endif
CHECK(ssf_bxdf_ref_put(bxdf), RES_OK);
CHECK(ssf_bxdf_ref_put(dummy), RES_OK);
CHECK(ssf_fresnel_ref_put(F), RES_OK);
CHECK(ssf_microfacet_distribution_ref_put(D), RES_OK);
+ CHECK(ssp_rng_ref_put(rng), RES_OK);
check_memory_allocator(&allocator);
mem_shutdown_proxy_allocator(&allocator);
diff --git a/src/test_ssf_specular_reflection.c b/src/test_ssf_specular_reflection.c
@@ -23,6 +23,7 @@ main(int argc, char** argv)
{
const size_t NSTEPS = 100000;
struct mem_allocator allocator;
+ struct ssp_rng* rng;
struct ssf_bxdf* brdf;
struct ssf_bxdf* dummy;
struct ssf_fresnel* fresnel;
@@ -34,6 +35,7 @@ main(int argc, char** argv)
(void)argc, (void)argv;
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
+ CHECK(ssp_rng_create(&allocator, &ssp_rng_threefry, &rng), RES_OK);
CHECK(ssf_bxdf_create(&allocator, &ssf_specular_reflection, &brdf), RES_OK);
CHECK(ssf_bxdf_create(&allocator, &bxdf_dummy, &dummy), RES_OK);
CHECK(ssf_fresnel_create
@@ -48,13 +50,13 @@ 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, 0, 0, wo, N, wi, &pdf);
+ 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);
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, 0, 0, wo, N, wi, &pdf);
+ 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(d3_eq_eps(d3(wo, -wo[0], wo[1], 0.0), wi, 1.e-6), 1);
@@ -63,41 +65,42 @@ main(int argc, char** argv)
CHECK(ssf_bxdf_pdf(brdf, wo, N, wi), 0.0);
d3(wo, 0.0, 1.0, 0.0);
- R = ssf_bxdf_sample(brdf, 0, 0, wo, N, wi, &pdf);
+ 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(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, 0, 0, wo, N, wi, &pdf);
+ 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(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, 0, 0, wo, N, wi, &pdf);
+ R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &pdf);
CHECK(eq_eps(R, 0, 1.e-6), 1);
CHECK(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);
- R = ssf_bxdf_sample(brdf, 0, 0, wo, N, wi, &pdf);
+ R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &pdf);
CHECK(eq_eps(R, 0, 1.e-6), 1);
CHECK(d3_eq_eps(d3(wo, -1.0, 0, 0), wi, 1.e-6), 1);
- d3(wo, rand_canonic(), rand_canonic(), rand_canonic());
+ wo[0] = ssp_rng_uniform_double(rng, -1, 1);
+ wo[1] = ssp_rng_uniform_double(rng, -1, 1);
+ wo[2] = ssp_rng_uniform_double(rng, -1, 1);
d3_normalize(wo, wo);
- R = ssf_bxdf_sample(brdf, rand_canonic(), rand_canonic(), wo, N, wi, &pdf);
+ R = ssf_bxdf_sample(brdf, rng, wo, N, wi, &pdf);
FOR_EACH(i, 0, NSTEPS) {
- const double u = rand_canonic();
- const double v = rand_canonic();
- CHECK(eq_eps(ssf_bxdf_sample(brdf, u, v, wo, N, wi, &pdf), R, 1.e-6), 1);
+ CHECK(eq_eps(ssf_bxdf_sample(brdf, rng, wo, N, wi, &pdf), R, 1.e-6), 1);
}
CHECK(ssf_bxdf_ref_put(brdf), RES_OK);
CHECK(ssf_bxdf_ref_put(dummy), RES_OK);
CHECK(ssf_fresnel_ref_put(fresnel), RES_OK);
+ CHECK(ssp_rng_ref_put(rng), RES_OK);
check_memory_allocator(&allocator);
mem_shutdown_proxy_allocator(&allocator);
diff --git a/src/test_ssf_utils.h b/src/test_ssf_utils.h
@@ -19,6 +19,9 @@
#include <rsys/double33.h>
#include <rsys/math.h>
#include <rsys/mem_allocator.h>
+
+#include <star/ssp.h>
+
#include <stdio.h>
/*******************************************************************************
@@ -40,14 +43,13 @@ bxdf_dummy_release(void* bxdf)
static double
bxdf_dummy_sample
(void* bxdf,
- const double u,
- const double v,
+ struct ssp_rng* rng,
const double w[3],
const double N[3],
double dir[3],
double* pdf)
{
- (void)bxdf, (void)u, (void)v, (void)w, (void)N, (void)dir, (void)pdf;
+ (void)bxdf, (void)rng, (void)w, (void)N, (void)dir, (void)pdf;
return 0.0;
}
@@ -133,14 +135,13 @@ microfacet_dummy_release(void* distrib)
static void
microfacet_dummy_sample
(void* distrib,
- const double u,
- const double v,
+ struct ssp_rng* rng,
const double w[3],
const double N[3],
double dir[3],
double* pdf)
{
- (void)distrib, (void)u, (void)v, (void)w, (void)N, (void)dir, (void)pdf;
+ (void)distrib, (void)rng, (void)w, (void)N, (void)dir, (void)pdf;
}
static double
@@ -177,69 +178,29 @@ static const struct ssf_microfacet_distribution_type microfacet_dummy = {
/*******************************************************************************
* Miscellaneous functions
******************************************************************************/
-static INLINE double
-rand_canonic(void)
-{
- return (double)rand()/(double)RAND_MAX;
-}
-
-static INLINE double*
-ran_hemisphere_cos
- (const double N[3],
- double dir[3],
- double *pdf)
-{
- const double u = rand_canonic();
- const double v = rand_canonic();
- const double phi = 2.0 * PI * u;
- const double cos_theta = sqrt(v);
- const double sin_theta = sqrt(1.0 - v);
- double basis[9];
- double tmp[3];
- tmp[0] = cos(phi) * sin_theta;
- tmp[1] = sin(phi) * sin_theta;
- tmp[2] = cos_theta;
- d33_muld3(dir, d33_basis(basis, N), tmp);
- if(pdf) *pdf = cos_theta / PI;
- return dir;
-}
-
-static INLINE double*
-ran_hemisphere(const double N[3], double dir[3], double *pdf)
-{
- const double u = rand_canonic();
- const double v = rand_canonic();
- const double phi = 2.0 * PI * u;
- const double cos_theta = v;
- const double sin_theta = cos2sin(cos_theta);
- double basis[9];
- double tmp[3];
- tmp[0] = cos(phi) * sin_theta;
- tmp[1] = sin(phi) * sin_theta;
- tmp[2] = cos_theta;
- d33_muld3(dir, d33_basis(basis, N), tmp);
- if(pdf) *pdf = 1/(2*PI);
- return dir;
-}
-
static INLINE void
check_microfacet_distribution
- (struct ssf_microfacet_distribution* distrib)
+ (struct ssf_microfacet_distribution* distrib,
+ struct ssp_rng* rng)
{
double N[3];
+ float Nf[3];
const size_t NSTEPS = 10000;
size_t i;
size_t n;
double wo[3];
+ float sample[4];
double E, V, SE;
double sum, sum2;
- N[0] = rand_canonic()*2 - 1;
- N[1] = rand_canonic()*2 - 1;
- N[2] = rand_canonic()*2 - 1;
+ N[0] = ssp_rng_uniform_double(rng, -1, 1);
+ N[1] = ssp_rng_uniform_double(rng, -1, 1);
+ N[2] = ssp_rng_uniform_double(rng, -1, 1);
d3_normalize(N, N);
- ran_hemisphere(N, wo, NULL);
+ f3_set_d3(Nf, N);
+ ssp_ran_hemisphere_uniform(rng, Nf, sample);
+ d3_set_f3(wo, sample);
/* Check that D(wh) is normalized wrt \int_{2PI} D(wh) |wh.n| dwh */
sum = sum2 = 0;
@@ -247,7 +208,9 @@ check_microfacet_distribution
do {
FOR_EACH(i, 0, NSTEPS) {
double wh[3], pdf, D, weight;
- ran_hemisphere_cos(N, wh, &pdf);
+ ssp_ran_hemisphere_cos(rng, Nf, sample);
+ d3_set_f3(wh, sample);
+ pdf = sample[3];
D = ssf_microfacet_distribution_eval(distrib, wo, N, wh);
weight = D * d3_dot(wh, N) / pdf;
sum += weight;
@@ -262,11 +225,9 @@ check_microfacet_distribution
/* Check the sampling of a direction wh and the returned pdf */
FOR_EACH(i, 0, NSTEPS) {
- const double u = rand_canonic();
- const double v = rand_canonic();
double wh[3], pdf, D, weight;
- ssf_microfacet_distribution_sample(distrib, u, v, wo, N, wh, &pdf);
+ ssf_microfacet_distribution_sample(distrib, rng, wo, N, wh, &pdf);
D = ssf_microfacet_distribution_eval(distrib, wo, N, wh);
weight = D * d3_dot(wh, N) / pdf;
sum += weight;