raytracer

raytracer.git
git clone git://git.lenczewski.org/raytracer.git
Log | Files | Refs | README | LICENSE

rt.c (2285B)


      1 #include "rt.h"
      2 
      3 extern inline void
      4 world_init(struct world *world);
      5 
      6 extern inline void
      7 world_push(struct world *world, struct hittable *hittable);
      8 
      9 inline color_t
     10 ray_color(struct ray *ray, struct list_node *objects)
     11 {
     12 	struct hit_record hit_record;
     13 	struct interval t = { .min = 0, .max = INFINITY, };
     14 	int hit_something = 0;
     15 
     16 	struct hittable *it;
     17 	LIST_ENTRY_ITER(objects, it, list_node) {
     18 		if (it->impl(it, ray, t, &hit_record)) {
     19 			hit_something = 1;
     20 			t.max = hit_record.t;
     21 		}
     22 	}
     23 
     24 	if (hit_something) {
     25 		return VEC3MULS(color_t,
     26 				VEC3ADDS(vec3f_t, hit_record.normal, 1), 0.5);
     27 	}
     28 
     29 	vec3f_t unit_direction = VEC3UNIT(ray->direction);
     30 	float a = 0.5 * (unit_direction.xyz.y + 1);
     31 	return VEC3LERP(VEC31(color_t), VEC3(color_t, 0, 0, 1), a);
     32 }
     33 
     34 void
     35 render(pixel_t *image, size_t image_width, size_t image_height, struct world *world)
     36 {
     37 	// camera
     38 	float aspect_ratio = (float) image_width / image_height;
     39 
     40 	float focal_length = 1.0;
     41 
     42 	vec3f_t camera_centre = VEC30(vec3f_t);
     43 
     44 	float viewport_width = 4.0, viewport_height = viewport_width / aspect_ratio;
     45 	vec3f_t viewport_u = VEC3(vec3f_t, +viewport_width, 0, 0);
     46 	vec3f_t viewport_v = VEC3(vec3f_t, 0, -viewport_height, 0);
     47 	vec3f_t pixel_du = VEC3DIVS(vec3f_t, viewport_u, image_width);
     48 	vec3f_t pixel_dv = VEC3DIVS(vec3f_t, viewport_v, image_height);
     49 
     50 	vec3f_t viewport_origin = VEC3SUB(vec3f_t,
     51 					VEC3SUB(vec3f_t,
     52 						VEC3SUB(vec3f_t, camera_centre, VEC3(vec3f_t, 0, 0, focal_length)),
     53 						VEC3DIVS(vec3f_t, viewport_u, 2)),
     54 					VEC3DIVS(vec3f_t, viewport_v, 2));
     55 
     56 	vec3f_t pixel00 = VEC3ADD(vec3f_t,
     57 				viewport_origin,
     58 				VEC3MULS(vec3f_t, VEC3ADD(vec3f_t, pixel_du, pixel_dv), 0.5));
     59 
     60 	// rendering
     61 	for (size_t j = 0; j < image_height; j++) {
     62 		fprintf(stderr, "Scanline: %zu/%zu\n", j, image_height);
     63 		for (size_t i = 0; i < image_width; i++) {
     64 			vec3f_t pixel_centre = VEC3ADD(vec3f_t,
     65 						pixel00,
     66 						VEC3ADD(vec3f_t,
     67 							VEC3MULS(vec3f_t, pixel_du, i),
     68 							VEC3MULS(vec3f_t, pixel_dv, j)));
     69 
     70 			vec3f_t ray_direction = VEC3SUB(vec3f_t, pixel_centre, camera_centre);
     71 
     72 			struct ray ray = { .origin = camera_centre, .direction = ray_direction, };
     73 			color_t color = ray_color(&ray, &world->objects);
     74 
     75 			image[j * image_width + i] = pixel_from_color(color, PIXEL_FORMAT_ARGB32);
     76 		}
     77 	}
     78 }