Make samples per pixel a camera parameter

This commit is contained in:
Camden Dixie O'Brien
2025-09-23 15:35:26 +01:00
parent 73028df5b3
commit 746b902302
3 changed files with 12 additions and 10 deletions

4
demo.c
View File

@@ -9,6 +9,7 @@
#define H 600 #define H 600
#define FOCAL_LEN 1.0 #define FOCAL_LEN 1.0
#define VIEWPORT_H 2.0 #define VIEWPORT_H 2.0
#define SAMPLES_PER_PIXEL 100
#define NELEMS(arr) (sizeof(arr) / sizeof(arr[0])) #define NELEMS(arr) (sizeof(arr) / sizeof(arr[0]))
@@ -30,7 +31,8 @@ static pix_t pixbuf[W * H];
int main() int main()
{ {
img_t img = { .pix = pixbuf }; 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); camera_render(&camera, scene, NELEMS(scene), &img);
ff_write(STDOUT_FILENO, img); ff_write(STDOUT_FILENO, img);

View File

@@ -11,11 +11,12 @@ typedef struct {
vec3_t pos; vec3_t pos;
vec3_t pix_origin, x_step, y_step; vec3_t pix_origin, x_step, y_step;
uint32_t img_width, img_height; uint32_t img_width, img_height;
unsigned samples_per_pixel;
} camera_t; } camera_t;
camera_t camera_init( camera_t camera_init(
vec3_t pos, double focal_len, double viewport_height, uint32_t img_width, 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( void camera_render(
const camera_t *camera, const obj_t *scene, unsigned scene_count, const camera_t *camera, const obj_t *scene, unsigned scene_count,

View File

@@ -11,14 +11,11 @@
#define MAX_ITER 10 #define MAX_ITER 10
#define MIN_T 1e-6 #define MIN_T 1e-6
#define NSAMPLES 100
#define SAMPLE_WEIGHT (1.0 / (double)NSAMPLES)
#define SAMPLE_STDDEV 0.333 #define SAMPLE_STDDEV 0.333
#define GAMMA 2.2 #define GAMMA 2.2
#define NTHREADS 40 #define NTHREADS 20
typedef struct { typedef struct {
const camera_t *camera; 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; vec3_t atten;
if (!material.scatter(material.params, hit, rng, &ray, &atten)) if (!material.scatter(material.params, hit, rng, &ray, &atten))
break; return black;
colour = vec3_hadamard(colour, atten); colour = vec3_hadamard(colour, atten);
} }
@@ -79,6 +76,7 @@ static int render_thread(void *arg)
work_slice_t *slice = (work_slice_t *)arg; work_slice_t *slice = (work_slice_t *)arg;
const camera_t *camera = slice->camera; const camera_t *camera = slice->camera;
const uint32_t w = camera->img_width; 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; const unsigned stop_y = slice->start_y + slice->row_count;
for (unsigned y = slice->start_y; y < stop_y; ++y) { 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)); const vec3_t pix = vec3_add(row, vec3_scale(camera->x_step, x));
vec3_t colour = black; 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 const vec3_t jitter
= rng_gaussian_xy(&slice->rng, SAMPLE_STDDEV); = rng_gaussian_xy(&slice->rng, SAMPLE_STDDEV);
const vec3_t offset = vec3_add( const vec3_t offset = vec3_add(
@@ -102,7 +100,7 @@ static int render_thread(void *arg)
const vec3_t sample = trace( const vec3_t sample = trace(
ray, slice->scene, slice->scene_count, &slice->rng); 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)); setpix(colour, slice->pixels + (w * y + x));
@@ -116,7 +114,7 @@ static int render_thread(void *arg)
camera_t camera_init( camera_t camera_init(
vec3_t pos, double focal_len, double viewport_height, uint32_t img_width, 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 aspect = (double)img_width / (double)img_height;
const double viewport_width = viewport_height * aspect; const double viewport_width = viewport_height * aspect;
@@ -138,6 +136,7 @@ camera_t camera_init(
.y_step = y_step, .y_step = y_step,
.img_width = img_width, .img_width = img_width,
.img_height = img_height, .img_height = img_height,
.samples_per_pixel = samples_per_pixel,
}; };
} }