Allow camera position and target position to vary

This commit is contained in:
Camden Dixie O'Brien
2025-09-22 20:16:41 +01:00
parent 6e8dd39d43
commit fb09a5553e
3 changed files with 32 additions and 25 deletions

24
demo.c
View File

@@ -7,22 +7,23 @@
#define W 800
#define H 600
#define FOV 120
#define FOV 90
#define SAMPLES_PER_PIXEL 100
#define NELEMS(arr) (sizeof(arr) / sizeof(arr[0]))
static const vec3_t camera_pos = { 0.0, 0.0, 0.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 obj_t scene[] = {
SPHERE(1.0, 0.0, -3.0, 1.0, LAMBERTIAN(0.6, 0.2, 0.8)),
SPHERE(-0.8, 0.0, -3.8, 1.0, LAMBERTIAN(1.0, 1.0, 1.0)),
SPHERE(-1.0, -0.8, -2.6, 0.2, LAMBERTIAN(0.2, 0.9, 0.3)),
SPHERE(0.3, -0.7, -1.8, 0.3, LAMBERTIAN(0.9, 0.6, 0.2)),
SPHERE(-1.6, -0.8, -2.0, 0.2, REFLECTIVE(1.0, 0.9, 0.4, 0.0)),
SPHERE(-6.0, 5.0, -5.0, 6.0, REFLECTIVE(0.9, 0.9, 0.9, 0.05)),
SPHERE(-0.7, -0.75, -1.5, 0.25, DIELECTRIC(1.5)),
SPHERE(0.0, -1001.0, 0.0, 1000.0, LAMBERTIAN(0.3, 0.3, 0.3)),
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 pix_t pixbuf[W * H];
@@ -30,7 +31,8 @@ static pix_t pixbuf[W * H];
int main()
{
img_t img = { .pix = pixbuf };
camera_t camera = camera_init(camera_pos, FOV, W, H, SAMPLES_PER_PIXEL);
camera_t camera = camera_init(
camera_pos, camera_target, FOV, W, H, SAMPLES_PER_PIXEL);
camera_render(&camera, scene, NELEMS(scene), &img);
ff_write(STDOUT_FILENO, img);

View File

@@ -15,8 +15,8 @@ typedef struct {
} camera_t;
camera_t camera_init(
vec3_t pos, double fov, uint32_t img_width, uint32_t img_height,
unsigned samples_per_pixel);
vec3_t pos, vec3_t target, double fov, uint32_t img_width,
uint32_t img_height, unsigned samples_per_pixel);
void camera_render(
const camera_t *camera, const obj_t *scene, unsigned scene_count,

View File

@@ -16,7 +16,6 @@
#define MAX_ITER 10
#define MIN_T 1e-6
#define SAMPLE_STDDEV 0.333
#define FOCAL_LEN 1.0
#define GAMMA 2.2
@@ -31,6 +30,8 @@ typedef struct {
atomic_uint *progress;
} work_slice_t;
static const vec3_t up = { 0.0, 1.0, 0.0 };
static const vec3_t lightblue = { 0.4, 0.6, 1.0 };
static const vec3_t white = { 1.0, 1.0, 1.0 };
static const vec3_t black = { 0.0, 0.0, 0.0 };
@@ -97,10 +98,11 @@ static int render_thread(void *arg)
const vec3_t offset = vec3_add(
vec3_scale(camera->x_step, jitter.x),
vec3_scale(camera->y_step, jitter.y));
const vec3_t jittered_pix = vec3_add(pix, offset);
const ray_t ray = {
.orig = camera->pos,
.dir = vec3_unit(vec3_add(pix, offset)),
.dir = vec3_unit(vec3_sub(jittered_pix, camera->pos)),
};
const vec3_t sample = trace(
ray, slice->scene, slice->scene_count, &slice->rng);
@@ -118,20 +120,23 @@ static int render_thread(void *arg)
}
camera_t camera_init(
vec3_t pos, double fov, uint32_t img_width, uint32_t img_height,
unsigned samples_per_pixel)
vec3_t pos, vec3_t target, double fov, uint32_t img_width,
uint32_t img_height, unsigned samples_per_pixel)
{
const double aspect = (double)img_width / (double)img_height;
const double fov_rad = M_PI * fov / 180.0;
const double viewport_height = FOCAL_LEN * tan(fov_rad / 2);
const double aspect = (double)img_width / (double)img_height;
const double viewport_height = tan(fov_rad / 2);
const double viewport_width = viewport_height * aspect;
const vec3_t viewport_disp = { 0, 0, FOCAL_LEN };
const vec3_t u = { viewport_width, 0, 0 };
const vec3_t v = { 0, -viewport_height, 0 };
const vec3_t topleft = vec3_sub(
vec3_sub(pos, viewport_disp), vec3_scale(vec3_add(u, v), 0.5));
const vec3_t w_hat = vec3_unit(vec3_sub(target, pos));
const vec3_t u_hat = vec3_unit(vec3_cross(up, w_hat));
const vec3_t v_hat = vec3_unit(vec3_cross(w_hat, u_hat));
const vec3_t u = vec3_scale(u_hat, viewport_width);
const vec3_t v = vec3_scale(v_hat, -viewport_height);
const vec3_t topleft
= vec3_sub(vec3_add(pos, w_hat), vec3_scale(vec3_add(u, v), 0.5));
const vec3_t x_step = vec3_scale(u, 1.0 / (double)img_width);
const vec3_t y_step = vec3_scale(v, 1.0 / (double)img_height);