rt.h (14139B)
1 #ifndef RT_H 2 #define RT_H 3 4 #include <assert.h> 5 #include <stdint.h> 6 #include <stdio.h> 7 #include <stdlib.h> 8 #include <string.h> 9 #include <unistd.h> 10 11 #include <fcntl.h> 12 13 // memory utilities 14 // =========================================================================== 15 16 #include <stdalign.h> 17 #include <stddef.h> 18 19 #define IS_POW2(v) (((v) & ((v) - 1)) == 0) 20 21 #define IS_ALIGNED(v, align) (((v) & ((align) - 1)) == 0) 22 #define ALIGN_PREV(v, align) ((v) & ~((align) - 1)) 23 #define ALIGN_NEXT(v, align) ALIGN_PREV((v) + ((align) - 1), (align)) 24 25 struct arena { 26 void *ptr; 27 size_t cap, len; 28 }; 29 30 inline void 31 arena_reset(struct arena *arena) 32 { 33 arena->len = 0; 34 } 35 36 inline void * 37 arena_alloc(struct arena *arena, size_t size, size_t alignment) 38 { 39 assert(size); 40 assert(alignment); 41 assert(IS_POW2(alignment)); 42 43 uintptr_t cur_ptr = (uintptr_t) arena->ptr, end_ptr = cur_ptr + arena->cap; 44 45 uintptr_t aligned_ptr = ALIGN_NEXT(cur_ptr, alignment); 46 if (aligned_ptr + size > end_ptr) 47 return NULL; 48 49 arena->len = (aligned_ptr + size) - end_ptr; 50 51 return (void *) aligned_ptr; 52 } 53 54 #define ARENA_ALLOC_ARRAY(arena, T, n) \ 55 arena_alloc((arena), sizeof(T) * (n), alignof(T)) 56 57 #define ARENA_ALLOC_SIZED(arena, T) ARENA_ALLOC_ARRAY((arena), T, 1) 58 59 #define TO_PARENT_PTR(ptr, T, member) \ 60 ((ptr) ? ((T *) (((uintptr_t) (ptr)) - offsetof(T, member))) : NULL) 61 62 struct list_node { 63 struct list_node *prev, *next; 64 }; 65 66 #define LIST_INIT(list) ((struct list_node) { &(list), &(list), }) 67 68 #define LIST_HEAD(list) ((list)->next) 69 #define LIST_TAIL(list) ((list)->prev) 70 71 #define LIST_IS_EMPTY(list) \ 72 (LIST_HEAD(list) == (list) && LIST_TAIL(list) == (list)) 73 74 #define LIST_NODE_ITER(list, it) \ 75 for ((it) = LIST_HEAD(list); (it) != (list); (it) = LIST_HEAD(it)) 76 77 #define LIST_NODE_RITER(list, it) \ 78 for ((it) = LIST_TAIL(list); (it) != (list); (it) = LIST_TAIL(it)) 79 80 #define LIST_NODE_ENTRY(node, T, member) TO_PARENT_PTR((node), T, member) 81 82 #define LIST_ENTRY_ITER(list, it, member) \ 83 for ((it) = LIST_NODE_ENTRY(LIST_HEAD(list), __typeof__ (*(it)), member); \ 84 &(it)->member != (list); \ 85 (it) = LIST_NODE_ENTRY(LIST_HEAD(&(it)->member), __typeof__ (*(it)), member)) 86 87 #define LIST_ENTRY_RITER(list, it, member) \ 88 for ((it) = LIST_NODE_ENTRY(LIST_TAIL(list), __typeof__ (*(it)), member); \ 89 &(it)->member != (list); \ 90 (it) = LIST_NODE_ENTRY(LIST_TAIL(&(it)->member), __typeof__ (*(it)), member)) 91 92 inline void 93 list_node_link(struct list_node *node, struct list_node *prev, struct list_node *next) 94 { 95 node->prev = prev; 96 prev->next = node; 97 node->next = next; 98 next->prev = node; 99 } 100 101 inline struct list_node * 102 list_node_unlink(struct list_node *node) 103 { 104 node->prev->next = node->next; 105 node->next->prev = node->prev; 106 return node; 107 } 108 109 inline void 110 list_push_head(struct list_node *list, struct list_node *node) 111 { 112 list_node_link(node, list, LIST_HEAD(list)); 113 } 114 115 inline void 116 list_push_tail(struct list_node *list, struct list_node *node) 117 { 118 list_node_link(node, LIST_TAIL(list), list); 119 } 120 121 inline struct list_node * 122 list_pop_head(struct list_node *list) 123 { 124 struct list_node *res = list_node_unlink(LIST_HEAD(list)); 125 return res; 126 } 127 128 inline struct list_node * 129 list_pop_tail(struct list_node *list) 130 { 131 struct list_node *res = list_node_unlink(LIST_TAIL(list)); 132 return res; 133 } 134 135 // math utilities 136 // =========================================================================== 137 138 #include <tgmath.h> 139 140 typedef union vec3i { 141 int32_t vs[3]; 142 struct { 143 int32_t x, y, z; 144 } xyz; 145 } vec3i_t; 146 147 typedef union vec3u { 148 uint32_t vs[3]; 149 struct { 150 uint32_t x, y, z; 151 } xyz; 152 } vec3u_t; 153 154 typedef union vec3f { 155 float vs[3]; 156 struct { 157 float x, y, z; 158 } xyz; 159 } vec3f_t; 160 161 typedef union vec3d { 162 double vs[3]; 163 struct { 164 double x, y, z; 165 } xyz; 166 } vec3d_t; 167 168 #define VEC3(T, x, y, z) ((T) { .vs = { (x), (y), (z), }, }) 169 170 #define VEC30(T) VEC3(T, 0, 0, 0) 171 #define VEC31(T) VEC3(T, 1, 1, 1) 172 173 #define VEC3NEG(lhs) \ 174 VEC3(__typeof__ (lhs), -(lhs).xyz.x, -(lhs).xyz.y, -(lhs).xyz.z) 175 176 #define VEC3ADD(T, lhs, rhs) \ 177 VEC3(T, (lhs).xyz.x + (rhs).xyz.x, (lhs).xyz.y + (rhs).xyz.y, (lhs).xyz.z + (rhs).xyz.z) 178 #define VEC3SUB(T, lhs, rhs) \ 179 VEC3(T, (lhs).xyz.x - (rhs).xyz.x, (lhs).xyz.y - (rhs).xyz.y, (lhs).xyz.z - (rhs).xyz.z) 180 #define VEC3MUL(T, lhs, rhs) \ 181 VEC3(T, (lhs).xyz.x * (rhs).xyz.x, (lhs).xyz.y * (rhs).xyz.y, (lhs).xyz.z * (rhs).xyz.z) 182 #define VEC3DIV(T, lhs, rhs) \ 183 VEC3(T, (lhs).xyz.x / (rhs).xyz.x, (lhs).xyz.y / (rhs).xyz.y, (lhs).xyz.z / (rhs).xyz.z) 184 185 #define VEC3ADDS(T, lhs, scalar) \ 186 VEC3(T, (lhs).xyz.x + scalar, (lhs).xyz.y + scalar, (lhs).xyz.z + scalar) 187 #define VEC3SUBS(T, lhs, scalar) \ 188 VEC3(T, (lhs).xyz.x - scalar, (lhs).xyz.y - scalar, (lhs).xyz.z - scalar) 189 #define VEC3MULS(T, lhs, scalar) \ 190 VEC3(T, (lhs).xyz.x * scalar, (lhs).xyz.y * scalar, (lhs).xyz.z * scalar) 191 #define VEC3DIVS(T, lhs, scalar) \ 192 VEC3(T, (lhs).xyz.x / scalar, (lhs).xyz.y / scalar, (lhs).xyz.z / scalar) 193 194 #define VEC3LEN2(lhs) \ 195 (((lhs).xyz.x * (lhs).xyz.x) + ((lhs).xyz.y * (lhs).xyz.y) + ((lhs).xyz.z * (lhs).xyz.z)) 196 197 #define VEC3LEN(lhs) sqrt(VEC3LEN2(lhs)) 198 199 #define VEC3LERP(a, b, t) \ 200 VEC3ADD(__typeof__ (a), \ 201 VEC3MULS(__typeof__ (a), (a), (1 - (t))), \ 202 VEC3MULS(__typeof__ (b), (b), (t))) 203 204 #define VEC3DOT(lhs, rhs) \ 205 (((lhs).xyz.x * (rhs).xyz.x) + ((lhs).xyz.y * (rhs).xyz.y) + ((lhs).xyz.z * (rhs).xyz.z)) 206 207 #define VEC3CROSS(T, lhs, rhs) \ 208 VEC3(T, \ 209 (((lhs).xyz.y * (rhs).xyz.z) - ((lhs).xyz.z * (rhs).xyz.y)), \ 210 (((lhs).xyz.z * (rhs).xyz.x) - ((lhs).xyz.x * (rhs).xyz.z)), \ 211 (((lhs).xyz.x * (rhs).xyz.y) - ((lhs).xyz.y * (rhs).xyz.x))) 212 213 #define VEC3UNIT(lhs) \ 214 VEC3(__typeof__ (lhs), \ 215 (lhs).xyz.x / VEC3LEN(lhs), \ 216 (lhs).xyz.y / VEC3LEN(lhs), \ 217 (lhs).xyz.z / VEC3LEN(lhs)) 218 219 typedef union vec4i { 220 int32_t vs[4]; 221 struct { 222 int32_t x, y, z, w; 223 } xyzw; 224 } vec4i_t; 225 226 typedef union vec4u { 227 uint32_t vs[4]; 228 struct { 229 uint32_t x, y, z, w; 230 } xyzw; 231 } vec4u_t; 232 233 typedef union vec4f { 234 float vs[4]; 235 struct { 236 float x, y, z, w; 237 } xyzw; 238 } vec4f_t; 239 240 typedef union vec4d { 241 double vs[4]; 242 struct { 243 double x, y, z, w; 244 } xyzw; 245 } vec4d_t; 246 247 #define VEC4(T, x, y, z, w) ((T) { .vs = { (x), (y), (z), (w), }, }) 248 249 #define VEC40(T) VEC4(T, 0, 0, 0, 0) 250 #define VEC41(T) VEC4(T, 1, 1, 1, 1) 251 252 #define VEC4NEG(lhs) \ 253 VEC4(__typeof__ (lhs), -(lhs).xyzw.x, -(lhs).xyzw.y, -(lhs).xyzw.z, -(lhs).xyzw.w) 254 255 #define VEC4ADD(T, lhs, rhs) \ 256 VEC4(T, (lhs).xyzw.x + (rhs).xyzw.x, (lhs).xyzw.y + (rhs).xyzw.y, (lhs).xyzw.z + (rhs).xyzw.z, (lhs).xyzw.w + (rhs).xyzw.w) 257 #define VEC4SUB(T, lhs, rhs) \ 258 VEC4(T, (lhs).xyzw.x - (rhs).xyzw.x, (lhs).xyzw.y - (rhs).xyzw.y, (lhs).xyzw.z - (rhs).xyzw.z, (lhs).xyzw.w - (rhs).xyzw.w) 259 #define VEC4MUL(T, lhs, rhs) \ 260 VEC4(T, (lhs).xyzw.x * (rhs).xyzw.x, (lhs).xyzw.y * (rhs).xyzw.y, (lhs).xyzw.z * (rhs).xyzw.z, (lhs).xyzw.w * (rhs).xyzw.w) 261 #define VEC4DIV(T, lhs, rhs) \ 262 VEC4(T, (lhs).xyzw.x / (rhs).xyzw.x, (lhs).xyzw.y / (rhs).xyzw.y, (lhs).xyzw.z / (rhs).xyzw.z, (lhs).xyzw.w / (rhs).xyzw.w) 263 264 #define VEC4ADDS(T, lhs, scalar) \ 265 VEC4(T, (lhs).xyzw.x + scalar, (lhs).xyzw.y + scalar, (lhs).xyzw.z + scalar, (lhs).xyzw.w + scalar) 266 #define VEC4SUBS(T, lhs, scalar) \ 267 VEC4(T, (lhs).xyzw.x - scalar, (lhs).xyzw.y - scalar, (lhs).xyzw.z - scalar, (lhs).xyzw.w - scalar) 268 #define VEC4MULS(T, lhs, scalar) \ 269 VEC4(T, (lhs).xyzw.x * scalar, (lhs).xyzw.y * scalar, (lhs).xyzw.z * scalar, (lhs).xyzw.w * scalar) 270 #define VEC4DIVS(T, lhs, scalar) \ 271 VEC4(T, (lhs).xyzw.x / scalar, (lhs).xyzw.y / scalar, (lhs).xyzw.z / scalar, (lhs).xyzw.w / scalar) 272 273 #define VEC4LEN2(lhs) \ 274 (((lhs).xyzw.x * (lhs).xyzw.x) + ((lhs).xyzw.y * (lhs).xyzw.y) + ((lhs).xyzw.z * (lhs).xyzw.z) + ((lhs).xyzw.w * (lhs).xyzw.w)) 275 276 #define VEC4LEN(lhs) sqrt(VEC4LEN2(lhs)) 277 278 #define VEC4LERP(a, b, t) \ 279 VEC4ADD(__typeof__ (a), \ 280 VEC4MULS(__typeof__ (a), (a), (1 - (t))), \ 281 VEC4MULS(__typeof__ (b), (b), (t))) 282 283 #define VEC4DOT(lhs, rhs) \ 284 (((lhs).xyzw.x * (rhs).xyzw.x) + ((lhs).xyzw.y * (rhs).xyzw.y) + ((lhs).xyzw.z * (rhs).xyzw.z)) 285 286 #define VEC4UNIT(lhs) \ 287 VEC4(__typeof__ (lhs), \ 288 (lhs).xyzw.x / VEC4LEN(lhs), \ 289 (lhs).xyzw.y / VEC4LEN(lhs), \ 290 (lhs).xyzw.z / VEC4LEN(lhs), \ 291 (lhs).xyzw.w / VEC4LEN(lhs)) 292 293 #define DEG2RAD(degrees) (((degrees) * M_PI) / 180) 294 295 #define MAX(a, b) (((a) > (b)) ? (a) : (b)) 296 #define MIN(a, b) (((a) < (b)) ? (a) : (b)) 297 298 #define CLAMP(max, min, v) MAX(MIN((max), (v)), (min)) 299 300 // raytracing utilities 301 // ========================================================================== 302 303 typedef vec3f_t point_t; 304 305 struct ray { 306 point_t origin; 307 vec3f_t direction; 308 }; 309 310 inline vec3f_t 311 ray_at(struct ray const *ray, float t) 312 { 313 return VEC3ADD(vec3f_t, ray->origin, VEC3MULS(vec3f_t, ray->direction, t)); 314 } 315 316 struct hit_record { 317 point_t point; 318 vec3f_t normal; 319 float t; 320 321 int front_face; 322 }; 323 324 inline void 325 hit_record_set_face_normal(struct hit_record *record, struct ray const *ray, 326 vec3f_t outward_normal) 327 { 328 record->front_face = VEC3DOT(ray->direction, outward_normal) < 0; 329 record->normal = record->front_face ? outward_normal : VEC3NEG(outward_normal); 330 } 331 332 struct interval { 333 float min, max; 334 }; 335 336 #define EMPTY_INTERVAL ((struct interval) { +INFINITY, -INFINITY, }) 337 #define UNIVERSE_INTERVAL ((struct interval) { -INFINITY, +INFINITY, }) 338 339 inline int 340 interval_contains(struct interval interval, float v) 341 { 342 return interval.min <= v && v <= interval.max; 343 } 344 345 inline int 346 interval_surrounds(struct interval interval, float v) 347 { 348 return interval.min < v && v < interval.max; 349 } 350 351 struct hittable { 352 int (*impl)(struct hittable *data, struct ray const *ray, 353 struct interval t, struct hit_record *record); 354 355 struct list_node list_node; 356 }; 357 358 struct sphere { 359 point_t centre; 360 float radius; 361 362 struct hittable hittable; 363 }; 364 365 inline int 366 sphere_hittable_impl(struct hittable *data, struct ray const *ray, 367 struct interval t, struct hit_record *record) 368 { 369 struct sphere *self = TO_PARENT_PTR(data, struct sphere, hittable); 370 371 vec3f_t oc = VEC3SUB(point_t, self->centre, ray->origin); 372 373 float a = VEC3LEN2(ray->direction); 374 float h = VEC3DOT(ray->direction, oc); 375 float c = VEC3LEN2(oc) - (self->radius * self->radius); 376 float discriminant = (h * h) - (a * c); 377 378 if (discriminant < 0) 379 return 0; 380 381 float sqrtd = sqrt(discriminant); 382 383 float root = (h - sqrtd) / a; 384 if (interval_surrounds(t, root)) 385 goto found_valid_root; 386 387 root = (h + sqrtd) / a; 388 if (interval_surrounds(t, root)) 389 goto found_valid_root; 390 391 return 0; 392 393 found_valid_root: 394 record->t = root; 395 record->point = ray_at(ray, record->t); 396 397 vec3f_t outward_normal = VEC3DIVS(vec3f_t, 398 VEC3SUB(vec3f_t, record->point, self->centre), 399 self->radius); 400 hit_record_set_face_normal(record, ray, outward_normal); 401 402 return 1; 403 } 404 405 typedef vec3f_t color_t; 406 407 // bitmap utilities 408 // =========================================================================== 409 410 typedef uint32_t pixel_t; 411 412 enum pixel_format { 413 PIXEL_FORMAT_ARGB32, 414 }; 415 416 inline pixel_t 417 pixel_from_argb32(uint8_t a, uint8_t r, uint8_t g, uint8_t b) 418 { 419 return (((uint32_t) a) << 24) | \ 420 (((uint32_t) r) << 16) | \ 421 (((uint32_t) g) << 8) | \ 422 (((uint32_t) b)); 423 } 424 425 inline pixel_t 426 pixel_from_color(color_t color, enum pixel_format format) 427 { 428 assert(format == PIXEL_FORMAT_ARGB32); 429 430 uint8_t a = 255; 431 uint8_t r = color.xyz.x * 255; 432 uint8_t g = color.xyz.y * 255; 433 uint8_t b = color.xyz.z * 255; 434 435 switch (format) { 436 case PIXEL_FORMAT_ARGB32: return pixel_from_argb32(a, r, g, b); 437 } 438 } 439 440 inline void 441 pixel_format_set_masks(enum pixel_format format, 442 uint32_t *r, uint32_t *g, uint32_t *b, uint32_t *a) 443 { 444 /* NOTE: bitmap field masks are big endian! */ 445 switch (format) { 446 case PIXEL_FORMAT_ARGB32: 447 *r = 0x0000ff00; 448 *g = 0x00ff0000; 449 *b = 0xff000000; 450 *a = 0x000000ff; 451 break; 452 } 453 } 454 455 /* see: https://en.wikipedia.org/wiki/BMP_file_format */ 456 inline void 457 bitmap_write(int fd, pixel_t *buf, size_t width, size_t height, enum pixel_format format) 458 { 459 uint32_t pixels = width * height; 460 uint32_t pixel_bytes = pixels * sizeof(pixel_t); 461 462 uint32_t dib_header_size = 108; 463 uint32_t bitmap_header_size = 14; 464 uint32_t header_size = bitmap_header_size + dib_header_size; 465 466 uint32_t file_size = header_size + pixel_bytes; 467 uint32_t reserved = 0; 468 469 int32_t xres = width, yres = -height; 470 uint16_t planes = 1, bits_per_pixel = sizeof(pixel_t) * 8; 471 uint32_t compression = 3; /* 3 = bitfields */ 472 uint32_t xdpi = 0, ydpi = 0; 473 uint32_t palette = 0, important = 0; 474 475 uint32_t r_mask, g_mask, b_mask, a_mask; 476 pixel_format_set_masks(format, &r_mask, &g_mask, &b_mask, &a_mask); 477 478 unsigned char colorspace[4] = "sRGB"; 479 unsigned char endpoints[36]; 480 memset(endpoints, 0, sizeof endpoints); 481 482 uint32_t r_gamma = 0, g_gamma = 0, b_gamma = 0; 483 484 /* bitmap header */ 485 write(fd, "BM", 2); 486 write(fd, &file_size, sizeof file_size); 487 write(fd, &reserved, sizeof reserved); 488 write(fd, &header_size, sizeof header_size); 489 490 /* dib header: BITMAPV4HEADER */ 491 write(fd, &dib_header_size, sizeof dib_header_size); 492 write(fd, &xres, sizeof xres); 493 write(fd, &yres, sizeof yres); 494 write(fd, &planes, sizeof planes); 495 write(fd, &bits_per_pixel, sizeof bits_per_pixel); 496 write(fd, &compression, sizeof compression); 497 write(fd, &pixel_bytes, sizeof pixel_bytes); 498 write(fd, &xdpi, sizeof xdpi); 499 write(fd, &ydpi, sizeof ydpi); 500 write(fd, &palette, sizeof palette); 501 write(fd, &important, sizeof important); 502 write(fd, &r_mask, sizeof r_mask); 503 write(fd, &g_mask, sizeof g_mask); 504 write(fd, &b_mask, sizeof b_mask); 505 write(fd, &a_mask, sizeof a_mask); 506 write(fd, colorspace, sizeof colorspace); 507 write(fd, endpoints, sizeof endpoints); 508 write(fd, &r_gamma, sizeof r_gamma); 509 write(fd, &g_gamma, sizeof g_gamma); 510 write(fd, &b_gamma, sizeof b_gamma); 511 512 /* pixel data */ 513 write(fd, buf, pixel_bytes); 514 } 515 516 // rt definitions 517 // =========================================================================== 518 519 struct world { 520 struct list_node objects; 521 }; 522 523 inline void 524 world_init(struct world *world) 525 { 526 world->objects = LIST_INIT(world->objects); 527 } 528 529 inline void 530 world_push(struct world *world, struct hittable *hittable) 531 { 532 list_push_tail(&world->objects, &hittable->list_node); 533 } 534 535 void 536 render(pixel_t *image, size_t image_width, size_t image_height, struct world *world); 537 538 #endif /* RT_H */