commit ac7c9edf63de832c06b6059845f18a2561d98bc4
parent ac0e6a010b1acb8685d0a7b7fd56f2b25311d7d8
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Wed, 8 Apr 2015 09:13:18 +0200
Finalize the light path test
Diffstat:
2 files changed, 47 insertions(+), 16 deletions(-)
diff --git a/src/smc_integrator.c b/src/smc_integrator.c
@@ -124,7 +124,7 @@ smc_solve
estimator->status.N = 0;
estimator->type = *type;
- FOR_EACH(i, 0, 4096) {
+ FOR_EACH(i, 0, 16) {
if(estimator->nsamples == ULONG_MAX) break;
integrand(val, dev->rng, ctx);
type->add(estimator->value, estimator->value, val);
diff --git a/src/test_smc_light_path.c b/src/test_smc_light_path.c
@@ -44,8 +44,9 @@
#define IMG_WIDTH 640
#define IMG_HEIGHT 480
#define LIGHT_PATH_DEPTH 4
-#define SKY_RADIANCE 1.f
+#define SKY_RADIANCE 0.1f
#define ALBEDO 1.f
+#define EPSILON 1.e-3f
struct cbox_desc{
const float* vertices;
@@ -201,6 +202,30 @@ struct integrator_context {
size_t ipixel[2]; /* Image space pixel coordinates */
};
+static float
+direct_lighting(struct s3d_scene* scn, const float pos[3], const float N[3])
+{
+ const float light_pos[3] = { 200.f, 0.f, 400.f };
+ const float radiance = 20000.f;
+ struct s3d_hit hit;
+ float len;
+ float wi[3];
+ float range[2];
+
+ f3_sub(wi, light_pos, pos);
+ len = f3_normalize(wi, wi);
+
+ /* Trace shadow ray */
+ range[0] = EPSILON;
+ range[1] = len;
+ CHECK(s3d_scene_trace_ray(scn, pos, wi, range, &hit), RES_OK);
+
+ if(!S3D_HIT_NONE(&hit))
+ return 0.f;
+
+ return (radiance * (float)(ALBEDO / PI)) / (len*len) * f3_dot(wi, N);
+}
+
static void
light_path_integrator(void* value, struct ssp_rng* rng, void* data)
{
@@ -233,29 +258,35 @@ light_path_integrator(void* value, struct ssp_rng* rng, void* data)
FOR_EACH(idepth, 0, LIGHT_PATH_DEPTH) {
struct s3d_hit hit = S3D_HIT_NULL;
float cos_theta;
- float offset = 1.e-6f;
+ float sample[4];
float pdf;
- float wi[3];
+ float pos[3];
float N[3];
CHECK(s3d_scene_trace_ray
(ctx->scn, ray_org, ray_dir, ray_range, &hit), RES_OK);
- if(!S3D_HIT_NONE(&hit)) { /* Skydome lighting */
+ if(S3D_HIT_NONE(&hit)) { /* Skydome lighting */
L += throughput * SKY_RADIANCE;
break;
}
- /* TODO sample the surface hemisphere at the hit position */
+ f3_normalize(N, hit.normal);
+ cos_theta = f3_dot(N, ray_dir);
+ if(cos_theta >= 0.f) f3_minus(N, N);
+ f3_add(pos, f3_mulf(pos, ray_dir, hit.distance), ray_org);
+
+ /* Direct lighting */
+ L += throughput * direct_lighting(ctx->scn, pos, N);
/* New ray */
- f3_normalize(N, hit.normal);
- cos_theta = f3_dot(N, wi);
- if(cos_theta < 0.f) f3_dot(f3_minus(N, N), wi);
- f3_mulf(ray_org, ray_dir, hit.distance);
- f3_set(ray_dir, wi);
- ray_range[0] = offset;
- throughput *= ALBEDO / pdf * cos_theta;
+ ssp_ran_hemisphere_cos(rng, N, sample);
+ pdf = sample[3];
+ cos_theta = f3_dot(N, sample);
+ f3_set(ray_org, pos);
+ f3_set(ray_dir, sample);
+ ray_range[0] = EPSILON;
+ throughput *= (float)(ALBEDO / PI) / pdf * cos_theta;
}
*(float*)value = L;
}
@@ -273,7 +304,7 @@ main(int argc, char** argv)
struct s3d_shape* shape;
struct s3d_vertex_data attribs[2];
struct smc_device* smc;
- unsigned char* img;
+ unsigned char* img = NULL;
size_t ix, iy;
float pos[3];
(void)argc, (void)argv;
@@ -343,8 +374,8 @@ main(int argc, char** argv)
unsigned char colu;
CHECK(smc_estimator_get_status(estimator, &status), RES_OK);
- col = CLAMP(SMC_FLOAT(status.E), 0.f, 1.f);
- colu = (unsigned char)(col * 255.f);
+ col = (float)pow(SMC_FLOAT(status.E), 1.0/2.2); /* Gamma correction */
+ colu = (unsigned char)(CLAMP(col, 0.f, 1.f) * 255.f); /* Float to U8 */
img[ipix + 0] = colu;
img[ipix + 1] = colu;
img[ipix + 2] = colu;