Make samples per pixel a camera parameter

This commit is contained in:
2025-09-23 15:36:08 +01:00
parent 1eb8fd3067
commit 1e31fae5d0
3 changed files with 12 additions and 10 deletions

4
demo.c
View File

@@ -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);

View File

@@ -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,

View File

@@ -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,
};
}