From 1e31fae5d0ffc809ef4e36b02782368c45a99791 Mon Sep 17 00:00:00 2001 From: Camden Dixie O'Brien Date: Tue, 23 Sep 2025 15:36:08 +0100 Subject: [PATCH] Make samples per pixel a camera parameter --- demo.c | 4 +++- include/camera.h | 3 ++- src/camera.c | 15 +++++++-------- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/demo.c b/demo.c index 23423d5..2d3e103 100644 --- a/demo.c +++ b/demo.c @@ -9,6 +9,7 @@ #define H 600 #define FOCAL_LEN 1.0 #define VIEWPORT_H 2.0 +#define SAMPLES_PER_PIXEL 100 #define NELEMS(arr) (sizeof(arr) / sizeof(arr[0])) @@ -30,7 +31,8 @@ static pix_t pixbuf[W * H]; int main() { img_t img = { .pix = pixbuf }; - camera_t camera = camera_init(camera_pos, FOCAL_LEN, VIEWPORT_H, W, H); + camera_t camera = camera_init( + camera_pos, FOCAL_LEN, VIEWPORT_H, W, H, SAMPLES_PER_PIXEL); camera_render(&camera, scene, NELEMS(scene), &img); ff_write(STDOUT_FILENO, img); diff --git a/include/camera.h b/include/camera.h index cf434f5..354f14c 100644 --- a/include/camera.h +++ b/include/camera.h @@ -11,11 +11,12 @@ typedef struct { vec3_t pos; vec3_t pix_origin, x_step, y_step; uint32_t img_width, img_height; + unsigned samples_per_pixel; } camera_t; camera_t camera_init( vec3_t pos, double focal_len, double viewport_height, uint32_t img_width, - uint32_t img_height); + uint32_t img_height, unsigned samples_per_pixel); void camera_render( const camera_t *camera, const obj_t *scene, unsigned scene_count, diff --git a/src/camera.c b/src/camera.c index d923870..2a41393 100644 --- a/src/camera.c +++ b/src/camera.c @@ -11,14 +11,11 @@ #define MAX_ITER 10 #define MIN_T 1e-6 - -#define NSAMPLES 100 -#define SAMPLE_WEIGHT (1.0 / (double)NSAMPLES) #define SAMPLE_STDDEV 0.333 #define GAMMA 2.2 -#define NTHREADS 40 +#define NTHREADS 20 typedef struct { const camera_t *camera; @@ -54,7 +51,7 @@ trace(ray_t ray, const obj_t *scene, unsigned scene_count, rng_t *rng) vec3_t atten; if (!material.scatter(material.params, hit, rng, &ray, &atten)) - break; + return black; colour = vec3_hadamard(colour, atten); } @@ -79,6 +76,7 @@ static int render_thread(void *arg) work_slice_t *slice = (work_slice_t *)arg; const camera_t *camera = slice->camera; const uint32_t w = camera->img_width; + const double sample_weight = 1.0 / (double)camera->samples_per_pixel; const unsigned stop_y = slice->start_y + slice->row_count; for (unsigned y = slice->start_y; y < stop_y; ++y) { @@ -88,7 +86,7 @@ static int render_thread(void *arg) const vec3_t pix = vec3_add(row, vec3_scale(camera->x_step, x)); vec3_t colour = black; - for (unsigned i = 0; i < NSAMPLES; ++i) { + for (unsigned i = 0; i < camera->samples_per_pixel; ++i) { const vec3_t jitter = rng_gaussian_xy(&slice->rng, SAMPLE_STDDEV); const vec3_t offset = vec3_add( @@ -102,7 +100,7 @@ static int render_thread(void *arg) const vec3_t sample = trace( ray, slice->scene, slice->scene_count, &slice->rng); - colour = vec3_add(colour, vec3_scale(sample, SAMPLE_WEIGHT)); + colour = vec3_add(colour, vec3_scale(sample, sample_weight)); } setpix(colour, slice->pixels + (w * y + x)); @@ -116,7 +114,7 @@ static int render_thread(void *arg) camera_t camera_init( vec3_t pos, double focal_len, double viewport_height, uint32_t img_width, - uint32_t img_height) + uint32_t img_height, unsigned samples_per_pixel) { const double aspect = (double)img_width / (double)img_height; const double viewport_width = viewport_height * aspect; @@ -138,6 +136,7 @@ camera_t camera_init( .y_step = y_step, .img_width = img_width, .img_height = img_height, + .samples_per_pixel = samples_per_pixel, }; }