/*======== double get_illumination() ========== Inputs: double *l double *n int cp double *constants Returns: illumination (0 - 255) Sum of ambient, diffuse, and specular components of illumination ====================*/ color get_illumination(vector light, vector normal, double *cp, color ca, struct constants *cons){ color c; double ambient, diffuse, specular; int val; ambient = get_ambient(ca.red, cons -> r[Ka]); diffuse = get_diffuse(light, normal, cp[0], cons -> r[Kd]); specular = get_specular(light, normal, cp[0], cons -> r[Ks]); val = ambient + diffuse + specular; c.red = val <= 255 ? val : 255; ambient = get_ambient(ca.green, cons -> g[Ka]); diffuse = get_diffuse(light, normal, cp[1], cons -> g[Kd]); specular = get_specular(light, normal, cp[1], cons -> g[Ks]); val = ambient + diffuse + specular; c.green = val <= 255 ? val : 255; ambient = get_ambient(ca.blue, cons -> b[Ka]); diffuse = get_diffuse(light, normal, cp[2], cons -> b[Kd]); specular = get_specular(light, normal, cp[2], cons -> b[Ks]); val = ambient + diffuse + specular; c.blue = val <= 255 ? val : 255; if (cons -> red || cons -> green || cons -> blue){ c.red *= cons -> red; c.green *= cons -> green; c.blue *= cons -> blue; } return c; }
optix::float3 DiffuseAmbientOccluded::doWeightedCosineSamplingWithEnvironmentSampling(const optix::Ray& r, HitInfo& hit, bool emit) const { float3 rho_a = get_emission(hit); float3 rho_d = get_diffuse(hit); float3 avgUnoccluded = make_float3(0,0,0); int numOfUnoccluded = 0; const int numOfRays = 200; for(int i = 0 ; i < numOfRays ; i++) { Ray hemiRay = r; HitInfo hemiHit; if(sampleCosineWeightedHemisphere(hemiRay, hemiHit, hit)) { avgUnoccluded += hemiRay.direction; numOfUnoccluded++; } } float3 averageNormal = normalize(avgUnoccluded / numOfUnoccluded); float accessability = ((float)numOfUnoccluded) / numOfRays; // sample the environment in the average unoccluded direction float3 hdrValue = tracer -> get_background(averageNormal); return M_1_PIf * accessability * rho_d * hdrValue; }
vector3f get_ray_trace(ray &r, kdtree &kdtree, int depth) { if (depth >= max_depth) { return vector3f(0.0, 0.0, 0.0); } vector3f origin_cp = r.origin; primitive *pri = get_intersecting_primitive(kdtree, r); if (pri == NULL) { return background; } else { double *amb = pri->get_material().amb; double *dif = pri->get_material().dif; double *spc = pri->get_material().spc; // ambient calculation vector3f ambient = get_ambient(amb); // specular calculation (no transparency) vector3f specular = get_specular(spc, pri, r, kdtree, depth); // diffuse calculation double spc_alpha = 1; vector3f diffuse = get_diffuse(dif, pri, r, kdtree, depth, spc_alpha); return rgb_trim(ambient + specular * spc_alpha + diffuse); } }
static int get_spot(t_ray *ray, t_ray *light, t_spot *spot) { int color; color = get_diffuse(ray, light, spot); color = color_add(color, get_specular(ray, light, spot)); return (color); }
/** * Performs a raytrace on the given pixel on the current scene. * The pixel is relative to the bottom-left corner of the image. */ Color3 Raytracer::trace_pixel(int recursions, const Ray& ray, float refractive) { size_t num_geometries = scene->num_geometries(); bool hit_any = false; // if any geometries were hit IsectInfo min_info; // everything we're calculating from intersection Vector3 intersection_point = Vector3::Zero; // run intersection test on every object in scene for (size_t i = 0; i < num_geometries; i++) { IsectInfo info; // intersect returns true if there's a hit, false if not, and sets // values in info struct bool hit = scene->get_geometries()[i]->intersect_ray(ray, info); if (hit && info.time < min_info.time) // min_info.time initializes to inf { min_info = info; intersection_point = ray.eye + (min_info.time * ray.dir); hit_any = true; } } // found a hit if (hit_any) { Color3 direct; Color3 diffuse = Color3::Black; Color3 ambient = scene->ambient_light * min_info.ambient; float angle = dot(ray.dir, min_info.normal); // compute reflected ray Ray incident_ray; incident_ray.dir = ray.dir - 2 * angle * min_info.normal; incident_ray.dir = normalize(incident_ray.dir); incident_ray.eye = intersection_point + eps * incident_ray.dir; // no-refraction case if (min_info.refractive == 0.0) { diffuse = get_diffuse(incident_ray.eye, min_info.normal, min_info.diffuse, eps); direct = min_info.texture * (ambient + diffuse); // return direct light and reflected light if we have recursions left if (recursions >= max_recursion_depth) { return direct; } return direct + min_info.texture * min_info.specular * trace_pixel(recursions + 1, incident_ray, refractive); } // refraction case else { // return black if no more recursions if (recursions >= max_recursion_depth) { return Color3::Black; } float c; Ray transmitted_ray; float refract_ratio = refractive / min_info.refractive; // negative dot product between ray and normal indicates entering object if (angle < 0.0) { refract(ray.dir, min_info.normal, refract_ratio, &transmitted_ray.dir); c = dot(-1.0 * ray.dir, min_info.normal); } else { // exiting object if (refract(ray.dir, (-1.0 * min_info.normal), min_info.refractive, &transmitted_ray.dir)) { c = dot(transmitted_ray.dir, min_info.normal); } // total internal reflection else { return trace_pixel(recursions + 1, incident_ray, refractive); } } // schlick approximation to fresnel equations float R_0 = pow(refract_ratio - 1, 2) / pow(refract_ratio + 1, 2); float R = R_0 + (1 - R_0) * pow(1 - c, 5); transmitted_ray.eye = intersection_point + eps * transmitted_ray.dir; // return reflected and refracted rays return R * trace_pixel(recursions + 1, incident_ray, refractive) + (1.0 - R) * trace_pixel(recursions + 1, transmitted_ray, min_info.refractive); } } // didn't hit anything - return background color else { return scene->background_color; } }
Color3 Raytracer::trace_pixel_end(int recursions, const Ray& ray, float refractive, IsectInfo min_info) { Color3 direct; Color3 diffuse = Color3::Black; Color3 ambient = scene->ambient_light * min_info.ambient; float angle = dot(ray.dir, min_info.normal); // compute reflected ray Vector3 intersection_point = ray.eye + (min_info.time * ray.dir); Ray incident_ray; incident_ray.dir = ray.dir - 2 * angle * min_info.normal; incident_ray.dir = normalize(incident_ray.dir); incident_ray.eye = intersection_point + eps * incident_ray.dir; // no-refraction case if (min_info.refractive == 0.0) { diffuse = get_diffuse(incident_ray.eye, min_info.normal, min_info.diffuse, eps); direct = min_info.texture * (ambient + diffuse); // return direct light and reflected light if we have recursions left if (recursions >= max_recursion_depth) { return direct; } return direct + min_info.texture * min_info.specular * trace_pixel(recursions + 1, incident_ray, refractive); } // refraction case else { // return black if no more recursions if (recursions >= max_recursion_depth) { return Color3::Black; } float c; Ray transmitted_ray; float refract_ratio = refractive / min_info.refractive; // negative dot product between ray and normal indicates entering object if (angle < 0.0) { refract(ray.dir, min_info.normal, refract_ratio, &transmitted_ray.dir); c = dot(-1.0 * ray.dir, min_info.normal); } else { // exiting object if (refract(ray.dir, (-1.0 * min_info.normal), min_info.refractive, &transmitted_ray.dir)) { c = dot(transmitted_ray.dir, min_info.normal); } // total internal reflection else { return trace_pixel(recursions + 1, incident_ray, refractive); } } // schlick approximation to fresnel equations float R_0 = pow(refract_ratio - 1, 2) / pow(refract_ratio + 1, 2); float R = R_0 + (1 - R_0) * pow(1 - c, 5); transmitted_ray.eye = intersection_point + eps * transmitted_ray.dir; // return reflected and refracted rays return R * trace_pixel(recursions + 1, incident_ray, refractive) + (1.0 - R) * trace_pixel(recursions + 1, transmitted_ray, min_info.refractive); } }