nuclear@22: #include nuclear@22: #include nuclear@22: #include "raytrace.h" nuclear@22: #include "rayzor.h" nuclear@22: #include "scene.h" nuclear@22: #include "logger.h" nuclear@22: nuclear@22: Vector3 ray_trace(const Ray &ray, int iter) nuclear@22: { nuclear@22: RayHit hit; nuclear@22: if(!scene->intersect(ray, &hit)) { nuclear@22: return scene->get_background(ray); nuclear@22: } nuclear@22: nuclear@22: return shade(hit, iter); nuclear@22: } nuclear@22: nuclear@22: static inline float positive(float x) nuclear@22: { nuclear@22: return x < 0.0f ? 0.0f : x; nuclear@22: } nuclear@22: nuclear@22: Vector3 shade(const RayHit &hit, int iter) nuclear@22: { nuclear@22: const Material &mtl = hit.obj->mtl; nuclear@22: nuclear@22: Vector3 pos = hit.ray.origin + hit.ray.dir * hit.dist; nuclear@22: Vector3 norm = hit.obj->hit_normal(hit); nuclear@22: norm = normalize(transform(normal_matrix(hit.obj->get_matrix()), norm)); nuclear@22: Vector3 vdir = -normalize(hit.ray.dir); nuclear@22: nuclear@22: float ior = mtl.ior; nuclear@22: nuclear@22: if(dot(norm, hit.ray.dir) > 0.0) { nuclear@22: norm = -norm; nuclear@22: ior = 1.0 / mtl.ior; nuclear@22: } nuclear@22: nuclear@22: Vector3 color = scene->get_ambient(); nuclear@22: nuclear@22: // for each light, calculate local illumination nuclear@22: int num_lights = scene->get_light_count(); nuclear@22: for(int i=0; iget_light(i); nuclear@22: Vector3 ldir = lt->get_position() - pos; nuclear@22: Vector3 lcol = lt->get_color(pos); nuclear@22: nuclear@22: RayHit hit; nuclear@22: if(!scene->intersect(Ray(pos, ldir), &hit) || hit.dist > 1.0) { nuclear@22: // if we can see the light, calculate and add its contribution nuclear@22: ldir.normalize(); nuclear@22: float ndotl = positive(dot(norm, ldir)); nuclear@22: Vector3 diffuse = mtl.diffuse * lcol * ndotl; nuclear@22: nuclear@22: Vector3 hdir = normalize(ldir + vdir); nuclear@22: float ndoth = positive(dot(norm, hdir)); nuclear@22: Vector3 specular = mtl.specular * lcol * pow(ndoth, mtl.roughness * 128.0); nuclear@22: nuclear@22: color = color + lerp(specular, diffuse, mtl.roughness); nuclear@22: } nuclear@22: } nuclear@22: nuclear@22: if(mtl.reflect > 1e-4 && iter < 6) { nuclear@22: Ray reflray(pos, reflect(vdir, norm)); nuclear@22: nuclear@22: Vector3 rcol = ray_trace(reflray, iter + 1) * mtl.specular * mtl.reflect; nuclear@22: color = color + rcol; nuclear@22: } nuclear@22: nuclear@22: if(mtl.refract > 1e-4 && iter < 6) { nuclear@22: Ray refrray(pos, refract(vdir, norm, ior)); nuclear@22: nuclear@22: Vector3 rcol = ray_trace(refrray, iter + 1) * mtl.specular * mtl.refract; nuclear@22: color = color + rcol; nuclear@22: } nuclear@22: nuclear@22: return color; nuclear@22: }