Vec3f Ray::getColor(const vector <tinyobj::shape_t> &shapes, const vector <tinyobj::material_t> &materials, Vec3f lightSource) { if (DBG) cout << "[getColor] depth = " << depth << endl; //get triangle that intersect the ray Vec3f triangle[3]; pair <int, int> triangleId = this->getIntersectTriangle(shapes, triangle); DBG && cout << "\t[triangleId] " << triangleId.first << ' ' << triangleId.second << endl; if (triangleId.first == -1) { DBG && cout << "\t[return] no intersection" << endl; return Vec3f(0.0, 0.0, 0.0); } Vec3f reversedDirection = this->direction * -1; if (dot(reversedDirection, getNormalwithRayComes(triangle, this->direction)) < 0) { DBG && cout << "[return] " << endl; return Vec3f(0.0, 0.0, 0.0); } //check if position and lightsource are in different sides of the triangle Vec3f intersection; Vec3f color_direct; unsigned int iMaterial = shapes[triangleId.first].mesh.material_ids[triangleId.second]; if (lineCutTrianglePlane(triangle, this->direction, this->position, lightSource)) { DBG && cout << "\t[message] lineCutTrianglePlane" << endl; color_direct = Vec3f(0.0, 0.0, 0.0); } else { //calculate intersection this->intersect_remake(triangle, intersection); //check reflected ray Ray reflectedRay(intersection, lightSource - intersection, bshRoot, 0, triangleId); if (reflectedRay.canReach(lightSource, shapes) == false) { DBG && cout << "\t[message] reflected ray cannot reach lightsource" << endl; color_direct = Vec3f(0.0, 0.0, 0.0); } else { //calculate color_direct float radian_direct = ggx(this->position, lightSource, intersection, triangle, 1.0, 0.8, 0.8, 2.0); // color_direct = Vec3f( (materials[iMaterial].diffuse[0] + materials[iMaterial].specular[0]) * radian_direct, // (materials[iMaterial].diffuse[1] + materials[iMaterial].specular[1]) * radian_direct, // (materials[iMaterial].diffuse[2] + materials[iMaterial].specular[2]) * radian_direct); color_direct = Vec3f( (materials[iMaterial].diffuse[0]) * radian_direct, (materials[iMaterial].diffuse[1]) * radian_direct, (materials[iMaterial].diffuse[2]) * radian_direct); DBG && cout << "\t[color] " << color_direct << endl; } } Vec3f color_indirect(0.0, 0.0, 0.0); int counter = 0; if (depth < MAX_DEPTH) { for (int iRay = 0; iRay < NUMBER_OF_RAYS; ++iRay) { Ray ray = this->getRandomRay_Sphere(intersection, triangle, depth + 1, triangleId); // if (triangleId.first == 4) // ray = this->getMirrorRay(intersection, triangle, depth + 1, triangleId); // Ray ray = this->getRandomRay_Sphere(intersection, triangle, depth + 1, triangleId); // Ray ray = this->getInConeRay(intersection, triangle, depth + 1, triangleId); // Ray ray = this->getUniformRay_Plane(intersection, triangle, depth + 1, triangleId, iRay, NUMBER_OF_RAYS); // Ray ray = this->getMirrorRay(intersection, triangle, depth + 1, triangleId); Vec3f color = ray.getColor(shapes, materials, lightSource); float cos_theta = dot(ray.direction, getNormalwithRayComes(triangle, this->direction)); Vec3f w = lightSource - intersection; Vec3f w0 = this->position - intersection; Vec3f n = getNormalwithRayComes(triangle, this->direction); w.normalize(); w0.normalize(); n.normalize(); float f_s = brdf_GGX(w, w0, n, 0.8, 0.8); float f_d = f_Lambert(2.0); // float f_d = 0; color_indirect += color * (f_s + f_d) * fabs(cos_theta); // color_indirect += color * (f_s + f_d); counter++; } if (counter > 0) color_indirect /= counter; DBG && cout << "\t[color_indirect] = " << color_indirect << endl; } DBG && cout << "\t[counter] " << counter << endl; DBG && cout << "\t[color] " << color_direct << endl; // color_direct = (color_direct * 0.5) + (color_indirect * 0.5); color_direct += (1.0f * color_indirect); for (int i = 0; i < 3; ++i) color_direct[i] = min(color_direct[i], 1.0f); if (this->depth == 1) DBG && cout << "final color = " << color_direct << endl; // return color_direct + Vec3f(materials[iMaterial].ambient[0], // materials[iMaterial].ambient[1], // materials[iMaterial].ambient[2]); return color_direct; }
Color Ray::getColor(const Scene& scene, int maxdepth, double relevance) const { Color sum = Color(0,0,0), colorReflection = Color(0, 0, 0), colorTransmission = Color(0,0,0), colorRefraction = Color(0,0,0), colorEmission = Color(0, 0, 0); Intersection intersect; Vector normal; vector<Photon> photons; vector<Photon>::const_iterator photon, end; Vector rayDirection; double reflectance, refractance, emittance, roughness; double angle; if (maxdepth == 0 || relevance < Engine::EPS || !scene.intersect(*this, intersect)) return Color(0,0,0); normal = intersect.prim->normal(intersect.point); if (this->inside) normal = -normal; /* emittance + reflectance + refractance = 1 */ emittance = intersect.prim->mat.emittance; roughness = intersect.prim->mat.roughness; if (this->inside) reflectance = scene.environment.reflectance(this->direction, normal, intersect.prim->mat); else reflectance = intersect.prim->mat.reflectance(this->direction, normal, scene.environment); reflectance = (1 - emittance) * reflectance; refractance = 1 - reflectance - emittance; if (reflectance > 0) { Ray specularRay; Color specularReflection = Color(0,0,0), diffuseReflection = Color(0,0,0); /* Specular reflection */ rayDirection = intersect.prim->mat.reflectionDirection(this->direction,normal); specularRay.origin = intersect.point; specularRay.direction = rayDirection; specularRay.inside = this->inside; specularReflection = specularRay.getColor(scene, maxdepth-1, relevance * reflectance * (1 - roughness)); /* Diffuse reflection */ photons = scene.getNearestPhotons(intersect.point, Engine::MAX_GATHER_DISTANCE); for (photon = photons.begin(), end = photons.end(); photon != end; photon++) { angle = (*photon).ray.direction.dot(normal); if (angle > 0 && ((intersect.point - (*photon).ray.origin).sqrd_norm() < Engine::MAX_GATHER_DISTANCE_SQRD)) diffuseReflection = diffuseReflection + (*photon).color * angle; } diffuseReflection = diffuseReflection * Engine::EXPOSURE / (M_PI * Engine::MAX_GATHER_DISTANCE_SQRD); colorReflection = (diffuseReflection * reflectance * roughness) + (specularReflection * reflectance * (1 - roughness)); } if (refractance > 0) { Ray refractedRay; /* Check whether the ray is inside (= refracted ray going out) or outside (= refracted ray coming in) a primitive */ if (this->inside) { rayDirection = scene.environment.refractionDirection(this->direction,normal,intersect.prim->mat); /* from primitive's material to scene's environment */ colorRefraction = intersect.prim->mat.color; } else { rayDirection = intersect.prim->mat.refractionDirection(this->direction,normal,scene.environment); /* from scene's environment to primitive's material */ colorRefraction = Color(255,255,255); } /* "original" ray must always be casted */ refractedRay.origin = intersect.point; refractedRay.direction = rayDirection; refractedRay.inside = (this->inside ? NULL : intersect.prim); /* Set ray's relative location (inside or outside of a primitive (outside = air)) */ colorTransmission = refractedRay.getColor(scene, maxdepth-1, relevance*refractance); colorRefraction = colorRefraction * colorTransmission * refractance; } if (emittance > 0) colorEmission = intersect.prim->mat.color * emittance; sum = colorReflection + colorRefraction + colorEmission; return sum.cap(); }