RGBColor Phong::shade(ShadeRec& sr) { Vector3D wo = -sr.ray.d; RGBColor L = ambient_brdf->rho(sr, wo) * sr.w.ambient_ptr->L(sr); int num_lights = sr.w.lights.size(); for (int j = 0; j < num_lights; j++) { Vector3D wi = sr.w.lights[j]->get_direction(sr); float ndotwi = sr.normal * wi; if (ndotwi > 0.0) { bool in_shadow = false; if (shadows && sr.w.lights[j]->casts_shadows()) { Ray shadowsRay(sr.hit_point, wi); in_shadow = sr.w.lights[j]->in_shadow(shadowsRay, sr); } if (!in_shadow) L += (diffuse_brdf->f(sr, wo, wi) + specular_brdf->f(sr, wo, wi)) * sr.w.lights[j]->L(sr) * ndotwi; } } return L; }
gml::vec3_t Scene::shadeRay(const RayTracing::Ray_t &ray, RayTracing::HitInfo_t &hitinfo, const int remainingRecursionDepth) const { // TODO! // Calculate the shade/radiance/color of the given ray. Return the calculated color // - Information about the ray's point of nearest intersection is located // in 'hitinfo' // - If remainingRecursionDepth is 0, then _no_ recursive rays (mirror or indirect lighting) should be cast // Note: You will have to set up the values for a RayTracing::ShaderValues object, and then // pass the object to a shader object to do the appropriate shading. // Use m_shaderManager.getShader() to get an appropriate Shader object for shading // the point based on material properties of the object intersected. // When implementing shadows, then the direct lighting component of the // calculated ray color will be black if the point is in shadow. //ml::vec3_t shade(0.5, 0.5, 0.5); //RayTracing::ShaderValues sv(hitinfo.objHit->getMaterial()); // Note: For debugging your rayIntersection() function, this function // returns some non-black constant color at first. When you actually implement // this function, then initialize shade to black (0,0,0). gml::vec3_t shade(0.0, 0.0, 0.0); gml::vec2_t texCoord; gml::vec3_t normal; hitinfo.objHit->hitProperties(hitinfo, normal, texCoord); RayTracing::ShaderValues shaderVal(hitinfo.objHit->getMaterial()); shaderVal.n = normal; shaderVal.p = gml::add(ray.o, gml::scale(hitinfo.hitDist, ray.d)); shaderVal.e = gml::normalize(gml::scale(-1.0f, ray.d)); shaderVal.tex = texCoord; shaderVal.lightDir = gml::normalize(gml::sub(gml::extract3(m_lightPos), shaderVal.p)); shaderVal.lightRad = m_lightRad; float distToLight = gml::length(gml::sub(gml::extract3(m_lightPos), shaderVal.p)); // test if in shadow RayTracing::Ray_t shadowRay; shadowRay.o = shaderVal.p; shadowRay.d = shaderVal.lightDir; if (!shadowsRay(shadowRay, 0.001, distToLight)) { // direct lighting shade = m_shaderManager.getShader(hitinfo.objHit->getMaterial())->shade(shaderVal); } else { shade = gml::vec3_t(0,0,0); } // Only proceed if the recursion depth limit has not been met. if (remainingRecursionDepth > 0) { // Mirror checks, and shading. if (hitinfo.objHit->getMaterial().isMirror()) { // Ray for mirrors. RayTracing::Ray_t mirrorRay; mirrorRay.o = shaderVal.p; mirrorRay.d = gml::normalize(gml::scale(-1, gml::reflect(ray.d, normal))); RayTracing::HitInfo_t mirrorHitInfo; // If intersection, get the mirror shading color and apply it. if (this->rayIntersects(mirrorRay, 0.001f, FLT_MAX, mirrorHitInfo)) { gml::vec3_t mirrorShade = shadeRay(mirrorRay, mirrorHitInfo, remainingRecursionDepth - 1); shade = gml::add(shade, gml::mul(hitinfo.objHit->getMaterial().getMirrorRefl(), mirrorShade)); } } // Setup indirect lighting. RayTracing::Ray_t indirectRay; indirectRay.o = shaderVal.p; indirectRay.randomDirection(shaderVal.n); RayTracing::HitInfo_t indirectHitInfo; // If intersection, apply indirect ray for indirect lighting. if (this->rayIntersects(indirectRay, 0.001f, FLT_MAX, indirectHitInfo)) { shaderVal.lightDir = indirectRay.d; shaderVal.lightRad = shadeRay(indirectRay, indirectHitInfo, remainingRecursionDepth - 1); gml::vec3_t indirectShade = m_shaderManager.getShader(hitinfo.objHit->getMaterial())->shade(shaderVal); // Add together to the cumulative color. shade = gml::add(shade, indirectShade); } } // Note: For debugging your rayIntersection() function, this function // returns some non-black constant color at first. When you actually implement // this function, then initialize shade to black (0,0,0). // Return the cumulative color for the point. return shade; }