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 |
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) |