233 |
233 |
234 return col; |
234 return col; |
235 } |
235 } |
236 } |
236 } |
237 |
237 |
238 #if 0 |
|
239 static void *renderrow(void *data) |
|
240 { |
|
241 RenderrowData *d = (RenderrowData*) data; |
|
242 const int subsample = d->rt->getSubsample(); |
|
243 const Float subsample2 = 1.0/(subsample*subsample); |
|
244 const int oversample = d->rt->getOversample(); |
|
245 const int ww = d->w*3; |
|
246 Vector3 dir = d->dfix; |
|
247 for (int x = 0; x < d->w; x += subsample) { |
|
248 // generate a ray from eye passing through this pixel |
|
249 if (subsample > 1) |
|
250 { |
|
251 Colour ic; |
|
252 // top-left |
|
253 dir.normalize(); |
|
254 Ray ray(d->eye, dir); |
|
255 Colour c1 = d->rt->raytrace(ray, 0, NULL); |
|
256 // top-right |
|
257 Vector3 tmpdir = dir + (subsample-1)*d->dx; |
|
258 tmpdir.normalize(); |
|
259 ray.dir = tmpdir; |
|
260 Colour c2 = d->rt->raytrace(ray, 0, NULL); |
|
261 // bottom right |
|
262 tmpdir += (subsample-1)*d->dy; |
|
263 tmpdir.normalize(); |
|
264 ray.dir = tmpdir; |
|
265 Colour c4 = d->rt->raytrace(ray, 0, NULL); |
|
266 // bottom left |
|
267 tmpdir = dir + (subsample-1)*d->dy; |
|
268 tmpdir.normalize(); |
|
269 ray.dir = tmpdir; |
|
270 Colour c3 = d->rt->raytrace(ray, 0, NULL); |
|
271 // are the colors similar? |
|
272 Float m = (c1-c2).mag2(); |
|
273 m = max(m, (c2-c3).mag2()); |
|
274 m = max(m, (c3-c4).mag2()); |
|
275 m = max(m, (c4-c1).mag2()); |
|
276 if (m < 0.001) |
|
277 { |
|
278 // interpolate |
|
279 Float *i = d->iter; |
|
280 for (int x = 0; x < subsample; x++) |
|
281 { |
|
282 for (int y = 0; y < subsample; y++) |
|
283 { |
|
284 ic = c1*(subsample-x)*(subsample-y)*subsample2 |
|
285 + c2*(x)*(subsample-y)*subsample2 |
|
286 + c3*(subsample-x)*(y)*subsample2 |
|
287 + c4*(x)*(y)*subsample2; |
|
288 *(i + ww*y) = ic.r; |
|
289 *(i + ww*y + 1) = ic.g; |
|
290 *(i + ww*y + 2) = ic.b; |
|
291 } |
|
292 i += 3; |
|
293 } |
|
294 d->iter = i; |
|
295 } |
|
296 else |
|
297 { |
|
298 // render all pixels |
|
299 Vector3 tmpdir = dir; |
|
300 |
|
301 if (oversample) |
|
302 { |
|
303 for (int x = 0; x < subsample; x++) |
|
304 { |
|
305 for (int y = 0; y < subsample; y++) |
|
306 { |
|
307 Vector3 tmp2dir = tmpdir + y*d->dy; |
|
308 samplepixel(ic, tmp2dir, d, oversample); |
|
309 *(d->iter + ww*y) = ic.r; |
|
310 *(d->iter + ww*y + 1) = ic.g; |
|
311 *(d->iter + ww*y + 2) = ic.b; |
|
312 } |
|
313 d->iter += 3; |
|
314 tmpdir += d->dx; |
|
315 } |
|
316 } |
|
317 else |
|
318 { |
|
319 /* this is so complex because it tries to reuse |
|
320 already computed corner pixels |
|
321 though, above code will also work for non-oversampling... */ |
|
322 // first column |
|
323 *(d->iter) = c1.r; |
|
324 *(d->iter + 1) = c1.g; |
|
325 *(d->iter + 2) = c1.b; |
|
326 for (int y = 1; y < subsample-1; y++) |
|
327 { |
|
328 Vector3 tmp2dir = tmpdir + y*d->dy; |
|
329 tmp2dir.normalize(); |
|
330 ray.dir = tmp2dir; |
|
331 ic = d->rt->raytrace(ray, 0, NULL); |
|
332 *(d->iter + ww*y) = ic.r; |
|
333 *(d->iter + ww*y + 1) = ic.g; |
|
334 *(d->iter + ww*y + 2) = ic.b; |
|
335 } |
|
336 *(d->iter + ww*(subsample-1)) = c3.r; |
|
337 *(d->iter + ww*(subsample-1) + 1) = c3.g; |
|
338 *(d->iter + ww*(subsample-1) + 2) = c3.b; |
|
339 d->iter += 3; |
|
340 tmpdir += d->dx; |
|
341 // middle |
|
342 for (int x = 1; x < subsample-1; x++) |
|
343 { |
|
344 for (int y = 0; y < subsample; y++) |
|
345 { |
|
346 Vector3 tmp2dir = tmpdir + y*d->dy; |
|
347 tmp2dir.normalize(); |
|
348 ray.dir = tmp2dir; |
|
349 ic = d->rt->raytrace(ray, 0, NULL); |
|
350 *(d->iter + ww*y) = ic.r; |
|
351 *(d->iter + ww*y + 1) = ic.g; |
|
352 *(d->iter + ww*y + 2) = ic.b; |
|
353 } |
|
354 d->iter += 3; |
|
355 tmpdir += d->dx; |
|
356 } |
|
357 // last column |
|
358 *(d->iter) = c2.r; |
|
359 *(d->iter + 1) = c2.g; |
|
360 *(d->iter + 2) = c2.b; |
|
361 for (int y = 1; y < subsample-1; y++) |
|
362 { |
|
363 Vector3 tmp2dir = tmpdir + y*d->dy; |
|
364 tmp2dir.normalize(); |
|
365 ray.dir = tmp2dir; |
|
366 ic = d->rt->raytrace(ray, 0, NULL); |
|
367 *(d->iter + ww*y) = ic.r; |
|
368 *(d->iter + ww*y + 1) = ic.g; |
|
369 *(d->iter + ww*y + 2) = ic.b; |
|
370 } |
|
371 *(d->iter + ww*(subsample-1)) = c4.r; |
|
372 *(d->iter + ww*(subsample-1) + 1) = c4.g; |
|
373 *(d->iter + ww*(subsample-1) + 2) = c4.b; |
|
374 d->iter += 3; |
|
375 } |
|
376 } |
|
377 } |
|
378 else // subsample <= 1 |
|
379 { |
|
380 Colour c; |
|
381 samplepixel(c, dir, d, oversample); |
|
382 // write color to buffer |
|
383 *d->iter++ = c.r; |
|
384 *d->iter++ = c.g; |
|
385 *d->iter++ = c.b; |
|
386 } |
|
387 dir += d->dx*subsample; |
|
388 } |
|
389 #ifdef PTHREADS |
|
390 pthread_exit((void *)d); |
|
391 #endif |
|
392 return (void *)d; |
|
393 } |
|
394 #endif |
|
395 |
|
396 void *Raytracer::raytrace_worker(void *d) |
238 void *Raytracer::raytrace_worker(void *d) |
397 { |
239 { |
398 static const int my_queue_size = 256; |
240 static const int my_queue_size = 256; |
399 Raytracer *rt = (Raytracer*)d; |
241 Raytracer *rt = (Raytracer*)d; |
400 Sample my_queue[my_queue_size]; |
242 Sample my_queue[my_queue_size]; |
460 return; |
302 return; |
461 |
303 |
462 static const int my_count_max = 256; |
304 static const int my_count_max = 256; |
463 sample_queue_size = my_count_max*2*num_threads; |
305 sample_queue_size = my_count_max*2*num_threads; |
464 sample_queue = new Sample [sample_queue_size]; |
306 sample_queue = new Sample [sample_queue_size]; |
465 sample_queue_pos = 0; |
|
466 sample_queue_count = 0; |
307 sample_queue_count = 0; |
467 end_of_samples = false; |
308 int my_count, my_pos; |
468 int my_count, my_pos = 0; |
|
469 int sampnum = 0, sampdone; |
309 int sampnum = 0, sampdone; |
|
310 int phase = 1; |
470 bool more_samples; |
311 bool more_samples; |
471 |
312 |
472 sampler->init(); |
313 sampler->init(); |
473 |
314 |
474 // create workers |
315 // create workers |
475 dbgmsg(1, "* running %d threads\n", num_threads); |
316 dbgmsg(1, "* using %d threads\n", num_threads); |
476 pthread_t threads[num_threads]; |
317 pthread_t threads[num_threads]; |
477 for (int t = 0; t < num_threads; t++) |
|
478 { |
|
479 int rc = pthread_create(&threads[t], NULL, raytrace_worker, (void*)this); |
|
480 if (rc) { |
|
481 dbgmsg(0, "\nE pthread_create unsuccessful, return code was %d\n", rc); |
|
482 exit(1); |
|
483 } |
|
484 } |
|
485 |
318 |
486 dbgmsg(1, "* raytracing...\n"); |
319 dbgmsg(1, "* raytracing...\n"); |
487 dbgmsg(2, "- 0%% done"); |
320 |
488 |
|
489 pthread_mutex_lock(&sampler_mutex); |
|
490 while ( (sampnum = sampler->initSampleSet()) > 0 ) |
321 while ( (sampnum = sampler->initSampleSet()) > 0 ) |
491 { |
322 { |
|
323 my_pos = 0; |
|
324 sample_queue_pos = 0; |
492 sampdone = 0; |
325 sampdone = 0; |
|
326 end_of_samples = false; |
|
327 |
|
328 for (int t = 0; t < num_threads; t++) |
|
329 { |
|
330 int rc = pthread_create(&threads[t], NULL, raytrace_worker, (void*)this); |
|
331 if (rc) { |
|
332 dbgmsg(0, "\nE pthread_create unsuccessful, return code was %d\n", rc); |
|
333 exit(1); |
|
334 } |
|
335 } |
|
336 |
|
337 dbgmsg(2, "phase %d: 0%% done", phase); |
|
338 |
|
339 pthread_mutex_lock(&sampler_mutex); |
|
340 |
493 for (;;) |
341 for (;;) |
494 { |
342 { |
495 my_count = 0; |
343 my_count = 0; |
496 while ( more_samples = sampler->nextSample(&sample_queue[my_pos++]) ) |
344 while ( more_samples = sampler->nextSample(&sample_queue[my_pos++]) ) |
497 { |
345 { |
517 |
365 |
518 sampdone += my_count; |
366 sampdone += my_count; |
519 dbgmsg(2, "\b\b\b\b\b\b\b\b%2d%% done", (sampdone - sample_queue_count)*100/sampnum); |
367 dbgmsg(2, "\b\b\b\b\b\b\b\b%2d%% done", (sampdone - sample_queue_count)*100/sampnum); |
520 |
368 |
521 pthread_mutex_lock(&sampler_mutex); |
369 pthread_mutex_lock(&sampler_mutex); |
|
370 |
|
371 if (!more_samples) |
|
372 break; |
522 } |
373 } |
523 dbgmsg(2, "\b\b\b\b\b\b\b\b100%% done\n"); |
374 dbgmsg(2, "\b\b\b\b\b\b\b\b100%% done\n"); |
524 } |
375 |
525 pthread_mutex_unlock(&sampler_mutex); |
376 pthread_mutex_unlock(&sampler_mutex); |
526 |
377 |
527 // wait for workers |
378 // wait for workers |
528 dbgmsg(2, "- waiting for threads to finish\n"); |
379 dbgmsg(2, "- waiting for threads to finish\n"); |
529 |
380 |
530 pthread_mutex_lock(&sample_queue_mutex); |
381 pthread_mutex_lock(&sample_queue_mutex); |
531 end_of_samples = true; |
382 end_of_samples = true; |
532 while (sample_queue_count) |
383 while (sample_queue_count) |
533 { |
384 { |
|
385 pthread_cond_broadcast(&sample_queue_cond); |
|
386 pthread_mutex_unlock(&sample_queue_mutex); |
|
387 pthread_mutex_lock(&sample_queue_mutex); |
|
388 } |
534 pthread_cond_broadcast(&sample_queue_cond); |
389 pthread_cond_broadcast(&sample_queue_cond); |
535 pthread_mutex_unlock(&sample_queue_mutex); |
390 pthread_mutex_unlock(&sample_queue_mutex); |
536 pthread_mutex_lock(&sample_queue_mutex); |
391 |
|
392 for (int t = 0; t < num_threads; t++) |
|
393 pthread_join(threads[t], NULL); |
|
394 |
|
395 phase ++; |
537 } |
396 } |
538 pthread_cond_broadcast(&sample_queue_cond); |
|
539 pthread_mutex_unlock(&sample_queue_mutex); |
|
540 |
|
541 for (int t = 0; t < num_threads; t++) |
|
542 pthread_join(threads[t], NULL); |
|
543 |
397 |
544 delete[] sample_queue; |
398 delete[] sample_queue; |
545 } |
399 } |
546 |
400 |
547 void Raytracer::ambientOcclusion(int samples, Float distance, Float angle) |
401 void Raytracer::ambientOcclusion(int samples, Float distance, Float angle) |