rev |
line source |
nuclear@17
|
1 #include <assert.h>
|
nuclear@17
|
2 #include <float.h>
|
nuclear@17
|
3 #include "raytrace.h"
|
nuclear@17
|
4 #include "rayzor.h"
|
nuclear@17
|
5 #include "scene.h"
|
nuclear@17
|
6 #include "logger.h"
|
nuclear@17
|
7
|
nuclear@17
|
8 Vector3 ray_trace(const Ray &ray, int iter)
|
nuclear@17
|
9 {
|
nuclear@17
|
10 RayHit hit;
|
nuclear@17
|
11 if(!scene->intersect(ray, &hit)) {
|
nuclear@17
|
12 return scene->get_background(ray);
|
nuclear@17
|
13 }
|
nuclear@17
|
14
|
nuclear@17
|
15 return shade(hit, iter);
|
nuclear@17
|
16 }
|
nuclear@17
|
17
|
nuclear@17
|
18 static inline float positive(float x)
|
nuclear@17
|
19 {
|
nuclear@17
|
20 return x < 0.0f ? 0.0f : x;
|
nuclear@17
|
21 }
|
nuclear@17
|
22
|
nuclear@17
|
23 Vector3 shade(const RayHit &hit, int iter)
|
nuclear@17
|
24 {
|
nuclear@19
|
25 const Material &mtl = hit.obj->mtl;
|
nuclear@19
|
26
|
nuclear@17
|
27 Vector3 pos = hit.ray.origin + hit.ray.dir * hit.dist;
|
nuclear@17
|
28 Vector3 norm = hit.obj->hit_normal(hit);
|
nuclear@17
|
29 norm = normalize(transform(normal_matrix(hit.obj->get_matrix()), norm));
|
nuclear@17
|
30 Vector3 vdir = -normalize(hit.ray.dir);
|
nuclear@17
|
31
|
nuclear@19
|
32 float ior = mtl.ior;
|
nuclear@19
|
33
|
nuclear@19
|
34 if(dot(norm, hit.ray.dir) > 0.0) {
|
nuclear@19
|
35 norm = -norm;
|
nuclear@19
|
36 ior = 1.0 / mtl.ior;
|
nuclear@19
|
37 }
|
nuclear@19
|
38
|
nuclear@17
|
39 Vector3 color = scene->get_ambient();
|
nuclear@17
|
40
|
nuclear@19
|
41 // for each light, calculate local illumination
|
nuclear@17
|
42 int num_lights = scene->get_light_count();
|
nuclear@17
|
43 for(int i=0; i<num_lights; i++) {
|
nuclear@17
|
44 const Light *lt = scene->get_light(i);
|
nuclear@17
|
45 Vector3 ldir = lt->get_position() - pos;
|
nuclear@17
|
46 Vector3 lcol = lt->get_color(pos);
|
nuclear@17
|
47
|
nuclear@17
|
48 RayHit hit;
|
nuclear@17
|
49 if(!scene->intersect(Ray(pos, ldir), &hit) || hit.dist > 1.0) {
|
nuclear@17
|
50 // if we can see the light, calculate and add its contribution
|
nuclear@17
|
51 ldir.normalize();
|
nuclear@17
|
52 float ndotl = positive(dot(norm, ldir));
|
nuclear@19
|
53 Vector3 diffuse = mtl.diffuse * lcol * ndotl;
|
nuclear@17
|
54
|
nuclear@17
|
55 Vector3 hdir = normalize(ldir + vdir);
|
nuclear@17
|
56 float ndoth = positive(dot(norm, hdir));
|
nuclear@19
|
57 Vector3 specular = mtl.specular * lcol * pow(ndoth, mtl.roughness * 128.0);
|
nuclear@17
|
58
|
nuclear@19
|
59 color = color + lerp(specular, diffuse, mtl.roughness);
|
nuclear@17
|
60 }
|
nuclear@17
|
61 }
|
nuclear@17
|
62
|
nuclear@19
|
63 if(mtl.reflect > 1e-4 && iter < 6) {
|
nuclear@19
|
64 Ray reflray(pos, reflect(vdir, norm));
|
nuclear@19
|
65
|
nuclear@19
|
66 Vector3 rcol = ray_trace(reflray, iter + 1) * mtl.specular * mtl.reflect;
|
nuclear@19
|
67 color = color + rcol;
|
nuclear@19
|
68 }
|
nuclear@19
|
69
|
nuclear@19
|
70 if(mtl.refract > 1e-4 && iter < 6) {
|
nuclear@19
|
71 Ray refrray(pos, refract(vdir, norm, ior));
|
nuclear@19
|
72
|
nuclear@19
|
73 Vector3 rcol = ray_trace(refrray, iter + 1) * mtl.specular * mtl.refract;
|
nuclear@19
|
74 color = color + rcol;
|
nuclear@19
|
75 }
|
nuclear@19
|
76
|
nuclear@17
|
77 return color;
|
nuclear@17
|
78 }
|