예제 #1
0
Vector Raytracer::shade(Ray const &ray,
                        int &rayDepth,
                        Intersection const &intersection,
                        Material const &material,
                        Scene const &scene)
{
    // - iterate over all lights, calculating ambient/diffuse/specular contribution
    // - use shadow rays to determine shadows
    // - integrate the contributions of each light
    // - include emission of the surface material
    // - call Raytracer::trace for reflection/refraction colors
    // Don't reflect/refract if maximum ray recursion depth has been reached!
    //!!! USEFUL NOTES: attenuate factor = 1.0 / (a0 + a1 * d + a2 * d * d)..., ambient light doesn't attenuate, nor does it affected by shadow
    //!!! USEFUL NOTES: don't accept shadow intersection far away than the light position
    //!!! USEFUL NOTES: for each kind of ray, i.e. shadow ray, reflected ray, and primary ray, the accepted furthest depth are different
    Vector diffuse(0);
    Vector ambient(0);
    Vector specular(0);
    
    Vector v = -ray.direction.normalized();
    Vector n = intersection.normal.normalized();
    Vector reflect = (-v + 2 * v.dot(n) * n).normalized();
    
    for (auto lightIter = scene.lights.begin(); lightIter != scene.lights.end(); lightIter++)
    {
        // @@@@@@ YOUR CODE HERE
        // calculate local illumination here, remember to add all the lights together
        // also test shadow here, if a point is in shadow, multiply its diffuse and specular color by (1 - material.shadow)
        Vector l = (lightIter->position - intersection.position).normalized();
        Vector r = (-l + 2 * n.dot(l)*n).normalized();
        Vector view = (scene.camera.position - intersection.position).normalized();
        
        double d = //(intersection.position - ray.origin).length()+
        (lightIter->position - intersection.position).length();
        double attenuation = 1.0 / (lightIter->ambient[0] + d*lightIter->attenuation[1]
                                    +d *d*lightIter->attenuation[2]);
        
        Ray shadowRay = Ray(intersection.position + (lightIter->position - intersection.position).normalized()* 1e-6,(lightIter->position - intersection.position).normalized());
        Intersection hit = intersection;
        bool isShadow = false;
        
        Vector delAmbient = material.ambient * lightIter->ambient;
        Vector delDiffuse = material.diffuse * lightIter->diffuse * max(0.0, n.dot(l))
        * attenuation;
        Vector delSpecular = material.specular * lightIter->specular *
        pow(max(0.0, r.dot(view)), material.shininess) * attenuation;
        
        
        
        for (int x = 0; x< scene.objects.size(); x++) {
            if (scene.objects[x]->intersect(shadowRay, hit)) {
                isShadow = true;
            }
        }
        
        
        if (isShadow) {
            ambient += delAmbient;
            diffuse += delDiffuse * (1 - material.shadow);
            specular += delSpecular * (1 - material.shadow);
        }
        else {
            ambient += delAmbient;
            diffuse += delDiffuse;
            specular += delSpecular;
        }
    }
    
    Vector reflectedLight(0);
    if ((!(ABS_FLOAT(material.reflect) < 1e-6)) && (rayDepth < MAX_RAY_RECURSION))
    {
        // @@@@@@ YOUR CODE HERE
        // calculate reflected color using trace() recursively
        Ray reflect_ray(intersection.position + reflect*1e-6, reflect);
        double depth = DBL_MAX;
        trace(reflect_ray, rayDepth, scene, reflectedLight, depth);
        
    }
    
    return material.emission + ambient + diffuse + specular + material.reflect * reflectedLight;
}
예제 #2
0
Vector Raytracer::shade(Ray const &ray,
                 int &rayDepth,
                 Intersection const &intersection,
                 Material const &material,
                 Scene const &scene)
{
    // - iterate over all lights, calculating ambient/diffuse/specular contribution
    // - use shadow rays to determine shadows
    // - integrate the contributions of each light
    // - include emission of the surface material
    // - call Raytracer::trace for reflection/refraction colors
    // Don't reflect/refract if maximum ray recursion depth has been reached!
	//!!! USEFUL NOTES: attenuate factor = 1.0 / (a0 + a1 * d + a2 * d * d)..., ambient light doesn't attenuate, nor does it affected by shadow
	//!!! USEFUL NOTES: don't accept shadow intersection far away than the light position
	//!!! USEFUL NOTES: for each kind of ray, i.e. shadow ray, reflected ray, and primary ray, the accepted furthest depth are different
	Vector diffuse(0);
	Vector ambient(0);
	Vector specular(0);
	Vector refractedLight(0);
	    
    for (auto lightIter = scene.lights.begin(); lightIter != scene.lights.end(); lightIter++)
	{
		// calculate local illumination here, remember to add all the lights together
		// also test shadow here, if a point is in shadow, multiply its diffuse and specular color by (1 - material.shadow)
		
		Vector newAmbient = (lightIter->ambient * material.ambient);
		
		Vector normalI = intersection.normal.normalized();
		Vector incomingLight = (lightIter->position - intersection.position).normalized();
				
		float diffuseDot = max(normalI.dot(incomingLight), 0.0);
		Vector newDiffuse = (diffuseDot * material.diffuse * lightIter->diffuse);
		
		
		Vector reflectedLight = (-2 * (incomingLight.dot(normalI))* normalI + incomingLight).normalized();
		Vector viewVector = ray.direction.normalized();
		
		float specularDot = max(viewVector.dot(reflectedLight), 0.0);
		Vector newSpecular = (pow(specularDot, material.shininess) * material.specular * lightIter->specular);
		
        // create shadow ray
        
		Intersection shdHit;
        Ray shadowRay = Ray((intersection.position + (incomingLight * 0.000001)), incomingLight);
        double lightDist = (lightIter->position - intersection.position).length();
        shdHit.depth = lightDist;
		bool hitShadow = false;
        
        for(auto it = scene.objects.begin(); it != scene.objects.end(); ++ it) {
            Object * curObj = *it;
            
            if (curObj->intersect(shadowRay, shdHit)) {
				hitShadow = true;
            }
        }
        
        
        double attFactor = (lightIter->attenuation[0] + lightIter->attenuation[1] * lightDist + lightIter->attenuation[2] * lightDist * lightDist);
        
        if (hitShadow) {
            newSpecular = newSpecular * (1 - material.shadow);
            newDiffuse = newDiffuse * (1 - material.shadow);
        }
        
        newSpecular = newSpecular / attFactor;
        newDiffuse = newDiffuse  / attFactor;
        
        specular += newSpecular;
        ambient += newAmbient;
        diffuse += newDiffuse;
        
		
	}

	Vector reflectedLight(0);
	if ((!(ABS_FLOAT(material.reflect) < 1e-6)) && (rayDepth < MAX_RAY_RECURSION))
	{
		if (!ray.refracting) { //inside a refracting object
            // calculate reflected color using trace() recursively
            Vector normalI = intersection.normal.normalized();
            Vector reflectedDir = (-2 * (ray.direction.dot(normalI))* normalI + ray.direction).normalized();
            Ray reflectRay = Ray((intersection.position + (reflectedDir * 0.000001)), reflectedDir);
            double superdepth = DBL_MAX;
            trace(reflectRay, rayDepth, scene, reflectedLight, superdepth);
        }
	}
    
    if ((!(ABS_FLOAT(material.refract) < 1e-6)) && (rayDepth < MAX_RAY_RECURSION)) {
        
        Vector normalI = intersection.normal.normalized();
        
        double refractn = 1.0;
        if (ray.refracting) { //inside a refracting object
            refractn = material.rfrIndex / 1.0;
        } else { 
            refractn = 1.0 / material.rfrIndex;
        }
        double cosI = normalI.dot(ray.direction);
        double sinT2 = refractn * refractn * (1.0 - cosI * cosI);
        if (sinT2 <= 1.0)
        {
            Vector refractDir = refractn * ray.direction - (refractn + sqrt(1.0 - sinT2)) * normalI;
            Ray refractRay = Ray((intersection.position + (refractDir * 0.001)), refractDir, !(ray.refracting));
            double superdepth = DBL_MAX;
            trace(refractRay, rayDepth, scene, refractedLight, superdepth);
        }
	}

	return material.emission + ambient + diffuse + specular + material.reflect * reflectedLight + material.refract * refractedLight;
}