27 #include <pthread.h> |
27 #include <pthread.h> |
28 #include <stdio.h> |
28 #include <stdio.h> |
29 #include <malloc.h> |
29 #include <malloc.h> |
30 #include "raytracer.h" |
30 #include "raytracer.h" |
31 |
31 |
32 int pyrit_verbosity = 4; |
32 int pyrit_verbosity = 2; |
33 |
33 |
34 // Hammersley spherical point distribution |
34 // Hammersley spherical point distribution |
35 // http://www.cse.cuhk.edu.hk/~ttwong/papers/udpoint/udpoints.html |
35 // http://www.cse.cuhk.edu.hk/~ttwong/papers/udpoint/udpoints.html |
36 Vector3 Raytracer::SphereDistribute(int i, int n, Float extent, Vector3 &normal) |
36 Vector3 Raytracer::SphereDistribute(int i, int n, Float extent, Vector3 &normal) |
37 { |
37 { |
413 pthread_exit(NULL); |
414 pthread_exit(NULL); |
414 } |
415 } |
415 pthread_cond_wait(&rt->sample_queue_cond, &rt->sample_queue_mutex); |
416 pthread_cond_wait(&rt->sample_queue_cond, &rt->sample_queue_mutex); |
416 } |
417 } |
417 |
418 |
418 sample = rt->sample_queue[rt->sample_queue_pos++]; |
419 if (rt->sample_queue_count >= 80) |
419 rt->sample_queue_count--; |
420 my_count = 80; |
420 if (rt->sample_queue_pos > rt->sample_queue_max) |
421 else |
421 rt->sample_queue_pos = 0; |
422 my_count = rt->sample_queue_count; |
|
423 rt->sample_queue_count -= my_count; |
|
424 |
|
425 for (int i = 0; i < my_count; i++) |
|
426 { |
|
427 my_queue[i] = rt->sample_queue[rt->sample_queue_pos++]; |
|
428 if (rt->sample_queue_pos > rt->sample_queue_max) |
|
429 rt->sample_queue_pos = 0; |
|
430 } |
422 |
431 |
423 pthread_mutex_unlock(&rt->sample_queue_mutex); |
432 pthread_mutex_unlock(&rt->sample_queue_mutex); |
424 |
433 |
425 // do the work |
434 // do the work |
|
435 for (int i = 0; i < my_count; i++) |
|
436 { |
|
437 ray = rt->camera->makeRay(my_queue[i]); |
|
438 my_colours[i] = rt->raytrace(ray, 0, NULL); |
|
439 } |
|
440 |
|
441 // save the results |
426 pthread_mutex_lock(&rt->sampler_mutex); |
442 pthread_mutex_lock(&rt->sampler_mutex); |
427 ray = rt->camera->makeRay(sample); |
443 for (int i = 0; i < my_count; i++) |
|
444 rt->sampler->saveSample(my_queue[i], my_colours[i]); |
428 pthread_mutex_unlock(&rt->sampler_mutex); |
445 pthread_mutex_unlock(&rt->sampler_mutex); |
429 |
|
430 col = rt->raytrace(ray, 0, NULL); |
|
431 |
|
432 // save the result |
|
433 pthread_mutex_lock(&rt->sampler_mutex); |
|
434 rt->sampler->saveSample(sample, col); |
|
435 pthread_mutex_unlock(&rt->sampler_mutex); |
|
436 |
|
437 delete sample; |
|
438 } |
446 } |
439 } |
447 } |
440 |
448 |
441 void Raytracer::render() |
449 void Raytracer::render() |
442 { |
450 { |
443 if (!sampler || !camera || !top) |
451 if (!sampler || !camera || !top) |
444 return; |
452 return; |
445 |
453 |
446 sample_queue_end = false; |
454 sample_queue_end = false; |
447 sample_queue_max = 2000; |
455 sample_queue_max = 2000; |
448 sample_queue = new Sample* [sample_queue_max+1]; |
456 sample_queue = new Sample [sample_queue_max+1]; |
449 sample_queue_pos = 0; |
457 sample_queue_pos = 0; |
450 sample_queue_count = 0; |
458 sample_queue_count = 0; |
451 |
459 |
452 // create workers |
460 // create workers |
453 dbgmsg(1, "* running %d threads\n", num_threads); |
461 dbgmsg(1, "* running %d threads\n", num_threads); |
463 |
471 |
464 dbgmsg(1, "* raytracing...\n"); |
472 dbgmsg(1, "* raytracing...\n"); |
465 dbgmsg(2, "- 0%% done"); |
473 dbgmsg(2, "- 0%% done"); |
466 |
474 |
467 sampler->init(); |
475 sampler->init(); |
468 Sample *sample; |
|
469 int sampnum = 0, sampdone; |
476 int sampnum = 0, sampdone; |
470 int my_pos = 0, my_count; |
477 int my_pos = 0, my_count; |
|
478 bool more_samples; |
471 |
479 |
472 pthread_mutex_lock(&sampler_mutex); |
480 pthread_mutex_lock(&sampler_mutex); |
473 while ( (sampnum = sampler->initSampleSet()) > 0 ) |
481 while ( (sampnum = sampler->initSampleSet()) > 0 ) |
474 { |
482 { |
475 sampdone = 0; |
483 sampdone = 0; |
476 for (;;) |
484 for (;;) |
477 { |
485 { |
478 my_count = 0; |
486 my_count = 0; |
479 while ( (sample = sampler->nextSample()) != NULL ) |
487 while ( more_samples = sampler->nextSample(&sample_queue[my_pos++]) ) |
480 { |
488 { |
481 sample_queue[my_pos++] = sample; |
|
482 my_count++; |
489 my_count++; |
483 if (my_count >= 1000) |
490 if (my_count >= 1000) |
484 break; |
491 break; |
485 if (my_pos > sample_queue_max) |
492 if (my_pos > sample_queue_max) |
486 my_pos = 0; |
493 my_pos = 0; |
487 } |
494 } |
488 if (sample == NULL) |
495 if (!more_samples) |
489 break; |
496 break; |
490 |
497 |
491 pthread_mutex_unlock(&sampler_mutex); |
498 pthread_mutex_unlock(&sampler_mutex); |
492 pthread_mutex_lock(&sample_queue_mutex); |
499 pthread_mutex_lock(&sample_queue_mutex); |
493 sample_queue_count += my_count; |
500 sample_queue_count += my_count; |
526 |
533 |
527 for (int t = 0; t < num_threads; t++) |
534 for (int t = 0; t < num_threads; t++) |
528 pthread_join(threads[t], NULL); |
535 pthread_join(threads[t], NULL); |
529 |
536 |
530 delete[] sample_queue; |
537 delete[] sample_queue; |
531 |
|
532 #if 0 |
|
533 RenderrowData *d; |
|
534 |
|
535 Float S = 0.5/w; |
|
536 Vector3 dfix = camera->u*(-w/2.0*S/camera->f) |
|
537 + camera->v*(h/2.0*S/camera->f) + camera->p; |
|
538 Vector3 dx = camera->u * (S/camera->f); |
|
539 Vector3 dy = camera->v * (-S/camera->f); |
|
540 |
|
541 #ifdef PTHREADS |
|
542 dbgmsg(1, "* pthreads enabled, using %d threads\n", num_threads); |
|
543 pthread_t threads[num_threads]; |
|
544 for (int t = 0; t < num_threads; t++) |
|
545 threads[t] = pthread_self(); |
|
546 int t = 0; |
|
547 #endif |
|
548 |
|
549 /* for each pixel... */ |
|
550 dbgmsg(1, "* raytracing...\n"); |
|
551 dbgmsg(2, "- row 0 ( 0%% done)"); |
|
552 for (int y = 0; y < h; y += subsample) |
|
553 { |
|
554 d = (RenderrowData*) malloc(sizeof(RenderrowData)); |
|
555 d->rt = this; |
|
556 d->w = w; |
|
557 d->eye = camera->eye; |
|
558 d->dfix = dfix; |
|
559 d->dx = dx; |
|
560 d->dy = dy; |
|
561 d->iter = buffer + y*3*w; |
|
562 #ifdef PTHREADS |
|
563 /* create new thread and increase 't' */ |
|
564 int rc = pthread_create(&threads[t++], NULL, renderrow, (void *)d); |
|
565 if (rc) { |
|
566 dbgmsg(0, "\nE pthread_create unsuccessful, return code was %d\n", rc); |
|
567 exit(1); |
|
568 } |
|
569 /* when 't' overflows, reset it */ |
|
570 if (t >= num_threads) |
|
571 t = 0; |
|
572 /* wait for next thread in fifo queue, so the descriptor can be reused; |
|
573 this also limits number of running threads */ |
|
574 if (!pthread_equal(threads[t], pthread_self())) |
|
575 if (pthread_join(threads[t], (void**)&d) == 0) |
|
576 free(d); |
|
577 #else |
|
578 renderrow((void *)d); |
|
579 free(d); |
|
580 #endif |
|
581 dfix += dy*subsample; |
|
582 dbgmsg(2, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b%4d (%2d%% done)", y, y*100/(h-1)); |
|
583 } |
|
584 dbgmsg(2, "\n"); |
|
585 |
|
586 #ifdef PTHREADS |
|
587 dbgmsg(2, "- waiting for threads to finish\n"); |
|
588 for (t = 0; t < num_threads; t++) |
|
589 if (pthread_join(threads[t], (void**)&d) == 0) |
|
590 free(d); |
|
591 #endif |
|
592 |
|
593 #endif |
|
594 } |
538 } |
595 |
539 |
596 void Raytracer::addlight(Light *light) |
540 void Raytracer::addlight(Light *light) |
597 { |
541 { |
598 lights.push_back(light); |
542 lights.push_back(light); |