c88277f85a598f8ca968e98abea2c5ed49571fda
[retroray] / src / rend.c
1 /*
2 RetroRay - integrated standalone vintage modeller/renderer
3 Copyright (C) 2023  John Tsiombikas <nuclear@mutantstargoat.com>
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 */
18 #include "rend.h"
19 #include "app.h"
20 #include "geom.h"
21 #include "util.h"
22 #include "gfxutil.h"
23 #include "scene.h"
24
25 struct img_pixmap renderbuf;
26
27 int max_ray_depth;
28
29 static int rx, ry, rwidth, rheight;
30 static int roffs;
31 static int xstep, ystep;
32
33 int rend_init(void)
34 {
35         img_init(&renderbuf);
36
37         rx = ry = rwidth = rheight = roffs = 0;
38
39         max_ray_depth = 6;
40         return 0;
41 }
42
43 void rend_destroy(void)
44 {
45         img_destroy(&renderbuf);
46 }
47
48 void rend_size(int xsz, int ysz)
49 {
50         if(xsz != renderbuf.width || ysz != renderbuf.height) {
51                 img_set_pixels(&renderbuf, xsz, ysz, IMG_FMT_RGBA32, 0);
52         }
53 }
54
55 void rend_begin(int x, int y, int w, int h)
56 {
57         int i;
58         uint32_t *ptr;
59
60         if(w == 0 || h == 0) {
61                 rx = ry = 0;
62                 rwidth = renderbuf.width;
63                 rheight = renderbuf.height;
64         } else {
65                 rx = x;
66                 ry = y;
67                 rwidth = w;
68                 rheight = h;
69         }
70         roffs = ry * renderbuf.width + rx;
71
72         xstep = rwidth;
73         ystep = rheight;
74
75         ptr = (uint32_t*)renderbuf.pixels + roffs;
76         for(i=0; i<rheight; i++) {
77                 memset(ptr, 0, rwidth * sizeof *ptr);
78                 ptr += renderbuf.width;
79         }
80 }
81
82 static void fillrect(uint32_t *fb, int x, int y, int w, int h, uint32_t c)
83 {
84         int i, j;
85
86         fb += y * renderbuf.width + x;
87         for(i=0; i<h; i++) {
88                 for(j=0; j<w; j++) {
89                         fb[j] = c;
90                 }
91                 fb += renderbuf.width;
92         }
93 }
94
95 int render(uint32_t *fb)
96 {
97         int i, j, w, h, offs, r, g, b;
98         uint32_t *dest, pcol;
99         cgm_vec3 color;
100         cgm_ray ray;
101
102         dest = (uint32_t*)renderbuf.pixels + roffs;
103         if(fb) fb += roffs;
104
105         if(xstep < 1) xstep = 1;
106         if(ystep < 1) ystep = 1;
107
108         for(i=0; i<rheight; i+=ystep) {
109                 h = ystep;
110                 if(i + h > rheight) h = rheight - i;
111
112                 for(j=0; j<rwidth; j+=xstep) {
113                         primray(&ray, rx + j, ry + i);
114                         ray_trace(&ray, max_ray_depth, &color);
115
116                         r = cround64(color.x * 255.0f);
117                         g = cround64(color.y * 255.0f);
118                         b = cround64(color.z * 255.0f);
119
120                         if(r > 255) r = 255;
121                         if(g > 255) g = 255;
122                         if(b > 255) b = 255;
123
124                         pcol = PACK_RGB32(r, g, b);
125
126                         offs = i * renderbuf.width + j;
127                         dest[offs] = pcol;
128
129                         if(fb) {
130                                 w = xstep;
131                                 if(j + w > rwidth) w = rwidth - j;
132
133                                 fillrect(fb, j, i, w, h, pcol);
134                         }
135                 }
136         }
137
138         xstep >>= 1;
139         ystep >>= 1;
140
141         if((xstep | ystep) >= 1) {
142                 return 1;
143         }
144         return 0;
145 }
146
147 int ray_trace(const cgm_ray *ray, int maxiter, cgm_vec3 *res)
148 {
149         struct rayhit hit;
150
151         if(!scn_intersect(scn, ray, &hit)) {
152                 *res = bgcolor(ray);
153                 return 0;
154         }
155
156         *res = shade(ray, &hit, maxiter);
157         return 1;
158 }
159
160 cgm_vec3 bgcolor(const cgm_ray *ray)
161 {
162         return cgm_vvec(0, 0, 0);
163 }
164
165 cgm_vec3 shade(const cgm_ray *ray, const struct rayhit *hit, int maxiter)
166 {
167         return cgm_vvec(1, 0, 0);
168 }