src/raytracer.cc
branchpyrit
changeset 93 96d65f841791
parent 92 9af5c039b678
child 95 ca7d4c665531
equal deleted inserted replaced
92:9af5c039b678 93:96d65f841791
    28 #include <stdio.h>
    28 #include <stdio.h>
    29 #include <stdlib.h>
    29 #include <stdlib.h>
    30 #include <assert.h>
    30 #include <assert.h>
    31 #include "raytracer.h"
    31 #include "raytracer.h"
    32 
    32 
    33 int pyrit_verbosity = 2;
       
    34 
       
    35 // Hammersley spherical point distribution
    33 // Hammersley spherical point distribution
    36 // http://www.cse.cuhk.edu.hk/~ttwong/papers/udpoint/udpoints.html
    34 // http://www.cse.cuhk.edu.hk/~ttwong/papers/udpoint/udpoints.html
    37 Vector Raytracer::SphereDistribute(int i, int n, Float extent, const Vector &normal)
    35 Vector Raytracer::SphereDistribute(int i, int n, Float extent, const Vector &normal)
    38 {
    36 {
    39 	Float p, t, st, phi, phirad;
    37 	Float p, t, st, phi, phirad;
    40 	int kk;
    38 	int kk;
    41 
    39 
    42 	t = 0;
    40 	t = 0;
    43 	for (p=0.5, kk=i; kk; p*=0.5, kk>>=1)
    41 	for (p=0.5f, kk=i; kk; p*=0.5f, kk>>=1)
    44 	if (kk & 1)
    42 	if (kk & 1)
    45 		t += p;
    43 		t += p;
    46 	t = 1.0 + (t - 1.0)*extent;
    44 	t = 1.0f + (t - 1.0f)*extent;
    47 
    45 
    48 	phi = (i + 0.5) / n;
    46 	phi = (i + 0.5f) / n;
    49 	phirad =  phi * 2.0 * M_PI;
    47 	phirad =  phi * 2.0f * PI;
    50 
    48 
    51 	st = sqrt(1.0 - t*t);
    49 	st = sqrt(1.0f - t*t);
    52 
    50 
    53 	Float x, y, z, xx, yy, zz, q;
    51 	Float x, y, z, xx, yy, zz, q;
    54 	x = st * cos(phirad);
    52 	x = st * cos(phirad);
    55 	y = st * sin(phirad);
    53 	y = st * sin(phirad);
    56 	z = t;
    54 	z = t;
   103 				Float dist = FLT_MAX;
   101 				Float dist = FLT_MAX;
   104 				if (top->nearest_intersection(shape, shadow_ray, dist))
   102 				if (top->nearest_intersection(shape, shadow_ray, dist))
   105 					continue;
   103 					continue;
   106 			}
   104 			}
   107 
   105 
   108 			const Vector R = L - 2.0 * L_dot_N * N;
   106 			const Vector R = L - 2.0f * L_dot_N * N;
   109 			const Float R_dot_V = dot(R, V);
   107 			const Float R_dot_V = dot(R, V);
   110 
   108 
   111 			// diffuse
   109 			// diffuse
   112 			acc += mat->diffuse * col * (*light)->colour * L_dot_N;
   110 			acc += mat->diffuse * col * (*light)->colour * L_dot_N;
   113 
   111 
   203 		const Float cos_i = - dot(normal, ray.dir);
   201 		const Float cos_i = - dot(normal, ray.dir);
   204 
   202 
   205 		// reflection
   203 		// reflection
   206 		if (refl > 0.01)
   204 		if (refl > 0.01)
   207 		{
   205 		{
   208 			Vector newdir = ray.dir + 2.0 * cos_i * normal;
   206 			Vector newdir = ray.dir + 2.0f * cos_i * normal;
   209 			Ray newray = Ray(P, newdir);
   207 			Ray newray = Ray(P, newdir);
   210 			refl_col = raytrace(newray, depth + 1, shape);
   208 			refl_col = raytrace(newray, depth + 1, shape);
   211 		}
   209 		}
   212 
   210 
   213 		// refraction
   211 		// refraction
   220 				n2 = 1.0;
   218 				n2 = 1.0;
   221 				n = n1;
   219 				n = n1;
   222 			}
   220 			}
   223 			else
   221 			else
   224 			{
   222 			{
   225 				n1 = 1.0;
   223 				n1 = 1.0f;
   226 				n2 = shape->material->refract_index;
   224 				n2 = shape->material->refract_index;
   227 				n = 1.0 / n2;
   225 				n = 1.0f / n2;
   228 			}
   226 			}
   229 			const Float sin2_t = n*n * (1 - cos_i*cos_i);
   227 			const Float sin2_t = n*n * (1 - cos_i*cos_i);
   230 			if (sin2_t >= 1.0)
   228 			if (sin2_t >= 1.0)
   231 			{
   229 			{
   232 					// totally reflected
   230 					// totally reflected
   234 					trans = 0;
   232 					trans = 0;
   235 			}
   233 			}
   236 			else
   234 			else
   237 			{
   235 			{
   238 				const Float cos_t = sqrtf(1 - sin2_t);
   236 				const Float cos_t = sqrtf(1 - sin2_t);
   239 				const Float Rdiv = 1.0/(n1*cos_i + n2*cos_t);
   237 				const Float Rdiv = 1.0f / (n1*cos_i + n2*cos_t);
   240 				const Float Rper = (n1*cos_i - n2*cos_t)*Rdiv;
   238 				const Float Rper = (n1*cos_i - n2*cos_t)*Rdiv;
   241 				const Float Rpar = (n2*cos_i - n1*cos_t)*Rdiv;
   239 				const Float Rpar = (n2*cos_i - n1*cos_t)*Rdiv;
   242 				const Float R = (Rper*Rper + Rpar*Rpar)/2;
   240 				const Float R = (Rper*Rper + Rpar*Rpar)/2;
   243 				refl += R*trans;
   241 				refl += R*trans;
   244 				trans = (1-R)*trans;
   242 				trans = (1-R)*trans;
   245 				Vector newdir = n * ray.dir + (n*cos_i - cos_t) * normal;
   243 				Vector newdir = n * ray.dir + (n*cos_i - cos_t) * normal;
   246 				Ray newray = Ray(P + 0.001*newdir, newdir);
   244 				Ray newray = Ray(P + 0.001f*newdir, newdir);
   247 				trans_col = raytrace(newray, depth + 1, NULL);
   245 				trans_col = raytrace(newray, depth + 1, NULL);
   248 			}
   246 			}
   249 		}
   247 		}
   250 		col = (1-refl-trans)*col + refl*refl_col + trans*trans_col;
   248 		col = (1-refl-trans)*col + refl*refl_col + trans*trans_col;
   251 	}
   249 	}
   321 
   319 
   322 	const VectorPacket P = rays.o + rays.dir * m_nearest_distances; // point of intersection
   320 	const VectorPacket P = rays.o + rays.dir * m_nearest_distances; // point of intersection
   323 	VectorPacket normal;
   321 	VectorPacket normal;
   324 	for (int i = 0; i < 4; i++)
   322 	for (int i = 0; i < 4; i++)
   325 		if (nearest_shapes[i] != NULL)
   323 		if (nearest_shapes[i] != NULL)
   326 			normal.setVector(i, nearest_shapes[i]->normal(P.getVector(i)));
   324 		{
       
   325 			const Vector Pvecti = P.getVector(i);
       
   326 			normal.setVector(i, nearest_shapes[i]->normal(Pvecti));
       
   327 		}
   327 
   328 
   328 	// make shapes double sided
   329 	// make shapes double sided
   329 	mfloat4 from_inside = mcmpgt(dot(normal, rays.dir), mZero);
   330 	mfloat4 from_inside = mcmpgt(dot(normal, rays.dir), mZero);
   330 	normal.mx = mselect(from_inside, msub(mZero, normal.mx), normal.mx);
   331 	normal.mx = mselect(from_inside, msub(mZero, normal.mx), normal.mx);
   331 	normal.my = mselect(from_inside, msub(mZero, normal.my), normal.my);
   332 	normal.my = mselect(from_inside, msub(mZero, normal.my), normal.my);
   348 		else
   349 		else
   349 			results[i] = bg_colour;
   350 			results[i] = bg_colour;
   350 }
   351 }
   351 #endif
   352 #endif
   352 
   353 
       
   354 #ifdef MSVC
       
   355 __declspec(noreturn)
       
   356 #else
       
   357 __attribute__((noreturn))
       
   358 #endif
   353 void *Raytracer::raytrace_worker(void *d)
   359 void *Raytracer::raytrace_worker(void *d)
   354 {
   360 {
   355 	static const int my_queue_size = 256;
   361 	static const int my_queue_size = 256;
   356 	Raytracer *rt = (Raytracer*)d;
   362 	Raytracer *rt = (Raytracer*)d;
   357 	Sample my_queue[my_queue_size];
   363 	Sample my_queue[my_queue_size];
   403 		// do the work
   409 		// do the work
   404 #ifndef NO_SIMD
   410 #ifndef NO_SIMD
   405 		if (can_use_packets)
   411 		if (can_use_packets)
   406 		{
   412 		{
   407 			// packet ray tracing
   413 			// packet ray tracing
   408 			assert((my_count % 4) == 0);
   414 			assert((my_count & 3) == 0);
   409 			for (int i = 0; i < my_count; i+=4)
   415 			for (int i = 0; i < (my_count >> 2); i++)
   410 			{
   416 			{
   411 				rt->camera->makeRayPacket(my_queue + i, rays);
   417 				rt->camera->makeRayPacket(my_queue + (i<<2), rays);
   412 				rt->raytracePacket(rays, my_colours + i);
   418 				rt->raytracePacket(rays, my_colours + (i<<2));
   413 			}
   419 			}
   414 		}
   420 		}
   415 		else
   421 		else
   416 #endif
   422 #endif
   417 		{
   423 		{
   427 		pthread_mutex_lock(&rt->sampler_mutex);
   433 		pthread_mutex_lock(&rt->sampler_mutex);
   428 		for (int i = 0; i < my_count; i++)
   434 		for (int i = 0; i < my_count; i++)
   429 			rt->sampler->saveSample(my_queue[i], my_colours[i]);
   435 			rt->sampler->saveSample(my_queue[i], my_colours[i]);
   430 		pthread_mutex_unlock(&rt->sampler_mutex);
   436 		pthread_mutex_unlock(&rt->sampler_mutex);
   431 	}
   437 	}
   432 	return NULL;
       
   433 }
   438 }
   434 
   439 
   435 void Raytracer::render()
   440 void Raytracer::render()
   436 {
   441 {
   437 	if (!sampler || !camera || !top)
   442 	if (!sampler || !camera || !top)