From 43670cbfbab7bb128cf906ef924c473801a58482 Mon Sep 17 00:00:00 2001 From: Camden Dixie O'Brien Date: Tue, 23 Sep 2025 15:35:26 +0100 Subject: [PATCH] Randomise scene --- demo.c | 67 +++++++++++++++++++++++++++++++++++++-------------- include/rng.h | 2 ++ src/rng.c | 30 +++++++++++------------ 3 files changed, 66 insertions(+), 33 deletions(-) diff --git a/demo.c b/demo.c index 07e6d64..e82da25 100644 --- a/demo.c +++ b/demo.c @@ -7,40 +7,71 @@ #define W 800 #define H 600 + +#define OBJ_COUNT 32 + +#define MAX_DIST 100.0 +#define MAX_RAD 10.0 +#define MIN_RAD 1.0 + #define FOV 90 #define SAMPLES_PER_PIXEL 100 -#define NELEMS(arr) (sizeof(arr) / sizeof(arr[0])) - -static const vec3_t camera_pos = { 0.0, 1.5, -2.0 }; -static const vec3_t camera_target = { 0.0, 1.0, 1.0 }; +static const vec3_t camera_pos = { -100.0, 25.0, -100.0 }; +static const vec3_t target = { 0.0, 0.0, 0.0 }; static const vec3_t sky = { 0.6, 0.7, 1.0 }; -static const obj_t objs[] = { - SPHERE(1.0, 1.0, 3.0, 1.0, LAMBERTIAN(0.6, 0.2, 0.8)), - SPHERE(-0.8, 1.0, 3.8, 1.0, LAMBERTIAN(1.0, 1.0, 1.0)), - SPHERE(-1.0, 0.2, 2.6, 0.2, LAMBERTIAN(0.2, 0.9, 0.3)), - SPHERE(0.3, 0.3, 1.8, 0.3, LAMBERTIAN(0.9, 0.6, 0.2)), - SPHERE(-1.6, 0.2, 2.0, 0.2, REFLECTIVE(1.0, 0.9, 0.4, 0.0)), - SPHERE(-6.0, 6.0, 5.0, 6.0, REFLECTIVE(0.9, 0.9, 0.9, 0.05)), - SPHERE(-0.7, 0.25, 1.5, 0.25, DIELECTRIC(1.5)), - SPHERE(0.0, -1000.0, 0.0, 1000.0, LAMBERTIAN(0.3, 0.3, 0.3)), +static const material_t floor = LAMBERTIAN(1.0, 0.94, 0.80); +static const material_t gold = REFLECTIVE(1.0, 0.9, 0.5, 0.0); +static const material_t silver = REFLECTIVE(0.9, 0.9, 0.9, 0.0); +static const material_t bronze = REFLECTIVE(0.9, 0.7, 0.5, 0.0); +static const material_t glass = DIELECTRIC(1.5); + +static const material_t metals[] = { gold, silver, bronze }; + +static obj_t objs[OBJ_COUNT] = { + [0] = SPHERE(0.0, -100000.0, 0.0, 100000.0, floor), }; static pix_t pixbuf[W * H]; +static void rand_obj(obj_t *out, rng_t *rng) +{ + material_t material; + const uint32_t rand = rng_uint32(rng); + if (rand % 2 == 0) { + const double r = rng_canon(rng); + const double g = rng_canon(rng); + const double b = rng_canon(rng); + material = (material_t)LAMBERTIAN(r, g, b); + } else if (rand % 3 == 0) { + material = glass; + } else { + material = metals[rng_uint32(rng) % 3]; + } + + const double r = MIN_RAD + (MAX_RAD - MIN_RAD) * rng_canon(rng); + const double x = MAX_DIST * rng_disc(rng); + const double z = MAX_DIST * rng_disc(rng); + *out = (obj_t)SPHERE(x, r, z, r, material); +} + int main() { + rng_t rng = rng_init(0); + for (int i = 1; i < OBJ_COUNT; ++i) + rand_obj(objs + i, &rng); + + img_t img = { .pix = pixbuf }; + camera_t camera + = camera_init(camera_pos, target, FOV, W, H, SAMPLES_PER_PIXEL); + const scene_t scene = { .sky_colour = sky, .objs = objs, - .obj_count = NELEMS(objs), + .obj_count = OBJ_COUNT, }; - - img_t img = { .pix = pixbuf }; - camera_t camera = camera_init( - camera_pos, camera_target, FOV, W, H, SAMPLES_PER_PIXEL); camera_render(&camera, &scene, &img); ff_write(STDOUT_FILENO, img); diff --git a/include/rng.h b/include/rng.h index 0d422f4..2ff4800 100644 --- a/include/rng.h +++ b/include/rng.h @@ -10,7 +10,9 @@ typedef struct { } rng_t; rng_t rng_init(unsigned seed); +uint32_t rng_uint32(rng_t *rng); double rng_canon(rng_t *rng); +double rng_disc(rng_t *rng); vec3_t rng_vec3(rng_t *rng); vec3_t rng_gaussian_xy(rng_t *rng, double stddev); diff --git a/src/rng.c b/src/rng.c index 7cc508a..acc5e6a 100644 --- a/src/rng.c +++ b/src/rng.c @@ -9,7 +9,14 @@ #define M_PI 3.14159265258979323846264 #endif -static uint32_t next(rng_t *rng) +rng_t rng_init(unsigned seed) +{ + struct timeval tv; + gettimeofday(&tv, nullptr); + return (rng_t) { .state = tv.tv_usec + seed }; +} + +uint32_t rng_uint32(rng_t *rng) { uint32_t x = rng->state; x ^= x << 13; @@ -18,26 +25,19 @@ static uint32_t next(rng_t *rng) return rng->state = x; } -static double disc(rng_t *rng) +double rng_canon(rng_t *rng) +{ + return (double)rng_uint32(rng) / (double)UINT32_MAX; +} + +double rng_disc(rng_t *rng) { return 2.0 * rng_canon(rng) - 1.0; } -rng_t rng_init(unsigned seed) -{ - struct timeval tv; - gettimeofday(&tv, nullptr); - return (rng_t) { .state = tv.tv_usec + seed }; -} - -double rng_canon(rng_t *rng) -{ - return (double)next(rng) / (double)UINT32_MAX; -} - vec3_t rng_vec3(rng_t *rng) { - const vec3_t v = { disc(rng), disc(rng), disc(rng) }; + const vec3_t v = { rng_disc(rng), rng_disc(rng), rng_disc(rng) }; return vec3_unit(v); }