src/raytracer.cc
branchpyrit
changeset 77 dbe8438d5dca
parent 75 20dee9819b17
child 82 930a2d3ecaed
equal deleted inserted replaced
76:3b60fd0bea64 77:dbe8438d5dca
   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)