163 |
167 |
164 return acc; |
168 return acc; |
165 } |
169 } |
166 } |
170 } |
167 |
171 |
|
172 static void *renderrow(void *data) |
|
173 { |
|
174 RenderrowData *d = (RenderrowData*) data; |
|
175 for (int x = 0; x < d->w; x++) { |
|
176 // generate a ray from eye passing through this pixel |
|
177 #if 1 |
|
178 // no oversampling |
|
179 Vector3 dir = Vector3(d->vx, d->vy, 0) - d->eye; |
|
180 dir.normalize(); |
|
181 Ray ray(d->eye, dir); |
|
182 Colour c = d->rt->raytrace(ray, 0, NULL); |
|
183 #else |
|
184 // 5x oversampling |
|
185 Vector3 dir = Vector3(); |
|
186 Colour c = Colour(); |
|
187 |
|
188 for (int i = 0; i < 5; i++) |
|
189 { |
|
190 float osax[] = {0.0, -0.4, +0.4, +0.4, -0.4}; |
|
191 float osay[] = {0.0, -0.4, -0.4, +0.4, +0.4}; |
|
192 dir = Vector3(d->vx + osax[i] * d->dx, |
|
193 d->vy + osay[i]*d->dy , 0) - d->eye; |
|
194 dir.normalize(); |
|
195 Ray ray(d->eye, dir); |
|
196 c += d->rt->raytrace(ray, 0, NULL); |
|
197 } |
|
198 c = c * (1./5); |
|
199 #endif |
|
200 *(d->iter++) = c.r; |
|
201 *d->iter++ = c.g; |
|
202 *d->iter++ = c.b; |
|
203 d->vx += d->dx; |
|
204 } |
|
205 #ifdef PTHREADS |
|
206 pthread_exit((void *)d); |
|
207 #endif |
|
208 } |
|
209 |
168 float *Raytracer::render(int w, int h) |
210 float *Raytracer::render(int w, int h) |
169 { |
211 { |
170 int x, y; |
212 float *data; |
171 float *data, *iter; |
|
172 |
213 |
173 data = (float *) malloc(w*h*3*sizeof(float)); |
214 data = (float *) malloc(w*h*3*sizeof(float)); |
174 if (!data) |
215 if (!data) |
175 return NULL; |
216 return NULL; |
176 |
217 |
177 float startx = -1.0 * 4, starty = (float)h/w * 4; |
218 float startx = -1.0 * 4, starty = (float)h/w * 4; |
178 float dx = -2*startx/w, dy = -2*starty/h; |
219 float dx = -2*startx/w, dy = -2*starty/h; |
179 float vx, vy; |
220 float vy; |
|
221 RenderrowData *d; |
180 |
222 |
181 //srand(time(NULL)); |
223 //srand(time(NULL)); |
182 |
224 |
183 // eye - viewing point |
225 // eye - viewing point |
184 Vector3 eye(0, 0, -5); |
226 Vector3 eye(0, 0, -5); |
185 |
227 |
186 // for each pixel... |
228 // for each pixel... |
187 iter = data; |
229 vy = starty; |
188 for (vy = starty, y = 0; y < h; y++) { |
230 |
189 vx = startx; |
231 #ifdef PTHREADS |
190 for (x = 0; x < w; x++) { |
232 int num_threads = 20; |
191 // generate a ray from eye passing through this pixel |
233 printf("* pthreads enabled, using %d threads\n", num_threads); |
192 #if 1 |
234 pthread_t threads[num_threads]; |
193 // no oversampling |
235 for (int t = 0; t < num_threads; t++) |
194 Vector3 dir = Vector3(vx, vy, 0) - eye; |
236 threads[t] = NULL; |
195 dir.normalize(); |
237 int t = 0; |
196 Ray ray(eye, dir); |
238 #endif |
197 Colour c = raytrace(ray, 0, NULL); |
239 |
|
240 printf("* rendering row 0 ( 0% done)"); |
|
241 for (int y = 0; y < h; y++) { |
|
242 d = (RenderrowData*) malloc(sizeof(RenderrowData)); |
|
243 d->rt = this; |
|
244 d->w = w; |
|
245 d->vx = startx; |
|
246 d->vy = vy; |
|
247 d->dx = dx; |
|
248 d->dy = dy; |
|
249 d->eye = eye; |
|
250 d->iter = data + y*3*w; |
|
251 #ifdef PTHREADS |
|
252 /* create new thread and increase 't' */ |
|
253 int rc = pthread_create(&threads[t++], NULL, renderrow, (void *)d); |
|
254 if (rc) { |
|
255 printf("\nERROR: return code from pthread_create() is %d\n", rc); |
|
256 exit(1); |
|
257 } |
|
258 /* when 't' owerflows, reset it */ |
|
259 if (t >= num_threads) |
|
260 t = 0; |
|
261 /* wait for next thread in fifo queue, so the descriptor can be reused; |
|
262 this also limits number of running threads */ |
|
263 if (threads[t] != NULL) |
|
264 if (pthread_join(threads[t], (void**)&d) == 0) |
|
265 free(d); |
198 #else |
266 #else |
199 // 5x oversampling |
267 renderrow((void *)d); |
200 Vector3 dir = Vector3(); |
268 free(d); |
201 Colour c = Colour(); |
269 #endif |
202 |
|
203 for (int i = 0; i < 5; i++) |
|
204 { |
|
205 float osax[] = {0.0, -0.4, +0.4, +0.4, -0.4}; |
|
206 float osay[] = {0.0, -0.4, -0.4, +0.4, +0.4}; |
|
207 dir = Vector3(vx + osax[i]*dx, |
|
208 vy + osay[i]*dy , 0) - eye; |
|
209 dir.normalize(); |
|
210 Ray ray(eye, dir); |
|
211 c += raytrace(ray, 0, NULL); |
|
212 } |
|
213 c = c * (1./5); |
|
214 #endif |
|
215 *iter++ = c.r; |
|
216 *iter++ = c.g; |
|
217 *iter++ = c.b; |
|
218 vx += dx; |
|
219 } |
|
220 vy += dy; |
270 vy += dy; |
221 printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b%2d%% done (row %4d)", y*100/(h-1), y); |
271 printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b%4d (%2d%% done)", y, y*100/(h-1)); |
222 } |
272 } |
223 printf("\n"); |
273 printf("\n"); |
|
274 |
|
275 #ifdef PTHREADS |
|
276 printf("* waiting for threads to finish\n"); |
|
277 for (t = 0; t < num_threads; t++) |
|
278 if (pthread_join(threads[t], (void**)&d) == 0) |
|
279 free(d); |
|
280 #endif |
|
281 |
224 return data; |
282 return data; |
225 } |
283 } |
226 |
284 |
227 void Raytracer::addshape(Shape *shape) |
285 void Raytracer::addshape(Shape *shape) |
228 { |
286 { |