Skip to content

Commit

Permalink
add scattering pdf and sampling for HittableList. add option to chang…
Browse files Browse the repository at this point in the history
…e sampling behavior
  • Loading branch information
gau-nernst committed Nov 27, 2023
1 parent 610308f commit c736880
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 9 deletions.
3 changes: 2 additions & 1 deletion include/raytracing.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

typedef struct World {
HittableList objects;
Hittable *light;
HittableList lights;
} World;

void World_init(World *world, size_t max_objects);
Expand All @@ -34,6 +34,7 @@ typedef struct Camera {
Vec3 w;
Vec3 dof_disc_u;
Vec3 dof_disc_v;
bool importance_sampling;
} Camera;

void Camera_init(Camera *camera);
Expand Down
21 changes: 20 additions & 1 deletion src/hittable.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,26 @@ static bool HittableList_hit(const Hittable *self_, const Ray *ray, float t_min,

return hit_anything;
}
static HittableVTable HITTABLE_LIST_VTABLE = {HittableList_hit};
static float HittableList_pdf(const Hittable *self_, const Ray *ray, PCG32 *rng) {
const HittableList *self = (const HittableList *)self_;
float pdf = 0.0f;
float count = 0.0f;
for (int i = 0; i < self->size; i++) {
if (self->items[i]->vtable->pdf != NULL) { // TODO: remove this when all hittables implement pdf
pdf += self->items[i]->vtable->pdf(self->items[i], ray, rng);
count += 1.0f;
}
}
return pdf / fmaxf(count, 1.0f);
}
static Vec3 HittableList_rand(const Hittable *self_, Vec3 origin, PCG32 *rng) {
const HittableList *self = (const HittableList *)self_;
Hittable *obj = self->items[pcg32_u32_between(rng, 0, self->size)];
if (obj->vtable->rand == NULL)
return HittableList_rand(self_, origin, rng); // rejection sampling
return obj->vtable->rand(obj, origin, rng);
}
static HittableVTable HITTABLE_LIST_VTABLE = {HittableList_hit, HittableList_pdf, HittableList_rand};
void HittableList_init(HittableList *self, size_t max_size) {
*self =
(HittableList){{&HITTABLE_LIST_VTABLE, AABB_EMPTY}, max_size, 0, my_malloc(sizeof(self->items[0]) * max_size)};
Expand Down
14 changes: 11 additions & 3 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,15 @@ void scene_simple_light(World *world, Camera *camera) {
Material *light = DiffuseLight_new(Solid_new(vec3(4, 4, 4)));
HittableList_append(&world->objects, Sphere_new(vec3(0, -1000, 0), 1000, perlin));
HittableList_append(&world->objects, Sphere_new(vec3(0, 2, 0), 2, perlin));
HittableList_append(&world->objects, Sphere_new(vec3(0, 7, 0), 2, light));
HittableList_append(&world->objects, Quad_new(vec3(3, 1, -2), vec3(2, 0, 0), vec3(0, 2, 0), light));

Hittable *light_src;
light_src = Quad_new(vec3(3, 1, -2), vec3(2, 0, 0), vec3(0, 2, 0), light);
HittableList_append(&world->objects, light_src);
HittableList_append(&world->lights, light_src);

light_src = Sphere_new(vec3(0, 7, 0), 2, light);
HittableList_append(&world->objects, light_src);
HittableList_append(&world->lights, light_src);

camera->vfov = 20.0f;
camera->background = VEC3_ZERO;
Expand All @@ -160,7 +167,7 @@ void scene_cornell_box(World *world, Camera *camera) {

Hittable *light_src = Quad_new(vec3(343, 554, 332), vec3(-130, 0, 0), vec3(0, 0, -105), light);
HittableList_append(&world->objects, light_src);
world->light = light_src;
HittableList_append(&world->lights, light_src);

Hittable *box1 = Box_new(vec3(0, 0, 0), vec3(165, 330, 165), white);
box1 = RotateY_new(box1, 15);
Expand Down Expand Up @@ -272,6 +279,7 @@ int main(int argc, char *argv[]) {
camera.vup = vec3(0, 1, 0);
camera.dof_angle = 0.0f;
camera.focal_length = 10.0f;
camera.importance_sampling = true;

if (argc > 3)
camera.img_width = strtol(argv[2], NULL, 10);
Expand Down
12 changes: 8 additions & 4 deletions src/raytracing.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
#include <math.h>
#include <stdio.h>

void World_init(World *world, size_t max_objects) { HittableList_init(&world->objects, max_objects); }
void World_init(World *world, size_t max_objects) {
HittableList_init(&world->objects, max_objects);
HittableList_init(&world->lights, max_objects);
}

void Camera_init(Camera *camera) {
camera->img_height = (int)((float)camera->img_width / camera->aspect_ratio);
Expand Down Expand Up @@ -48,10 +51,11 @@ static Vec3 Camera_ray_color(const Camera *camera, const Ray *ray, const World *
return emission_color;

// mixture pdf
if (world->light != NULL) {
if (camera->importance_sampling) {
const Hittable *lights = &world->lights.hittable;
if (pcg32_f32(rng) < 0.5f) // change scatter ray towards the light half of the time
new_ray.direction = world->light->vtable->rand(world->light, rec.p, rng);
pdf = 0.5f * pdf + 0.5f * world->light->vtable->pdf(world->light, &new_ray, rng); // update pdf
new_ray.direction = lights->vtable->rand(lights, rec.p, rng);
pdf = 0.5f * pdf + 0.5f * lights->vtable->pdf(lights, &new_ray, rng); // update pdf
}

// spawn new ray
Expand Down

0 comments on commit c736880

Please sign in to comment.