rt: started working on the tile-based rendering
[dosdemo] / src / scr / raytrace.c
1 #include <stdio.h>
2 #include <math.h>
3 #include "demo.h"
4 #include "screen.h"
5 #include "gfxutil.h"
6 #include "util.h"
7 #include "cgmath/cgmath.h"
8 #include "rt.h"
9
10 static int init(void);
11 static void destroy(void);
12 static void start(long trans_time);
13 static void draw(void);
14
15 static struct screen scr = {
16         "raytrace",
17         init,
18         destroy,
19         start,
20         0,
21         draw
22 };
23
24 enum {LASTX = 1, LASTY = 2};
25
26 struct tile {
27         int sz;
28         unsigned int flags;
29         struct { int x, y; } cpos[4];   /* corner coordinates */
30         uint16_t *cptr[4];      /* corner pixels */
31 };
32
33 #define TILESZ          8
34 #define NUM_TILES       ((320 / TILESZ) * (240 / TILESZ))
35
36 static cgm_vec3 raydir[240][320];
37 static struct tile tiles[NUM_TILES];
38 static struct rtscene scn;
39
40 struct screen *raytrace_screen(void)
41 {
42         return &scr;
43 }
44
45 static int init(void)
46 {
47         int i, j, k;
48         float z = 1.0f / tan(cgm_deg_to_rad(25.0f));
49         struct tile *tptr = tiles;
50
51         for(i=0; i<240; i++) {
52                 cgm_vec3 *vptr = raydir[i];
53                 float y = 1.0f - (float)i / 120.0f;
54                 for(j=0; j<320; j++) {
55                         vptr->x = ((float)j / 160.0f - 1.0f) * 1.333333f;
56                         vptr->y = y;
57                         vptr->z = z;
58                         vptr++;
59
60                         if(((j & (TILESZ-1)) | (i & (TILESZ-1))) == 0) {
61                                 tptr->sz = TILESZ;
62                                 tptr->flags = 0;
63                                 if(j + TILESZ >= 320) tptr->flags |= LASTX;
64                                 if(i + TILESZ >= 240) tptr->flags |= LASTY;
65
66                                 tptr->cpos[0].x = j;
67                                 tptr->cpos[0].y = i;
68                                 tptr->cpos[1].x = j + (tptr->flags & LASTX ? TILESZ - 1 : TILESZ);
69                                 tptr->cpos[1].y = i;
70                                 tptr->cpos[2].x = j;
71                                 tptr->cpos[2].y = i + (tptr->flags & LASTY ? TILESZ - 1 : TILESZ);
72                                 tptr->cpos[3].x = tptr->cpos[1].x;
73                                 tptr->cpos[3].y = tptr->cpos[2].y;
74
75                                 for(k=0; k<4; k++) {
76                                         tptr->cptr[k] = fb_pixels + tptr->cpos[k].y * 320 + tptr->cpos[k].x;
77                                 }
78                                 tptr++;
79                         }
80                 }
81         }
82
83         rt_init(&scn);
84
85         rt_color(1, 0, 0);
86         rt_specular(0.8f, 0.8f, 0.8f);
87         rt_shininess(30.0f);
88         rt_add_sphere(&scn, 0, 0, 0, 1);        /* x,y,z, rad */
89
90         rt_color(0.4, 0.4, 0.4);
91         rt_specular(0, 0, 0);
92         rt_shininess(1);
93         rt_add_plane(&scn, 0, 1, 0, -1);                /* nx,ny,nz, dist */
94
95         rt_color(1, 1, 1);
96         rt_add_light(&scn, -8, 15, -10);
97         return 0;
98 }
99
100 static void destroy(void)
101 {
102         rt_destroy(&scn);
103 }
104
105 static void start(long start_time)
106 {
107 }
108
109 static uint16_t INLINE rend_pixel(int x, int y)
110 {
111         int r, g, b;
112         cgm_ray ray;
113         cgm_vec3 col;
114
115         ray.dir = raydir[y][x];
116         cgm_vcons(&ray.origin, 0, 0, -5);
117
118         if(ray_trace(&ray, &scn, 0, &col)) {
119                 r = cround64(col.x * 255.0f);
120                 g = cround64(col.y * 255.0f);
121                 b = cround64(col.z * 255.0f);
122                 if(r > 255) r = 255;
123                 if(g > 255) g = 255;
124                 if(b > 255) b = 255;
125                 return PACK_RGB16(r, g, b);
126         }
127         return 0;
128 }
129
130 #define FBPTR(x, y)     (fb_pixels + ((y) << 8) + ((y) << 6) + (x))
131
132 static void draw(void)
133 {
134         int i, j, xbound, ybound;
135         uint16_t *fbptr;
136         struct tile *tptr;
137
138         tptr = tiles;
139         for(i=0; i<NUM_TILES; i++) {
140                 *tptr->cptr[0] = rend_pixel(tptr->cpos[0].x, tptr->cpos[0].y);
141                 if(tptr->flags & LASTX) {
142                         *tptr->cptr[1] = rend_pixel(tptr->cpos[1].x, tptr->cpos[1].y);
143                         if(tptr->flags & LASTY) {
144                                 *tptr->cptr[3] = rend_pixel(tptr->cpos[3].x, tptr->cpos[3].y);
145                         }
146                 }
147                 if(tptr->flags & LASTY) {
148                         *tptr->cptr[2] = rend_pixel(tptr->cpos[2].x, tptr->cpos[2].y);
149                 }
150                 tptr++;
151         }
152
153         swap_buffers(0);
154 }