src/raytracer.cc
branchpyrit
changeset 53 228cb8bfdd54
parent 52 a6413a3d741d
child 54 dbe3c7a4e0f0
equal deleted inserted replaced
52:a6413a3d741d 53:228cb8bfdd54
    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 {
   394 #endif
   394 #endif
   395 
   395 
   396 void *Raytracer::raytrace_worker(void *d)
   396 void *Raytracer::raytrace_worker(void *d)
   397 {
   397 {
   398 	Raytracer *rt = (Raytracer*)d;
   398 	Raytracer *rt = (Raytracer*)d;
   399 	Sample *sample;
   399 	Sample my_queue[80];
   400 	Colour col;
   400 	Colour my_colours[80];
       
   401 	int my_count;
   401 	Ray ray;
   402 	Ray ray;
   402 	for (;;)
   403 	for (;;)
   403 	{
   404 	{
   404 		pthread_mutex_lock(&rt->sample_queue_mutex);
   405 		pthread_mutex_lock(&rt->sample_queue_mutex);
   405 		pthread_cond_signal(&rt->worker_ready_cond);
   406 		pthread_cond_signal(&rt->worker_ready_cond);
   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);
   603 	ao_samples = samples;
   547 	ao_samples = samples;
   604 	ao_distance = distance;
   548 	ao_distance = distance;
   605 	ao_angle = angle;
   549 	ao_angle = angle;
   606 	if (ao_distance == 0)
   550 	if (ao_distance == 0)
   607 		/* 0 ==> Inf */
   551 		/* 0 ==> Inf */
   608 		ao_distance = FLT_MAX;
   552 		ao_distance = Inf;
   609 }
   553 }