const ColorRGB Scene3D::traceRay(const Ray& ray, int depth) const { float closest_t_value = NO_INTERSECT; const SceneObject* closest_object = findClosest(ray, closest_t_value); if (closest_object == 0) return ColorRGB(0,0,0); ColorRGB retColor(0,0,0); for (int i = 0; i < lights.size(); i++) { Vector3D normL = ((*lights[i]).get_position()-ray.getPointAt(closest_t_value)).normalize(); Vector3D normN = (*closest_object).surface_normal(ray.getPointAt(closest_t_value)); retColor += (*lights[i]).get_color()*(*closest_object).get_color()*std::max((normL*normN),float(0)); if (depth < 6 && (*closest_object).get_reflectivity() > 0) { Ray reflected_ray = ray.reflect(ray.getPointAt(closest_t_value), (*closest_object).surface_normal(ray.getPointAt(closest_t_value))); ColorRGB reflection_color = traceRay(reflected_ray, depth+1); retColor+= (*closest_object).get_reflectivity()*reflection_color; } } return retColor; }
Spectrum IntegratorHelpers::radianceDirect(const Scene* scene, const Ray& ray, const RaySurfIntersection& hit, const IntegratorHelpers::SpectralStrategy& ss) { //Memory for output spectrum //TODO: Remove all dynamic memory allocations from rendering inner loop //...for now this is still in here for east of implementation float* buf = new float[ss.numSpectralSamples]; for(int i = 0; i < ss.numSpectralSamples; i++){ buf[i] = 0.0f; } //Return spectrum Spectrum retColor(buf, ss.nmMin, ss.nmMax, ss.nmStep, ss.numSpectralSamples); //Create relavent params const Vector omega_o(-ray.getDir()); const Vector vecN(hit.n.x, hit.n.y, hit.n.z); const AccelStructure* geom = scene->getSceneGeom(); //Scene acceleration structure const bool isEmitter = hit.shp->isEmitter(); const Point hitLocWS(hit.locWS); //Determine the maximum number of light samples we will make //and allocate this memory OUTSIDE of the light loop int NLightSampsMax = -1; for(size_t i = 0; i < scene->getNumLights(); i++){ NLightSampsMax = std::max<int>( NLightSampsMax, scene->getLight(i)->getRecNumVisibilitySamples()); } Point* samps = new Point[NLightSampsMax]; //Process each light individually for(size_t i = 0; i < scene->getNumLights(); i++){ Light* l = scene->getLight(i); //Skip sampling the light itself if the geometry is an emitter if(isEmitter && hit.shp->getEmitter() == l){ continue; } //Sample the light source potentially many times const int N = l->getRecNumVisibilitySamples(); l->getSamples(samps, N); //Loop over all light samples const float invNumSamps = 1.0f / float(N); for(int j = 0; j < N; j++){ //Check if we can see the light VisibilityTester visTest(hitLocWS, samps[j], l->getGeom(), geom, DFLT_RAY_MOVE_EPSILON); //visTest.r is a ray to the light from hitLocWS //Get the incident radiance from the light at the hit location Spectrum L = l->sampleIncidentRadiance(hitLocWS, vecN, samps[j]); //TODO: "continue" here if the spectrum is black...is this any faster? //If we saw the light, add its contribution bool sawLight = visTest.visible(NULL); if(sawLight){ //Vector to light const Vector omega_i(visTest.r.getDir()); //Geomety term (solid angle) const Vector Nvec = hit.n; const float G = GeomUtils::absDotProd(omega_i, Nvec); //Technically, the above G is not correct! TODO //const Vector v = (samps[j] - hitLocWS); //const float r = v.magnitude(); //const float G = GeomUtils::absDotProd(omega_i, Nvec) / (r*r); //Transform vectors into local BRDF frame /* Vector w_i_brdfCS = BRDFCoordHelpers::worldCSToBrdfCS(omega_i, Nvec, hit.tangent, Nvec.cross(hit.tangent)); Vector w_o_brdfCS = BRDFCoordHelpers::worldCSToBrdfCS(omega_o, Nvec, hit.tangent, Nvec.cross(hit.tangent)); */ //Evaluate BRDF term at each wavelength float nm = ss.nmMin; BRDF* brdf = hit.shp->getBRDF(); for(int i = 0; i < ss.numSpectralSamples; i++){ buf[i] = brdf->f(omega_i, omega_o, nm); //buf[i] = brdf->f(w_i_brdfCS, w_o_brdfCS, nm); nm += ss.nmStep; } //Create a "spectrum" of BRDF values Spectrum brdfSpec(buf, ss.nmMin, ss.nmMax, ss.nmStep, ss.numSpectralSamples); //Light term retColor = retColor + (L * G * invNumSamps * brdfSpec); } } } //All done! delete[] samps; samps = NULL; delete[] buf; buf = NULL; return retColor; }