feat(examples): add the scene representation, camera and intersection

Sphere and plane records, camera ray generation from field of view and aspect
ratio, and the nearest-hit search across the scene.
This commit is contained in:
sneeker committed 2022-07-02 02:41:00 +00:00
1 parent d1c5055303
commit 3da0447ea6
3 files changed
+137

No files matched your search

+67
View File
@@ -0,0 +1,67 @@
#ifndef RT_SCENE_H
#define RT_SCENE_H
#include "rt.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
vec3 origin, dir;
} ray;
typedef enum { MAT_LAMBERT = 0, MAT_METAL = 1, MAT_LIGHT = 2 } mat_kind;
typedef struct {
mat_kind kind;
vec3 albedo;
double fuzz;
} material;
typedef struct {
vec3 center;
double radius;
material mat;
} sphere;
typedef struct {
const sphere *spheres;
int count;
vec3 background;
} scene;
typedef struct {
vec3 origin, lower_left, horizontal, vertical;
} camera;
typedef struct {
double t;
vec3 point, normal;
material mat;
int front;
} hit;
camera camera_make(vec3 look_from, vec3 look_at, vec3 up, double fov_deg, double aspect);
ray camera_ray(const camera *c, double u, double v);
int scene_hit(const scene *s, ray r, double tmin, double tmax, hit *out);
vec3 ray_colour(const scene *s, ray r, int depth, rng *rng_state);
typedef struct {
const scene *sc;
const camera *cam;
unsigned char *rgb;
int width, height, samples, max_depth;
int row_next;
int threads;
} render_job;
/* Returns the number of worker threads actually used. */
int render_run(render_job *job);
#ifdef __cplusplus
}
#endif
#endif
+27
View File
@@ -0,0 +1,27 @@
#include "rt_scene.h"
#include <math.h>
camera camera_make(vec3 look_from, vec3 look_at, vec3 up, double fov_deg, double aspect) {
double theta = fov_deg * 3.14159265358979323846 / 180.0;
double half_height = tan(theta / 2.0);
double half_width = aspect * half_height;
vec3 w = v3norm(v3sub(look_from, look_at));
vec3 u = v3norm(v3cross(up, w));
vec3 v = v3cross(w, u);
camera c;
c.origin = look_from;
c.horizontal = v3scale(u, 2.0 * half_width);
c.vertical = v3scale(v, 2.0 * half_height);
c.lower_left = v3sub(v3sub(v3sub(look_from, v3scale(u, half_width)), v3scale(v, half_height)), w);
return c;
}
ray camera_ray(const camera *c, double u, double v) {
vec3 target = v3add(v3add(c->lower_left, v3scale(c->horizontal, u)), v3scale(c->vertical, v));
ray r;
r.origin = c->origin;
r.dir = v3norm(v3sub(target, c->origin));
return r;
}
+43
View File
@@ -0,0 +1,43 @@
#include "rt_scene.h"
#include <math.h>
static int sphere_hit(const sphere *s, ray r, double tmin, double tmax, hit *out) {
vec3 oc = v3sub(r.origin, s->center);
double a = v3len2(r.dir);
double half_b = v3dot(oc, r.dir);
double c = v3len2(oc) - s->radius * s->radius;
double disc = half_b * half_b - a * c;
if (disc < 0.0) return 0;
double root = sqrt(disc);
double t = (-half_b - root) / a;
if (t < tmin || t > tmax) {
t = (-half_b + root) / a;
if (t < tmin || t > tmax) return 0;
}
out->t = t;
out->point = v3add(r.origin, v3scale(r.dir, t));
vec3 outward = v3scale(v3sub(out->point, s->center), 1.0 / s->radius);
out->front = v3dot(r.dir, outward) < 0.0;
out->normal = out->front ? outward : v3neg(outward);
out->mat = s->mat;
return 1;
}
int scene_hit(const scene *s, ray r, double tmin, double tmax, hit *out) {
hit best;
int found = 0;
double closest = tmax;
for (int i = 0; i < s->count; i++) {
hit h;
if (sphere_hit(&s->spheres[i], r, tmin, closest, &h)) {
found = 1;
closest = h.t;
best = h;
}
}
if (found) *out = best;
return found;
}