18b7f17548674537cd709473ddede1c73870f0a6
[cyberay] / src / rt.c
1 #include <float.h>
2 #include "rt.h"
3 #include "game.h"
4
5 #define TILESZ  32
6
7 struct tile {
8         int x, y, width, height;
9         int sample;
10         cgm_vec3 *fbptr;
11 };
12
13 struct framebuffer fb;
14 struct thread_pool *tpool;
15 float view_xform[16];
16 float vfov = M_PI / 4;
17
18 static float aspect;
19 static struct tile *tiles;
20 static int num_tiles;
21
22 static void render_tile(struct tile *tile);
23 static void ray_trace(cgm_vec3 *color, cgm_ray *ray);
24 static void bgcolor(cgm_vec3 *color, cgm_ray *ray);
25 static void primary_ray(cgm_ray *ray, int x, int y, int sample);
26
27 int fbsize(int width, int height)
28 {
29         int i, j, x, y, xtiles, ytiles;
30         cgm_vec3 *fbptr;
31         struct tile *tileptr;
32
33         if(!(fbptr = malloc(width * height * sizeof *fb.pixels))) {
34                 return -1;
35         }
36         xtiles = width / TILESZ;
37         ytiles = height / TILESZ;
38         if(!(tileptr = malloc(xtiles * ytiles * sizeof *tiles))) {
39                 free(fbptr);
40                 return -1;
41         }
42
43         free(fb.pixels);
44         fb.pixels = fbptr;
45         fb.width = width;
46         fb.height = height;
47
48         free(tiles);
49         tiles = tileptr;
50         num_tiles = xtiles * ytiles;
51
52         aspect = (float)fb.width / (float)fb.height;
53
54         y = 0;
55         for(i=0; i<ytiles; i++) {
56                 x = 0;
57                 for(j=0; j<xtiles; j++) {
58                         tileptr->x = x;
59                         tileptr->y = y;
60                         tileptr->width = width - x < TILESZ ? width - x : TILESZ;
61                         tileptr->height = height - y < TILESZ ? height - y : TILESZ;
62                         tileptr->fbptr = fbptr + x;
63                         tileptr++;
64
65                         x += TILESZ;
66                 }
67                 fbptr += width * TILESZ;
68                 y += TILESZ;
69         }
70
71         return 0;
72 }
73
74 void render(void)
75 {
76         int i;
77
78         for(i=0; i<num_tiles; i++) {
79                 tpool_enqueue(tpool, tiles + i, (tpool_callback)render_tile, 0);
80         }
81         tpool_wait(tpool);
82 }
83
84 static void render_tile(struct tile *tile)
85 {
86         int i, j;
87         cgm_ray ray;
88         cgm_vec3 *fbptr = tile->fbptr;
89
90         for(i=0; i<tile->height; i++) {
91                 for(j=0; j<tile->width; j++) {
92                         primary_ray(&ray, tile->x + j, tile->y + i, tile->sample);
93                         ray_trace(fbptr + j, &ray);
94                 }
95                 fbptr += fb.width;
96         }
97 }
98
99 static void ray_trace(cgm_vec3 *color, cgm_ray *ray)
100 {
101         struct rayhit hit;
102
103         if(ray_level(ray, &lvl, FLT_MAX, &hit)) {
104                 color->x = hit.v.norm.x * 0.5 + 0.5;
105                 color->y = hit.v.norm.y * 0.5 + 0.5;
106                 color->z = hit.v.norm.z * 0.5 + 0.5;
107         } else {
108                 bgcolor(color, ray);
109         }
110 }
111
112 static void bgcolor(cgm_vec3 *color, cgm_ray *ray)
113 {
114         color->x = color->y = color->z = 1.0f;
115 }
116
117 static void primary_ray(cgm_ray *ray, int x, int y, int sample)
118 {
119         ray->origin.x = ray->origin.y = ray->origin.z = 0.0f;
120         ray->dir.x = (2.0f * (float)x / (float)fb.width - 1.0f) * aspect;
121         ray->dir.y = 1.0f - 2.0f * (float)y / (float)fb.height;
122         ray->dir.z = -1.0f / tan(vfov / 2.0f);
123         cgm_vnormalize(&ray->dir);
124
125         /* TODO jitter */
126
127         cgm_rmul_mr(ray, view_xform);
128 }