commit 054a3047f0239db55b9ee6582b4318e25c6feacc
parent 0e55da9835f1afc59fa342544e00d94f1c15c158
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Mon, 14 Dec 2015 11:10:46 +0100
Fix the ssp_ran_hemisphere_<cos|uniform> routines
The returned sample was wrong when the submitted up vector aliased the
returned sample.
Diffstat:
2 files changed, 30 insertions(+), 4 deletions(-)
diff --git a/src/ssp.h b/src/ssp.h
@@ -427,9 +427,11 @@ ssp_ran_hemisphere_uniform
(struct ssp_rng* rng, const float up[3], float sample[4])
{
float basis[9];
+ float sample_local[3];
ASSERT(rng && up && sample && f3_is_normalized(up));
- ssp_ran_hemisphere_uniform_local(rng, sample);
- return f33_mulf3(sample, f33_basis(basis, up), sample);
+ ssp_ran_hemisphere_uniform_local(rng, sample_local);
+ sample[3] = sample_local[3];
+ return f33_mulf3(sample, f33_basis(basis, up), sample_local);
}
/* Return the probability distribution for an hemispheric uniform random
@@ -474,10 +476,12 @@ ssp_ran_hemisphere_cos_local_pdf(const float sample[3])
static INLINE float*
ssp_ran_hemisphere_cos(struct ssp_rng* rng, const float up[3], float sample[4])
{
+ float sample_local[4];
float basis[9];
ASSERT(rng && up && sample && f3_is_normalized(up));
- ssp_ran_hemisphere_cos_local(rng, sample);
- return f33_mulf3(sample, f33_basis(basis, up), sample);
+ ssp_ran_hemisphere_cos_local(rng, sample_local);
+ sample[3] = sample_local[3];
+ return f33_mulf3(sample, f33_basis(basis, up), sample_local);
}
/* Return the probability distribution for an hemispheric cosine weighted
diff --git a/src/test_ssp_ran_hemisphere.c b/src/test_ssp_ran_hemisphere.c
@@ -93,6 +93,17 @@ main(int argc, char** argv)
}
}
+ samps1[1][0] = (float)ssp_rng_uniform_double(rng1, -1.0, 1.0);
+ samps1[1][1] = (float)ssp_rng_uniform_double(rng1, -1.0, 1.0);
+ samps1[1][2] = (float)ssp_rng_uniform_double(rng1, -1.0, 1.0);
+ f3_normalize(samps1[1], samps1[1]);
+
+ ssp_rng_set(rng0, 0);
+ ssp_ran_hemisphere_uniform(rng0, samps1[1], samps0[0]);
+ ssp_rng_set(rng0, 0);
+ ssp_ran_hemisphere_uniform(rng0, samps1[1], samps1[1]);
+ CHECK(f4_eq(samps0[0], samps1[1]), 1);
+
ssp_rng_set(rng0, 0);
FOR_EACH(i, 0, NSAMPS) {
float frame[9];
@@ -137,6 +148,17 @@ main(int argc, char** argv)
}
}
+ samps1[1][0] = (float)ssp_rng_uniform_double(rng1, -1.0, 1.0);
+ samps1[1][1] = (float)ssp_rng_uniform_double(rng1, -1.0, 1.0);
+ samps1[1][2] = (float)ssp_rng_uniform_double(rng1, -1.0, 1.0);
+ f3_normalize(samps1[1], samps1[1]);
+
+ ssp_rng_set(rng0, 0);
+ ssp_ran_hemisphere_cos(rng0, samps1[1], samps0[0]);
+ ssp_rng_set(rng0, 0);
+ ssp_ran_hemisphere_cos(rng0, samps1[1], samps1[1]);
+ CHECK(f4_eq(samps0[0], samps1[1]), 1);
+
ssp_rng_ref_put(rng0);
ssp_rng_ref_put(rng1);
check_memory_allocator(&allocator);