#include "ff.h" #include "render.h" #include #define W 1280 #define H 720 #define OBJ_COUNT 32 #define MAX_DIST 100.0 #define MAX_RAD 10.0 #define MIN_RAD 1.0 #define FOV 90 #define APERTURE 0.8 #define FOCAL_LEN 100 #define SAMPLES_PER_PIXEL 100 #define NELEMS(arr) (sizeof(arr) / sizeof(arr[0])) static const vec3_t camera_pos = { -100.0, 30.0, -100.0 }; static const vec3_t target = { 0.0, 0.0, 0.0 }; static const vec3_t sky_pos = { 0.6, 0.8, 1.0 }; static const vec3_t sky_neg = { 1.0, 1.0, 1.0 }; static const material_t floor = LAMBERTIAN(1.0, 0.94, 0.80); static const material_t light = AREA_LIGHT(1.0, 0.8, 0.1, 4.0); 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, gold, silver, silver, bronze }; static obj_t objs[OBJ_COUNT] = { SPHERE(0.0, -100'000.0, 0.0, 100'000.0, floor), SPHERE(-3000.0, 3000.0, -2000.0, 1000.0, light), }; static pix_t pixbuf[W * H]; static void rand_obj(obj_t *out, rng_t *rng) { material_t material; const double rand = rng_canon(rng); if (rand < 0.75) { 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 < 0.925) { material = glass; } else { material = metals[rng_uint32(rng) % NELEMS(metals)]; } const double r = MIN_RAD + (MAX_RAD - MIN_RAD) * rng_canon(rng); const double x = MAX_DIST * rng_plusminus(rng); const double z = MAX_DIST * rng_plusminus(rng); *out = (obj_t)SPHERE(x, r, z, r, material); } int main() { rng_t rng = rng_init(0); for (int i = 2; 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, APERTURE, FOCAL_LEN); const scene_t scene = { .sky_pos = sky_pos, .sky_neg = sky_neg, .objs = objs, .obj_count = OBJ_COUNT, }; render(&camera, &scene, &img, SAMPLES_PER_PIXEL); ff_write(STDOUT_FILENO, img); return 0; }